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) -> rustc_errors::DiagArgValue {
198 self.to_string().into_diag_arg()
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 let hir = tcx.hir();
675
676 let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
677 debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
678 if !tcx.any_free_region_meets(&return_ty, |r| r.as_var() == fr) {
679 return None;
680 }
681
682 let mir_hir_id = self.mir_hir_id();
683
684 let (return_span, mir_description, hir_ty) = match tcx.hir_node(mir_hir_id) {
685 hir::Node::Expr(hir::Expr {
686 kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, kind, fn_decl_span, .. }),
687 ..
688 }) => {
689 let (mut span, mut hir_ty) = match fn_decl.output {
690 hir::FnRetTy::DefaultReturn(_) => {
691 (tcx.sess.source_map().end_point(fn_decl_span), None)
692 }
693 hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
694 };
695 let mir_description = match kind {
696 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
697 hir::CoroutineDesugaring::Async,
698 hir::CoroutineSource::Block,
699 )) => " of async block",
700
701 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
702 hir::CoroutineDesugaring::Async,
703 hir::CoroutineSource::Closure,
704 ))
705 | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => {
706 " of async closure"
707 }
708
709 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
710 hir::CoroutineDesugaring::Async,
711 hir::CoroutineSource::Fn,
712 )) => {
713 let parent_item =
714 tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
715 let output = &parent_item
716 .fn_decl()
717 .expect("coroutine lowered from async fn should be in fn")
718 .output;
719 span = output.span();
720 if let hir::FnRetTy::Return(ret) = output {
721 hir_ty = Some(self.get_future_inner_return_ty(ret));
722 }
723 " of async function"
724 }
725
726 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
727 hir::CoroutineDesugaring::Gen,
728 hir::CoroutineSource::Block,
729 )) => " of gen block",
730
731 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
732 hir::CoroutineDesugaring::Gen,
733 hir::CoroutineSource::Closure,
734 ))
735 | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => {
736 " of gen closure"
737 }
738
739 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
740 hir::CoroutineDesugaring::Gen,
741 hir::CoroutineSource::Fn,
742 )) => {
743 let parent_item =
744 tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
745 let output = &parent_item
746 .fn_decl()
747 .expect("coroutine lowered from gen fn should be in fn")
748 .output;
749 span = output.span();
750 " of gen function"
751 }
752
753 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
754 hir::CoroutineDesugaring::AsyncGen,
755 hir::CoroutineSource::Block,
756 )) => " of async gen block",
757
758 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
759 hir::CoroutineDesugaring::AsyncGen,
760 hir::CoroutineSource::Closure,
761 ))
762 | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::AsyncGen) => {
763 " of async gen closure"
764 }
765
766 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
767 hir::CoroutineDesugaring::AsyncGen,
768 hir::CoroutineSource::Fn,
769 )) => {
770 let parent_item =
771 tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
772 let output = &parent_item
773 .fn_decl()
774 .expect("coroutine lowered from async gen fn should be in fn")
775 .output;
776 span = output.span();
777 " of async gen function"
778 }
779
780 hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) => {
781 " of coroutine"
782 }
783 hir::ClosureKind::Closure => " of closure",
784 };
785 (span, mir_description, hir_ty)
786 }
787 node => match node.fn_decl() {
788 Some(fn_decl) => {
789 let hir_ty = match fn_decl.output {
790 hir::FnRetTy::DefaultReturn(_) => None,
791 hir::FnRetTy::Return(ty) => Some(ty),
792 };
793 (fn_decl.output.span(), "", hir_ty)
794 }
795 None => (self.body.span, "", None),
796 },
797 };
798
799 let highlight = hir_ty
800 .and_then(|hir_ty| self.highlight_if_we_can_match_hir_ty(fr, return_ty, hir_ty))
801 .unwrap_or_else(|| {
802 let counter = *self.next_region_name.try_borrow().unwrap();
806 self.highlight_if_we_cannot_match_hir_ty(fr, return_ty, return_span, counter)
807 });
808
809 Some(RegionName {
810 name: self.synthesize_region_name(),
811 source: RegionNameSource::AnonRegionFromOutput(highlight, mir_description),
812 })
813 }
814
815 fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
829 let hir::TyKind::OpaqueDef(opaque_ty) = hir_ty.kind else {
830 span_bug!(
831 hir_ty.span,
832 "lowered return type of async fn is not OpaqueDef: {:?}",
833 hir_ty
834 );
835 };
836 if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref)], .. } = opaque_ty
837 && let Some(segment) = trait_ref.trait_ref.path.segments.last()
838 && let Some(args) = segment.args
839 && let [constraint] = args.constraints
840 && constraint.ident.name == sym::Output
841 && let Some(ty) = constraint.ty()
842 {
843 ty
844 } else {
845 span_bug!(
846 hir_ty.span,
847 "bounds from lowered return type of async fn did not match expected format: {opaque_ty:?}",
848 );
849 }
850 }
851
852 #[instrument(level = "trace", skip(self))]
853 fn give_name_if_anonymous_region_appears_in_yield_ty(
854 &self,
855 fr: RegionVid,
856 ) -> Option<RegionName> {
857 let yield_ty = self.regioncx.universal_regions().yield_ty?;
860 debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty);
861
862 let tcx = self.infcx.tcx;
863
864 if !tcx.any_free_region_meets(&yield_ty, |r| r.as_var() == fr) {
865 return None;
866 }
867
868 let mut highlight = RegionHighlightMode::default();
869 highlight.highlighting_region_vid(tcx, fr, *self.next_region_name.try_borrow().unwrap());
870 let type_name = self
871 .infcx
872 .err_ctxt()
873 .extract_inference_diagnostics_data(yield_ty.into(), highlight)
874 .name;
875
876 let yield_span = match tcx.hir_node(self.mir_hir_id()) {
877 hir::Node::Expr(hir::Expr {
878 kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
879 ..
880 }) => tcx.sess.source_map().end_point(fn_decl_span),
881 _ => self.body.span,
882 };
883
884 debug!(
885 "give_name_if_anonymous_region_appears_in_yield_ty: \
886 type_name = {:?}, yield_span = {:?}",
887 yield_span, type_name,
888 );
889
890 Some(RegionName {
891 name: self.synthesize_region_name(),
892 source: RegionNameSource::AnonRegionFromYieldTy(yield_span, Symbol::intern(&type_name)),
893 })
894 }
895
896 fn give_name_if_anonymous_region_appears_in_impl_signature(
897 &self,
898 fr: RegionVid,
899 ) -> Option<RegionName> {
900 let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
901 return None;
902 };
903 if region.has_name() {
904 return None;
905 };
906
907 let tcx = self.infcx.tcx;
908 let region_def = tcx.generics_of(self.mir_def_id()).region_param(region, tcx).def_id;
909 let region_parent = tcx.parent(region_def);
910 let DefKind::Impl { .. } = tcx.def_kind(region_parent) else {
911 return None;
912 };
913
914 let found = tcx
915 .any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| {
916 *r == ty::ReEarlyParam(region)
917 });
918
919 Some(RegionName {
920 name: self.synthesize_region_name(),
921 source: RegionNameSource::AnonRegionFromImplSignature(
922 tcx.def_span(region_def),
923 if found { "self type" } else { "header" },
927 ),
928 })
929 }
930
931 fn give_name_if_anonymous_region_appears_in_arg_position_impl_trait(
932 &self,
933 fr: RegionVid,
934 ) -> Option<RegionName> {
935 let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
936 return None;
937 };
938 if region.has_name() {
939 return None;
940 };
941
942 let predicates = self
943 .infcx
944 .tcx
945 .predicates_of(self.body.source.def_id())
946 .instantiate_identity(self.infcx.tcx)
947 .predicates;
948
949 if let Some(upvar_index) = self
950 .regioncx
951 .universal_regions()
952 .defining_ty
953 .upvar_tys()
954 .iter()
955 .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
956 {
957 let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
958 self.infcx.tcx,
959 self.upvars,
960 upvar_index,
961 );
962 let region_name = self.synthesize_region_name();
963
964 Some(RegionName {
965 name: region_name,
966 source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
967 })
968 } else if let Some(arg_index) = self
969 .regioncx
970 .universal_regions()
971 .unnormalized_input_tys
972 .iter()
973 .position(|ty| self.any_param_predicate_mentions(&predicates, *ty, region))
974 {
975 let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
976 self.body,
977 &self.local_names,
978 arg_index,
979 );
980 let region_name = self.synthesize_region_name();
981
982 Some(RegionName {
983 name: region_name,
984 source: RegionNameSource::AnonRegionFromArgument(
985 RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?),
986 ),
987 })
988 } else {
989 None
990 }
991 }
992
993 fn any_param_predicate_mentions(
994 &self,
995 clauses: &[ty::Clause<'tcx>],
996 ty: Ty<'tcx>,
997 region: ty::EarlyParamRegion,
998 ) -> bool {
999 let tcx = self.infcx.tcx;
1000 ty.walk().any(|arg| {
1001 if let ty::GenericArgKind::Type(ty) = arg.unpack()
1002 && let ty::Param(_) = ty.kind()
1003 {
1004 clauses.iter().any(|pred| {
1005 match pred.kind().skip_binder() {
1006 ty::ClauseKind::Trait(data) if data.self_ty() == ty => {}
1007 ty::ClauseKind::Projection(data)
1008 if data.projection_term.self_ty() == ty => {}
1009 _ => return false,
1010 }
1011 tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyParam(region))
1012 })
1013 } else {
1014 false
1015 }
1016 })
1017 }
1018}