1#![allow(rustc::diagnostic_outside_of_impl)]
2#![allow(rustc::untranslatable_diagnostic)]
3
4use std::fmt::{self, Display};
5use std::iter;
6
7use rustc_data_structures::fx::IndexEntry;
8use rustc_errors::{Diag, EmissionGuarantee};
9use rustc_hir as hir;
10use rustc_hir::def::{DefKind, Res};
11use rustc_middle::ty::print::RegionHighlightMode;
12use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, RegionVid, Ty};
13use rustc_middle::{bug, span_bug};
14use rustc_span::{DUMMY_SP, Span, Symbol, kw, sym};
15use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
16use tracing::{debug, instrument};
17
18use crate::MirBorrowckCtxt;
19use crate::universal_regions::DefiningTy;
20
21#[derive(Debug, Clone, Copy)]
24pub(crate) struct RegionName {
25 pub(crate) name: Symbol,
27 pub(crate) source: RegionNameSource,
29}
30
31#[derive(Debug, Clone, Copy)]
35pub(crate) enum RegionNameSource {
36 NamedEarlyParamRegion(Span),
38 NamedLateParamRegion(Span),
40 Static,
42 SynthesizedFreeEnvRegion(Span, &'static str),
44 AnonRegionFromArgument(RegionNameHighlight),
46 AnonRegionFromUpvar(Span, Symbol),
48 AnonRegionFromOutput(RegionNameHighlight, &'static str),
50 AnonRegionFromYieldTy(Span, Symbol),
52 AnonRegionFromAsyncFn(Span),
54 AnonRegionFromImplSignature(Span, &'static str),
56}
57
58#[derive(Debug, Clone, Copy)]
61pub(crate) enum RegionNameHighlight {
62 MatchedHirTy(Span),
64 MatchedAdtAndSegment(Span),
66 CannotMatchHirTy(Span, Symbol),
69 Occluded(Span, Symbol),
73}
74
75impl RegionName {
76 pub(crate) fn was_named(&self) -> bool {
77 match self.source {
78 RegionNameSource::NamedEarlyParamRegion(..)
79 | RegionNameSource::NamedLateParamRegion(..)
80 | RegionNameSource::Static => true,
81 RegionNameSource::SynthesizedFreeEnvRegion(..)
82 | RegionNameSource::AnonRegionFromArgument(..)
83 | RegionNameSource::AnonRegionFromUpvar(..)
84 | RegionNameSource::AnonRegionFromOutput(..)
85 | RegionNameSource::AnonRegionFromYieldTy(..)
86 | RegionNameSource::AnonRegionFromAsyncFn(..)
87 | RegionNameSource::AnonRegionFromImplSignature(..) => false,
88 }
89 }
90
91 pub(crate) fn span(&self) -> Option<Span> {
92 match self.source {
93 RegionNameSource::Static => None,
94 RegionNameSource::NamedEarlyParamRegion(span)
95 | RegionNameSource::NamedLateParamRegion(span)
96 | RegionNameSource::SynthesizedFreeEnvRegion(span, _)
97 | RegionNameSource::AnonRegionFromUpvar(span, _)
98 | RegionNameSource::AnonRegionFromYieldTy(span, _)
99 | RegionNameSource::AnonRegionFromAsyncFn(span)
100 | RegionNameSource::AnonRegionFromImplSignature(span, _) => Some(span),
101 RegionNameSource::AnonRegionFromArgument(ref highlight)
102 | RegionNameSource::AnonRegionFromOutput(ref highlight, _) => match *highlight {
103 RegionNameHighlight::MatchedHirTy(span)
104 | RegionNameHighlight::MatchedAdtAndSegment(span)
105 | RegionNameHighlight::CannotMatchHirTy(span, _)
106 | RegionNameHighlight::Occluded(span, _) => Some(span),
107 },
108 }
109 }
110
111 pub(crate) fn highlight_region_name<G: EmissionGuarantee>(&self, diag: &mut Diag<'_, G>) {
112 match &self.source {
113 RegionNameSource::NamedLateParamRegion(span)
114 | RegionNameSource::NamedEarlyParamRegion(span) => {
115 diag.span_label(*span, format!("lifetime `{self}` defined here"));
116 }
117 RegionNameSource::SynthesizedFreeEnvRegion(span, note) => {
118 diag.span_label(*span, format!("lifetime `{self}` represents this closure's body"));
119 diag.note(*note);
120 }
121 RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::CannotMatchHirTy(
122 span,
123 type_name,
124 )) => {
125 diag.span_label(*span, format!("has type `{type_name}`"));
126 }
127 RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::MatchedHirTy(span))
128 | RegionNameSource::AnonRegionFromOutput(RegionNameHighlight::MatchedHirTy(span), _)
129 | RegionNameSource::AnonRegionFromAsyncFn(span) => {
130 diag.span_label(
131 *span,
132 format!("let's call the lifetime of this reference `{self}`"),
133 );
134 }
135 RegionNameSource::AnonRegionFromArgument(
136 RegionNameHighlight::MatchedAdtAndSegment(span),
137 )
138 | RegionNameSource::AnonRegionFromOutput(
139 RegionNameHighlight::MatchedAdtAndSegment(span),
140 _,
141 ) => {
142 diag.span_label(*span, format!("let's call this `{self}`"));
143 }
144 RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::Occluded(
145 span,
146 type_name,
147 )) => {
148 diag.span_label(
149 *span,
150 format!("lifetime `{self}` appears in the type {type_name}"),
151 );
152 }
153 RegionNameSource::AnonRegionFromOutput(
154 RegionNameHighlight::Occluded(span, type_name),
155 mir_description,
156 ) => {
157 diag.span_label(
158 *span,
159 format!(
160 "return type{mir_description} `{type_name}` contains a lifetime `{self}`"
161 ),
162 );
163 }
164 RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => {
165 diag.span_label(
166 *span,
167 format!("lifetime `{self}` appears in the type of `{upvar_name}`"),
168 );
169 }
170 RegionNameSource::AnonRegionFromOutput(
171 RegionNameHighlight::CannotMatchHirTy(span, type_name),
172 mir_description,
173 ) => {
174 diag.span_label(*span, format!("return type{mir_description} is {type_name}"));
175 }
176 RegionNameSource::AnonRegionFromYieldTy(span, type_name) => {
177 diag.span_label(*span, format!("yield type is {type_name}"));
178 }
179 RegionNameSource::AnonRegionFromImplSignature(span, location) => {
180 diag.span_label(
181 *span,
182 format!("lifetime `{self}` appears in the `impl`'s {location}"),
183 );
184 }
185 RegionNameSource::Static => {}
186 }
187 }
188}
189
190impl Display for RegionName {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 write!(f, "{}", self.name)
193 }
194}
195
196impl rustc_errors::IntoDiagArg for RegionName {
197 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
198 self.to_string().into_diag_arg(path)
199 }
200}
201
202impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
203 pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
204 self.body.source.def_id().expect_local()
205 }
206
207 pub(crate) fn mir_hir_id(&self) -> hir::HirId {
208 self.infcx.tcx.local_def_id_to_hir_id(self.mir_def_id())
209 }
210
211 pub(crate) fn synthesize_region_name(&self) -> Symbol {
216 let c = self.next_region_name.replace_with(|counter| *counter + 1);
217 Symbol::intern(&format!("'{c:?}"))
218 }
219
220 pub(crate) fn give_region_a_name(&self, fr: RegionVid) -> Option<RegionName> {
248 debug!(
249 "give_region_a_name(fr={:?}, counter={:?})",
250 fr,
251 self.next_region_name.try_borrow().unwrap()
252 );
253
254 assert!(self.regioncx.universal_regions().is_universal_region(fr));
255
256 match self.region_names.borrow_mut().entry(fr) {
257 IndexEntry::Occupied(precomputed_name) => Some(*precomputed_name.get()),
258 IndexEntry::Vacant(slot) => {
259 let new_name = self
260 .give_name_from_error_region(fr)
261 .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr))
262 .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
263 .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
264 .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr))
265 .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
266 .or_else(|| {
267 self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr)
268 });
269
270 if let Some(new_name) = new_name {
271 slot.insert(new_name);
272 }
273 debug!("give_region_a_name: gave name {:?}", new_name);
274
275 new_name
276 }
277 }
278 }
279
280 #[instrument(level = "trace", skip(self))]
285 fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
286 let error_region = self.to_error_region(fr)?;
287
288 let tcx = self.infcx.tcx;
289
290 debug!("give_region_a_name: error_region = {:?}", error_region);
291 match *error_region {
292 ty::ReEarlyParam(ebr) => ebr.has_name().then(|| {
293 let def_id = tcx.generics_of(self.mir_def_id()).region_param(ebr, tcx).def_id;
294 let span = tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
295 RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyParamRegion(span) }
296 }),
297
298 ty::ReStatic => {
299 Some(RegionName { name: kw::StaticLifetime, source: RegionNameSource::Static })
300 }
301
302 ty::ReLateParam(late_param) => match late_param.kind {
303 ty::LateParamRegionKind::Named(region_def_id, name) => {
304 let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP);
306 debug!(
307 "bound region named: {:?}, is_named: {:?}",
308 name,
309 late_param.kind.is_named()
310 );
311
312 if late_param.kind.is_named() {
313 Some(RegionName {
315 name,
316 source: RegionNameSource::NamedLateParamRegion(span),
317 })
318 } else if tcx.asyncness(self.mir_hir_id().owner).is_async() {
319 let name = self.synthesize_region_name();
325 Some(RegionName {
326 name,
327 source: RegionNameSource::AnonRegionFromAsyncFn(span),
328 })
329 } else {
330 None
331 }
332 }
333
334 ty::LateParamRegionKind::ClosureEnv => {
335 let def_ty = self.regioncx.universal_regions().defining_ty;
336
337 let closure_kind = match def_ty {
338 DefiningTy::Closure(_, args) => args.as_closure().kind(),
339 DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().kind(),
340 _ => {
341 bug!("BrEnv outside of closure.");
343 }
344 };
345 let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) =
346 tcx.hir_expect_expr(self.mir_hir_id()).kind
347 else {
348 bug!("Closure is not defined by a closure expr");
349 };
350 let region_name = self.synthesize_region_name();
351 let note = match closure_kind {
352 ty::ClosureKind::Fn => {
353 "closure implements `Fn`, so references to captured variables \
354 can't escape the closure"
355 }
356 ty::ClosureKind::FnMut => {
357 "closure implements `FnMut`, so references to captured variables \
358 can't escape the closure"
359 }
360 ty::ClosureKind::FnOnce => {
361 bug!("BrEnv in a `FnOnce` closure");
362 }
363 };
364
365 Some(RegionName {
366 name: region_name,
367 source: RegionNameSource::SynthesizedFreeEnvRegion(fn_decl_span, note),
368 })
369 }
370
371 ty::LateParamRegionKind::Anon(_) => None,
372 },
373
374 ty::ReBound(..)
375 | ty::ReVar(..)
376 | ty::RePlaceholder(..)
377 | ty::ReErased
378 | ty::ReError(_) => None,
379 }
380 }
381
382 #[instrument(level = "trace", skip(self))]
391 fn give_name_if_anonymous_region_appears_in_arguments(
392 &self,
393 fr: RegionVid,
394 ) -> Option<RegionName> {
395 let implicit_inputs = self.regioncx.universal_regions().defining_ty.implicit_inputs();
396 let argument_index = self.regioncx.get_argument_index_for_region(self.infcx.tcx, fr)?;
397
398 let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys
399 [implicit_inputs + argument_index];
400 let (_, span) = self.regioncx.get_argument_name_and_span_for_region(
401 self.body,
402 &self.local_names,
403 argument_index,
404 );
405
406 let highlight = self
407 .get_argument_hir_ty_for_highlighting(argument_index)
408 .and_then(|arg_hir_ty| self.highlight_if_we_can_match_hir_ty(fr, arg_ty, arg_hir_ty))
409 .unwrap_or_else(|| {
410 let counter = *self.next_region_name.try_borrow().unwrap();
414 self.highlight_if_we_cannot_match_hir_ty(fr, arg_ty, span, counter)
415 });
416
417 Some(RegionName {
418 name: self.synthesize_region_name(),
419 source: RegionNameSource::AnonRegionFromArgument(highlight),
420 })
421 }
422
423 fn get_argument_hir_ty_for_highlighting(
424 &self,
425 argument_index: usize,
426 ) -> Option<&hir::Ty<'tcx>> {
427 let fn_decl = self.infcx.tcx.hir_fn_decl_by_hir_id(self.mir_hir_id())?;
428 let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
429 match argument_hir_ty.kind {
430 hir::TyKind::Infer(()) => None,
436
437 _ => Some(argument_hir_ty),
438 }
439 }
440
441 fn highlight_if_we_cannot_match_hir_ty(
453 &self,
454 needle_fr: RegionVid,
455 ty: Ty<'tcx>,
456 span: Span,
457 counter: usize,
458 ) -> RegionNameHighlight {
459 let mut highlight = RegionHighlightMode::default();
460 highlight.highlighting_region_vid(self.infcx.tcx, needle_fr, counter);
461 let type_name =
462 self.infcx.err_ctxt().extract_inference_diagnostics_data(ty.into(), highlight).name;
463
464 debug!(
465 "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
466 type_name, needle_fr
467 );
468 if type_name.contains(&format!("'{counter}")) {
469 RegionNameHighlight::CannotMatchHirTy(span, Symbol::intern(&type_name))
471 } else {
472 RegionNameHighlight::Occluded(span, Symbol::intern(&type_name))
473 }
474 }
475
476 fn highlight_if_we_can_match_hir_ty(
498 &self,
499 needle_fr: RegionVid,
500 ty: Ty<'tcx>,
501 hir_ty: &hir::Ty<'_>,
502 ) -> Option<RegionNameHighlight> {
503 let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> = &mut vec![(ty, hir_ty)];
504
505 while let Some((ty, hir_ty)) = search_stack.pop() {
506 match (ty.kind(), &hir_ty.kind) {
507 (ty::Ref(region, referent_ty, _), hir::TyKind::Ref(_lifetime, referent_hir_ty)) => {
514 if region.as_var() == needle_fr {
515 let source_map = self.infcx.tcx.sess.source_map();
517 let ampersand_span = source_map.start_point(hir_ty.span);
518
519 return Some(RegionNameHighlight::MatchedHirTy(ampersand_span));
520 }
521
522 search_stack.push((*referent_ty, referent_hir_ty.ty));
524 }
525
526 (ty::Adt(_adt_def, args), hir::TyKind::Path(hir::QPath::Resolved(None, path))) => {
528 match path.res {
529 Res::Def(DefKind::TyAlias, _) => (),
534 _ => {
535 if let Some(last_segment) = path.segments.last() {
536 if let Some(highlight) = self.match_adt_and_segment(
537 args,
538 needle_fr,
539 last_segment,
540 search_stack,
541 ) {
542 return Some(highlight);
543 }
544 }
545 }
546 }
547 }
548
549 (&ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => {
553 search_stack.extend(iter::zip(elem_tys, *elem_hir_tys));
554 }
555
556 (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty))
557 | (ty::Array(elem_ty, _), hir::TyKind::Array(elem_hir_ty, _)) => {
558 search_stack.push((*elem_ty, elem_hir_ty));
559 }
560
561 (ty::RawPtr(mut_ty, _), hir::TyKind::Ptr(mut_hir_ty)) => {
562 search_stack.push((*mut_ty, mut_hir_ty.ty));
563 }
564
565 _ => {
566 }
568 }
569 }
570
571 None
572 }
573
574 fn match_adt_and_segment<'hir>(
580 &self,
581 args: GenericArgsRef<'tcx>,
582 needle_fr: RegionVid,
583 last_segment: &'hir hir::PathSegment<'hir>,
584 search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
585 ) -> Option<RegionNameHighlight> {
586 let explicit_args = last_segment.args.as_ref()?;
588 let lifetime =
589 self.try_match_adt_and_generic_args(args, needle_fr, explicit_args, search_stack)?;
590 if lifetime.is_anonymous() {
591 None
592 } else {
593 Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime.ident.span))
594 }
595 }
596
597 fn try_match_adt_and_generic_args<'hir>(
603 &self,
604 args: GenericArgsRef<'tcx>,
605 needle_fr: RegionVid,
606 hir_args: &'hir hir::GenericArgs<'hir>,
607 search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
608 ) -> Option<&'hir hir::Lifetime> {
609 for (kind, hir_arg) in iter::zip(args, hir_args.args) {
610 match (kind.unpack(), hir_arg) {
611 (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => {
612 if r.as_var() == needle_fr {
613 return Some(lt);
614 }
615 }
616
617 (GenericArgKind::Type(ty), hir::GenericArg::Type(hir_ty)) => {
618 search_stack.push((ty, hir_ty.as_unambig_ty()));
619 }
620
621 (GenericArgKind::Const(_ct), hir::GenericArg::Const(_hir_ct)) => {
622 }
625
626 (
627 GenericArgKind::Lifetime(_)
628 | GenericArgKind::Type(_)
629 | GenericArgKind::Const(_),
630 _,
631 ) => {
632 self.dcx().span_delayed_bug(
633 hir_arg.span(),
634 format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
635 );
636 }
637 }
638 }
639
640 None
641 }
642
643 #[instrument(level = "trace", skip(self))]
652 fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
653 let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
654 let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
655 self.infcx.tcx,
656 self.upvars,
657 upvar_index,
658 );
659 let region_name = self.synthesize_region_name();
660
661 Some(RegionName {
662 name: region_name,
663 source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
664 })
665 }
666
667 #[instrument(level = "trace", skip(self))]
672 fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
673 let tcx = self.infcx.tcx;
674
675 let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
676 debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
677 if !tcx.any_free_region_meets(&return_ty, |r| r.as_var() == fr) {
678 return None;
679 }
680
681 let mir_hir_id = self.mir_hir_id();
682
683 let (return_span, mir_description, hir_ty) = match tcx.hir_node(mir_hir_id) {
684 hir::Node::Expr(&hir::Expr {
685 kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, kind, fn_decl_span, .. }),
686 ..
687 }) => {
688 let (mut span, mut hir_ty) = match fn_decl.output {
689 hir::FnRetTy::DefaultReturn(_) => {
690 (tcx.sess.source_map().end_point(fn_decl_span), None)
691 }
692 hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
693 };
694 let mir_description = match kind {
695 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
696 hir::CoroutineDesugaring::Async,
697 hir::CoroutineSource::Block,
698 )) => " of async block",
699
700 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
701 hir::CoroutineDesugaring::Async,
702 hir::CoroutineSource::Closure,
703 ))
704 | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => {
705 " of async closure"
706 }
707
708 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
709 hir::CoroutineDesugaring::Async,
710 hir::CoroutineSource::Fn,
711 )) => {
712 let parent_item =
713 tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
714 let output = &parent_item
715 .fn_decl()
716 .expect("coroutine lowered from async fn should be in fn")
717 .output;
718 span = output.span();
719 if let hir::FnRetTy::Return(ret) = output {
720 hir_ty = Some(self.get_future_inner_return_ty(ret));
721 }
722 " of async function"
723 }
724
725 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
726 hir::CoroutineDesugaring::Gen,
727 hir::CoroutineSource::Block,
728 )) => " of gen block",
729
730 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
731 hir::CoroutineDesugaring::Gen,
732 hir::CoroutineSource::Closure,
733 ))
734 | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => {
735 " of gen closure"
736 }
737
738 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
739 hir::CoroutineDesugaring::Gen,
740 hir::CoroutineSource::Fn,
741 )) => {
742 let parent_item =
743 tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
744 let output = &parent_item
745 .fn_decl()
746 .expect("coroutine lowered from gen fn should be in fn")
747 .output;
748 span = output.span();
749 " of gen function"
750 }
751
752 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
753 hir::CoroutineDesugaring::AsyncGen,
754 hir::CoroutineSource::Block,
755 )) => " of async gen block",
756
757 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
758 hir::CoroutineDesugaring::AsyncGen,
759 hir::CoroutineSource::Closure,
760 ))
761 | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::AsyncGen) => {
762 " of async gen closure"
763 }
764
765 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
766 hir::CoroutineDesugaring::AsyncGen,
767 hir::CoroutineSource::Fn,
768 )) => {
769 let parent_item =
770 tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
771 let output = &parent_item
772 .fn_decl()
773 .expect("coroutine lowered from async gen fn should be in fn")
774 .output;
775 span = output.span();
776 " of async gen function"
777 }
778
779 hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) => {
780 " of coroutine"
781 }
782 hir::ClosureKind::Closure => " of closure",
783 };
784 (span, mir_description, hir_ty)
785 }
786 node => match node.fn_decl() {
787 Some(fn_decl) => {
788 let hir_ty = match fn_decl.output {
789 hir::FnRetTy::DefaultReturn(_) => None,
790 hir::FnRetTy::Return(ty) => Some(ty),
791 };
792 (fn_decl.output.span(), "", hir_ty)
793 }
794 None => (self.body.span, "", None),
795 },
796 };
797
798 let highlight = hir_ty
799 .and_then(|hir_ty| self.highlight_if_we_can_match_hir_ty(fr, return_ty, hir_ty))
800 .unwrap_or_else(|| {
801 let counter = *self.next_region_name.try_borrow().unwrap();
805 self.highlight_if_we_cannot_match_hir_ty(fr, return_ty, return_span, counter)
806 });
807
808 Some(RegionName {
809 name: self.synthesize_region_name(),
810 source: RegionNameSource::AnonRegionFromOutput(highlight, mir_description),
811 })
812 }
813
814 fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
828 let hir::TyKind::OpaqueDef(opaque_ty) = hir_ty.kind else {
829 span_bug!(
830 hir_ty.span,
831 "lowered return type of async fn is not OpaqueDef: {:?}",
832 hir_ty
833 );
834 };
835 if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref)], .. } = opaque_ty
836 && let Some(segment) = trait_ref.trait_ref.path.segments.last()
837 && let Some(args) = segment.args
838 && let [constraint] = args.constraints
839 && constraint.ident.name == sym::Output
840 && let Some(ty) = constraint.ty()
841 {
842 ty
843 } else {
844 span_bug!(
845 hir_ty.span,
846 "bounds from lowered return type of async fn did not match expected format: {opaque_ty:?}",
847 );
848 }
849 }
850
851 #[instrument(level = "trace", skip(self))]
852 fn give_name_if_anonymous_region_appears_in_yield_ty(
853 &self,
854 fr: RegionVid,
855 ) -> Option<RegionName> {
856 let yield_ty = self.regioncx.universal_regions().yield_ty?;
859 debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty);
860
861 let tcx = self.infcx.tcx;
862
863 if !tcx.any_free_region_meets(&yield_ty, |r| r.as_var() == fr) {
864 return None;
865 }
866
867 let mut highlight = RegionHighlightMode::default();
868 highlight.highlighting_region_vid(tcx, fr, *self.next_region_name.try_borrow().unwrap());
869 let type_name = self
870 .infcx
871 .err_ctxt()
872 .extract_inference_diagnostics_data(yield_ty.into(), highlight)
873 .name;
874
875 let yield_span = match tcx.hir_node(self.mir_hir_id()) {
876 hir::Node::Expr(&hir::Expr {
877 kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
878 ..
879 }) => tcx.sess.source_map().end_point(fn_decl_span),
880 _ => self.body.span,
881 };
882
883 debug!(
884 "give_name_if_anonymous_region_appears_in_yield_ty: \
885 type_name = {:?}, yield_span = {:?}",
886 yield_span, type_name,
887 );
888
889 Some(RegionName {
890 name: self.synthesize_region_name(),
891 source: RegionNameSource::AnonRegionFromYieldTy(yield_span, Symbol::intern(&type_name)),
892 })
893 }
894
895 fn give_name_if_anonymous_region_appears_in_impl_signature(
896 &self,
897 fr: RegionVid,
898 ) -> Option<RegionName> {
899 let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
900 return None;
901 };
902 if region.has_name() {
903 return None;
904 };
905
906 let tcx = self.infcx.tcx;
907 let region_def = tcx.generics_of(self.mir_def_id()).region_param(region, tcx).def_id;
908 let region_parent = tcx.parent(region_def);
909 let DefKind::Impl { .. } = tcx.def_kind(region_parent) else {
910 return None;
911 };
912
913 let found = tcx
914 .any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| {
915 *r == ty::ReEarlyParam(region)
916 });
917
918 Some(RegionName {
919 name: self.synthesize_region_name(),
920 source: RegionNameSource::AnonRegionFromImplSignature(
921 tcx.def_span(region_def),
922 if found { "self type" } else { "header" },
926 ),
927 })
928 }
929
930 fn give_name_if_anonymous_region_appears_in_arg_position_impl_trait(
931 &self,
932 fr: RegionVid,
933 ) -> Option<RegionName> {
934 let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
935 return None;
936 };
937 if region.has_name() {
938 return None;
939 };
940
941 let predicates = self
942 .infcx
943 .tcx
944 .predicates_of(self.body.source.def_id())
945 .instantiate_identity(self.infcx.tcx)
946 .predicates;
947
948 if let Some(upvar_index) = self
949 .regioncx
950 .universal_regions()
951 .defining_ty
952 .upvar_tys()
953 .iter()
954 .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
955 {
956 let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
957 self.infcx.tcx,
958 self.upvars,
959 upvar_index,
960 );
961 let region_name = self.synthesize_region_name();
962
963 Some(RegionName {
964 name: region_name,
965 source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
966 })
967 } else if let Some(arg_index) = self
968 .regioncx
969 .universal_regions()
970 .unnormalized_input_tys
971 .iter()
972 .position(|ty| self.any_param_predicate_mentions(&predicates, *ty, region))
973 {
974 let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
975 self.body,
976 &self.local_names,
977 arg_index,
978 );
979 let region_name = self.synthesize_region_name();
980
981 Some(RegionName {
982 name: region_name,
983 source: RegionNameSource::AnonRegionFromArgument(
984 RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?),
985 ),
986 })
987 } else {
988 None
989 }
990 }
991
992 fn any_param_predicate_mentions(
993 &self,
994 clauses: &[ty::Clause<'tcx>],
995 ty: Ty<'tcx>,
996 region: ty::EarlyParamRegion,
997 ) -> bool {
998 let tcx = self.infcx.tcx;
999 ty.walk().any(|arg| {
1000 if let ty::GenericArgKind::Type(ty) = arg.unpack()
1001 && let ty::Param(_) = ty.kind()
1002 {
1003 clauses.iter().any(|pred| {
1004 match pred.kind().skip_binder() {
1005 ty::ClauseKind::Trait(data) if data.self_ty() == ty => {}
1006 ty::ClauseKind::Projection(data)
1007 if data.projection_term.self_ty() == ty => {}
1008 _ => return false,
1009 }
1010 tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyParam(region))
1011 })
1012 } else {
1013 false
1014 }
1015 })
1016 }
1017}