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.kind() {
292 ty::ReEarlyParam(ebr) => ebr.is_named().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) => {
304 let span = tcx.hir_span_if_local(region_def_id).unwrap_or(DUMMY_SP);
306
307 if let Some(name) = late_param.kind.get_name(tcx) {
308 Some(RegionName {
310 name,
311 source: RegionNameSource::NamedLateParamRegion(span),
312 })
313 } else if tcx.asyncness(self.mir_hir_id().owner).is_async() {
314 let name = self.synthesize_region_name();
320 Some(RegionName {
321 name,
322 source: RegionNameSource::AnonRegionFromAsyncFn(span),
323 })
324 } else {
325 None
326 }
327 }
328
329 ty::LateParamRegionKind::ClosureEnv => {
330 let def_ty = self.regioncx.universal_regions().defining_ty;
331
332 let closure_kind = match def_ty {
333 DefiningTy::Closure(_, args) => args.as_closure().kind(),
334 DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().kind(),
335 _ => {
336 bug!("BrEnv outside of closure.");
338 }
339 };
340 let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) =
341 tcx.hir_expect_expr(self.mir_hir_id()).kind
342 else {
343 bug!("Closure is not defined by a closure expr");
344 };
345 let region_name = self.synthesize_region_name();
346 let note = match closure_kind {
347 ty::ClosureKind::Fn => {
348 "closure implements `Fn`, so references to captured variables \
349 can't escape the closure"
350 }
351 ty::ClosureKind::FnMut => {
352 "closure implements `FnMut`, so references to captured variables \
353 can't escape the closure"
354 }
355 ty::ClosureKind::FnOnce => {
356 bug!("BrEnv in a `FnOnce` closure");
357 }
358 };
359
360 Some(RegionName {
361 name: region_name,
362 source: RegionNameSource::SynthesizedFreeEnvRegion(fn_decl_span, note),
363 })
364 }
365
366 ty::LateParamRegionKind::Anon(_) => None,
367 ty::LateParamRegionKind::NamedAnon(_, _) => bug!("only used for pretty printing"),
368 },
369
370 ty::ReBound(..)
371 | ty::ReVar(..)
372 | ty::RePlaceholder(..)
373 | ty::ReErased
374 | ty::ReError(_) => None,
375 }
376 }
377
378 #[instrument(level = "trace", skip(self))]
387 fn give_name_if_anonymous_region_appears_in_arguments(
388 &self,
389 fr: RegionVid,
390 ) -> Option<RegionName> {
391 let implicit_inputs = self.regioncx.universal_regions().defining_ty.implicit_inputs();
392 let argument_index = self.regioncx.get_argument_index_for_region(self.infcx.tcx, fr)?;
393
394 let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys
395 [implicit_inputs + argument_index];
396 let (_, span) = self.regioncx.get_argument_name_and_span_for_region(
397 self.body,
398 self.local_names(),
399 argument_index,
400 );
401
402 let highlight = self
403 .get_argument_hir_ty_for_highlighting(argument_index)
404 .and_then(|arg_hir_ty| self.highlight_if_we_can_match_hir_ty(fr, arg_ty, arg_hir_ty))
405 .unwrap_or_else(|| {
406 let counter = *self.next_region_name.try_borrow().unwrap();
410 self.highlight_if_we_cannot_match_hir_ty(fr, arg_ty, span, counter)
411 });
412
413 Some(RegionName {
414 name: self.synthesize_region_name(),
415 source: RegionNameSource::AnonRegionFromArgument(highlight),
416 })
417 }
418
419 fn get_argument_hir_ty_for_highlighting(
420 &self,
421 argument_index: usize,
422 ) -> Option<&hir::Ty<'tcx>> {
423 let fn_decl = self.infcx.tcx.hir_fn_decl_by_hir_id(self.mir_hir_id())?;
424 let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
425 match argument_hir_ty.kind {
426 hir::TyKind::Infer(()) => None,
432
433 _ => Some(argument_hir_ty),
434 }
435 }
436
437 fn highlight_if_we_cannot_match_hir_ty(
449 &self,
450 needle_fr: RegionVid,
451 ty: Ty<'tcx>,
452 span: Span,
453 counter: usize,
454 ) -> RegionNameHighlight {
455 let mut highlight = RegionHighlightMode::default();
456 highlight.highlighting_region_vid(self.infcx.tcx, needle_fr, counter);
457 let type_name =
458 self.infcx.err_ctxt().extract_inference_diagnostics_data(ty.into(), highlight).name;
459
460 debug!(
461 "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
462 type_name, needle_fr
463 );
464 if type_name.contains(&format!("'{counter}")) {
465 RegionNameHighlight::CannotMatchHirTy(span, Symbol::intern(&type_name))
467 } else {
468 RegionNameHighlight::Occluded(span, Symbol::intern(&type_name))
469 }
470 }
471
472 fn highlight_if_we_can_match_hir_ty(
494 &self,
495 needle_fr: RegionVid,
496 ty: Ty<'tcx>,
497 hir_ty: &hir::Ty<'_>,
498 ) -> Option<RegionNameHighlight> {
499 let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> = &mut vec![(ty, hir_ty)];
500
501 while let Some((ty, hir_ty)) = search_stack.pop() {
502 match (ty.kind(), &hir_ty.kind) {
503 (ty::Ref(region, referent_ty, _), hir::TyKind::Ref(_lifetime, referent_hir_ty)) => {
510 if region.as_var() == needle_fr {
511 let source_map = self.infcx.tcx.sess.source_map();
513 let ampersand_span = source_map.start_point(hir_ty.span);
514
515 return Some(RegionNameHighlight::MatchedHirTy(ampersand_span));
516 }
517
518 search_stack.push((*referent_ty, referent_hir_ty.ty));
520 }
521
522 (ty::Adt(_adt_def, args), hir::TyKind::Path(hir::QPath::Resolved(None, path))) => {
524 match path.res {
525 Res::Def(DefKind::TyAlias, _) => (),
530 _ => {
531 if let Some(last_segment) = path.segments.last() {
532 if let Some(highlight) = self.match_adt_and_segment(
533 args,
534 needle_fr,
535 last_segment,
536 search_stack,
537 ) {
538 return Some(highlight);
539 }
540 }
541 }
542 }
543 }
544
545 (&ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => {
549 search_stack.extend(iter::zip(elem_tys, *elem_hir_tys));
550 }
551
552 (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty))
553 | (ty::Array(elem_ty, _), hir::TyKind::Array(elem_hir_ty, _)) => {
554 search_stack.push((*elem_ty, elem_hir_ty));
555 }
556
557 (ty::RawPtr(mut_ty, _), hir::TyKind::Ptr(mut_hir_ty)) => {
558 search_stack.push((*mut_ty, mut_hir_ty.ty));
559 }
560
561 _ => {
562 }
564 }
565 }
566
567 None
568 }
569
570 fn match_adt_and_segment<'hir>(
576 &self,
577 args: GenericArgsRef<'tcx>,
578 needle_fr: RegionVid,
579 last_segment: &'hir hir::PathSegment<'hir>,
580 search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
581 ) -> Option<RegionNameHighlight> {
582 let explicit_args = last_segment.args.as_ref()?;
584 let lifetime =
585 self.try_match_adt_and_generic_args(args, needle_fr, explicit_args, search_stack)?;
586 if lifetime.is_anonymous() {
587 None
588 } else {
589 Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime.ident.span))
590 }
591 }
592
593 fn try_match_adt_and_generic_args<'hir>(
599 &self,
600 args: GenericArgsRef<'tcx>,
601 needle_fr: RegionVid,
602 hir_args: &'hir hir::GenericArgs<'hir>,
603 search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
604 ) -> Option<&'hir hir::Lifetime> {
605 for (arg, hir_arg) in iter::zip(args, hir_args.args) {
606 match (arg.kind(), hir_arg) {
607 (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => {
608 if r.as_var() == needle_fr {
609 return Some(lt);
610 }
611 }
612
613 (GenericArgKind::Type(ty), hir::GenericArg::Type(hir_ty)) => {
614 search_stack.push((ty, hir_ty.as_unambig_ty()));
615 }
616
617 (GenericArgKind::Const(_ct), hir::GenericArg::Const(_hir_ct)) => {
618 }
621
622 (
623 GenericArgKind::Lifetime(_)
624 | GenericArgKind::Type(_)
625 | GenericArgKind::Const(_),
626 _,
627 ) => {
628 self.dcx().span_delayed_bug(
629 hir_arg.span(),
630 format!("unmatched arg and hir arg: found {arg:?} vs {hir_arg:?}"),
631 );
632 }
633 }
634 }
635
636 None
637 }
638
639 #[instrument(level = "trace", skip(self))]
648 fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
649 let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
650 let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
651 self.infcx.tcx,
652 self.upvars,
653 upvar_index,
654 );
655 let region_name = self.synthesize_region_name();
656
657 Some(RegionName {
658 name: region_name,
659 source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
660 })
661 }
662
663 #[instrument(level = "trace", skip(self))]
668 fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
669 let tcx = self.infcx.tcx;
670
671 let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
672 debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
673 if !tcx.any_free_region_meets(&return_ty, |r| r.as_var() == fr) {
674 return None;
675 }
676
677 let mir_hir_id = self.mir_hir_id();
678
679 let (return_span, mir_description, hir_ty) = match tcx.hir_node(mir_hir_id) {
680 hir::Node::Expr(&hir::Expr {
681 kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, kind, fn_decl_span, .. }),
682 ..
683 }) => {
684 let (mut span, mut hir_ty) = match fn_decl.output {
685 hir::FnRetTy::DefaultReturn(_) => {
686 (tcx.sess.source_map().end_point(fn_decl_span), None)
687 }
688 hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
689 };
690 let mir_description = match kind {
691 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
692 hir::CoroutineDesugaring::Async,
693 hir::CoroutineSource::Block,
694 )) => " of async block",
695
696 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
697 hir::CoroutineDesugaring::Async,
698 hir::CoroutineSource::Closure,
699 ))
700 | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => {
701 " of async closure"
702 }
703
704 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
705 hir::CoroutineDesugaring::Async,
706 hir::CoroutineSource::Fn,
707 )) => {
708 let parent_item =
709 tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
710 let output = &parent_item
711 .fn_decl()
712 .expect("coroutine lowered from async fn should be in fn")
713 .output;
714 span = output.span();
715 if let hir::FnRetTy::Return(ret) = output {
716 hir_ty = Some(self.get_future_inner_return_ty(ret));
717 }
718 " of async function"
719 }
720
721 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
722 hir::CoroutineDesugaring::Gen,
723 hir::CoroutineSource::Block,
724 )) => " of gen block",
725
726 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
727 hir::CoroutineDesugaring::Gen,
728 hir::CoroutineSource::Closure,
729 ))
730 | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => {
731 " of gen closure"
732 }
733
734 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
735 hir::CoroutineDesugaring::Gen,
736 hir::CoroutineSource::Fn,
737 )) => {
738 let parent_item =
739 tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
740 let output = &parent_item
741 .fn_decl()
742 .expect("coroutine lowered from gen fn should be in fn")
743 .output;
744 span = output.span();
745 " of gen function"
746 }
747
748 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
749 hir::CoroutineDesugaring::AsyncGen,
750 hir::CoroutineSource::Block,
751 )) => " of async gen block",
752
753 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
754 hir::CoroutineDesugaring::AsyncGen,
755 hir::CoroutineSource::Closure,
756 ))
757 | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::AsyncGen) => {
758 " of async gen closure"
759 }
760
761 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
762 hir::CoroutineDesugaring::AsyncGen,
763 hir::CoroutineSource::Fn,
764 )) => {
765 let parent_item =
766 tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
767 let output = &parent_item
768 .fn_decl()
769 .expect("coroutine lowered from async gen fn should be in fn")
770 .output;
771 span = output.span();
772 " of async gen function"
773 }
774
775 hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) => {
776 " of coroutine"
777 }
778 hir::ClosureKind::Closure => " of closure",
779 };
780 (span, mir_description, hir_ty)
781 }
782 node => match node.fn_decl() {
783 Some(fn_decl) => {
784 let hir_ty = match fn_decl.output {
785 hir::FnRetTy::DefaultReturn(_) => None,
786 hir::FnRetTy::Return(ty) => Some(ty),
787 };
788 (fn_decl.output.span(), "", hir_ty)
789 }
790 None => (self.body.span, "", None),
791 },
792 };
793
794 let highlight = hir_ty
795 .and_then(|hir_ty| self.highlight_if_we_can_match_hir_ty(fr, return_ty, hir_ty))
796 .unwrap_or_else(|| {
797 let counter = *self.next_region_name.try_borrow().unwrap();
801 self.highlight_if_we_cannot_match_hir_ty(fr, return_ty, return_span, counter)
802 });
803
804 Some(RegionName {
805 name: self.synthesize_region_name(),
806 source: RegionNameSource::AnonRegionFromOutput(highlight, mir_description),
807 })
808 }
809
810 fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
824 let hir::TyKind::OpaqueDef(opaque_ty) = hir_ty.kind else {
825 span_bug!(
826 hir_ty.span,
827 "lowered return type of async fn is not OpaqueDef: {:?}",
828 hir_ty
829 );
830 };
831 if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref)], .. } = opaque_ty
832 && let Some(segment) = trait_ref.trait_ref.path.segments.last()
833 && let Some(args) = segment.args
834 && let [constraint] = args.constraints
835 && constraint.ident.name == sym::Output
836 && let Some(ty) = constraint.ty()
837 {
838 ty
839 } else {
840 span_bug!(
841 hir_ty.span,
842 "bounds from lowered return type of async fn did not match expected format: {opaque_ty:?}",
843 );
844 }
845 }
846
847 #[instrument(level = "trace", skip(self))]
848 fn give_name_if_anonymous_region_appears_in_yield_ty(
849 &self,
850 fr: RegionVid,
851 ) -> Option<RegionName> {
852 let yield_ty = self.regioncx.universal_regions().yield_ty?;
855 debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty);
856
857 let tcx = self.infcx.tcx;
858
859 if !tcx.any_free_region_meets(&yield_ty, |r| r.as_var() == fr) {
860 return None;
861 }
862
863 let mut highlight = RegionHighlightMode::default();
864 highlight.highlighting_region_vid(tcx, fr, *self.next_region_name.try_borrow().unwrap());
865 let type_name = self
866 .infcx
867 .err_ctxt()
868 .extract_inference_diagnostics_data(yield_ty.into(), highlight)
869 .name;
870
871 let yield_span = match tcx.hir_node(self.mir_hir_id()) {
872 hir::Node::Expr(&hir::Expr {
873 kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
874 ..
875 }) => tcx.sess.source_map().end_point(fn_decl_span),
876 _ => self.body.span,
877 };
878
879 debug!(
880 "give_name_if_anonymous_region_appears_in_yield_ty: \
881 type_name = {:?}, yield_span = {:?}",
882 yield_span, type_name,
883 );
884
885 Some(RegionName {
886 name: self.synthesize_region_name(),
887 source: RegionNameSource::AnonRegionFromYieldTy(yield_span, Symbol::intern(&type_name)),
888 })
889 }
890
891 fn give_name_if_anonymous_region_appears_in_impl_signature(
892 &self,
893 fr: RegionVid,
894 ) -> Option<RegionName> {
895 let ty::ReEarlyParam(region) = self.to_error_region(fr)?.kind() else {
896 return None;
897 };
898 if region.is_named() {
899 return None;
900 };
901
902 let tcx = self.infcx.tcx;
903 let region_def = tcx.generics_of(self.mir_def_id()).region_param(region, tcx).def_id;
904 let region_parent = tcx.parent(region_def);
905 let DefKind::Impl { .. } = tcx.def_kind(region_parent) else {
906 return None;
907 };
908
909 let found = tcx
910 .any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| {
911 r.kind() == ty::ReEarlyParam(region)
912 });
913
914 Some(RegionName {
915 name: self.synthesize_region_name(),
916 source: RegionNameSource::AnonRegionFromImplSignature(
917 tcx.def_span(region_def),
918 if found { "self type" } else { "header" },
922 ),
923 })
924 }
925
926 fn give_name_if_anonymous_region_appears_in_arg_position_impl_trait(
927 &self,
928 fr: RegionVid,
929 ) -> Option<RegionName> {
930 let ty::ReEarlyParam(region) = self.to_error_region(fr)?.kind() else {
931 return None;
932 };
933 if region.is_named() {
934 return None;
935 };
936
937 let predicates = self
938 .infcx
939 .tcx
940 .predicates_of(self.body.source.def_id())
941 .instantiate_identity(self.infcx.tcx)
942 .predicates;
943
944 if let Some(upvar_index) = self
945 .regioncx
946 .universal_regions()
947 .defining_ty
948 .upvar_tys()
949 .iter()
950 .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
951 {
952 let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
953 self.infcx.tcx,
954 self.upvars,
955 upvar_index,
956 );
957 let region_name = self.synthesize_region_name();
958
959 Some(RegionName {
960 name: region_name,
961 source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
962 })
963 } else if let Some(arg_index) = self
964 .regioncx
965 .universal_regions()
966 .unnormalized_input_tys
967 .iter()
968 .position(|ty| self.any_param_predicate_mentions(&predicates, *ty, region))
969 {
970 let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
971 self.body,
972 self.local_names(),
973 arg_index,
974 );
975 let region_name = self.synthesize_region_name();
976
977 Some(RegionName {
978 name: region_name,
979 source: RegionNameSource::AnonRegionFromArgument(
980 RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?),
981 ),
982 })
983 } else {
984 None
985 }
986 }
987
988 fn any_param_predicate_mentions(
989 &self,
990 clauses: &[ty::Clause<'tcx>],
991 ty: Ty<'tcx>,
992 region: ty::EarlyParamRegion,
993 ) -> bool {
994 let tcx = self.infcx.tcx;
995 ty.walk().any(|arg| {
996 if let ty::GenericArgKind::Type(ty) = arg.kind()
997 && let ty::Param(_) = ty.kind()
998 {
999 clauses.iter().any(|pred| {
1000 match pred.kind().skip_binder() {
1001 ty::ClauseKind::Trait(data) if data.self_ty() == ty => {}
1002 ty::ClauseKind::Projection(data)
1003 if data.projection_term.self_ty() == ty => {}
1004 _ => return false,
1005 }
1006 tcx.any_free_region_meets(pred, |r| r.kind() == ty::ReEarlyParam(region))
1007 })
1008 } else {
1009 false
1010 }
1011 })
1012 }
1013}