@@ -6,8 +6,8 @@ use rustc_hir::def::{DefKind, Res};
66use rustc_middle::ty::print::RegionHighlightMode;
77use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
88use rustc_middle::ty::{self, RegionVid, Ty};
9- use rustc_span::symbol::kw ;
10- use rustc_span::{symbol::Symbol, Span, DUMMY_SP};
9+ use rustc_span::symbol::{kw, sym, Ident, Symbol} ;
10+ use rustc_span::{Span, DUMMY_SP};
1111
1212use crate::borrow_check::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt};
1313
@@ -39,7 +39,7 @@ crate enum RegionNameSource {
3939 /// The region corresponding to a closure upvar.
4040 AnonRegionFromUpvar(Span, String),
4141 /// The region corresponding to the return type of a closure.
42- AnonRegionFromOutput(Span, String , String),
42+ AnonRegionFromOutput(RegionNameHighlight , String),
4343 /// The region from a type yielded by a generator.
4444 AnonRegionFromYieldTy(Span, String),
4545 /// An anonymous region from an async fn.
@@ -85,10 +85,10 @@ impl RegionName {
8585 | RegionNameSource::NamedFreeRegion(span)
8686 | RegionNameSource::SynthesizedFreeEnvRegion(span, _)
8787 | RegionNameSource::AnonRegionFromUpvar(span, _)
88- | RegionNameSource::AnonRegionFromOutput(span, _, _)
8988 | RegionNameSource::AnonRegionFromYieldTy(span, _)
9089 | RegionNameSource::AnonRegionFromAsyncFn(span) => Some(span),
91- RegionNameSource::AnonRegionFromArgument(ref highlight) => match *highlight {
90+ RegionNameSource::AnonRegionFromArgument(ref highlight)
91+ | RegionNameSource::AnonRegionFromOutput(ref highlight, _) => match *highlight {
9292 RegionNameHighlight::MatchedHirTy(span)
9393 | RegionNameHighlight::MatchedAdtAndSegment(span)
9494 | RegionNameHighlight::CannotMatchHirTy(span, _)
@@ -117,6 +117,7 @@ impl RegionName {
117117 diag.span_label(*span, format!("has type `{}`", type_name));
118118 }
119119 RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::MatchedHirTy(span))
120+ | RegionNameSource::AnonRegionFromOutput(RegionNameHighlight::MatchedHirTy(span), _)
120121 | RegionNameSource::AnonRegionFromAsyncFn(span) => {
121122 diag.span_label(
122123 *span,
@@ -125,6 +126,10 @@ impl RegionName {
125126 }
126127 RegionNameSource::AnonRegionFromArgument(
127128 RegionNameHighlight::MatchedAdtAndSegment(span),
129+ )
130+ | RegionNameSource::AnonRegionFromOutput(
131+ RegionNameHighlight::MatchedAdtAndSegment(span),
132+ _,
128133 ) => {
129134 diag.span_label(*span, format!("let's call this `{}`", self));
130135 }
@@ -137,13 +142,28 @@ impl RegionName {
137142 format!("lifetime `{}` appears in the type {}", self, type_name),
138143 );
139144 }
145+ RegionNameSource::AnonRegionFromOutput(
146+ RegionNameHighlight::Occluded(span, type_name),
147+ mir_description,
148+ ) => {
149+ diag.span_label(
150+ *span,
151+ format!(
152+ "return type{} `{}` contains a lifetime `{}`",
153+ mir_description, type_name, self
154+ ),
155+ );
156+ }
140157 RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => {
141158 diag.span_label(
142159 *span,
143160 format!("lifetime `{}` appears in the type of `{}`", self, upvar_name),
144161 );
145162 }
146- RegionNameSource::AnonRegionFromOutput(span, mir_description, type_name) => {
163+ RegionNameSource::AnonRegionFromOutput(
164+ RegionNameHighlight::CannotMatchHirTy(span, type_name),
165+ mir_description,
166+ ) => {
147167 diag.span_label(*span, format!("return type{} is {}", mir_description, type_name));
148168 }
149169 RegionNameSource::AnonRegionFromYieldTy(span, type_name) => {
@@ -659,67 +679,131 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
659679 /// or be early bound (named, not in argument).
660680 fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
661681 let tcx = self.infcx.tcx;
682+ let hir = tcx.hir();
662683
663684 let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
664685 debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
665686 if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) {
666687 return None;
667688 }
668689
669- let mut highlight = RegionHighlightMode::default();
670- highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
671- let type_name =
672- self.infcx.extract_inference_diagnostics_data(return_ty.into(), Some(highlight)).name;
690+ let mir_hir_id = self.mir_hir_id();
673691
674- let (return_span, mir_description) = match tcx. hir() .get(self. mir_hir_id() ) {
692+ let (return_span, mir_description, hir_ty ) = match hir.get(mir_hir_id) {
675693 hir::Node::Expr(hir::Expr {
676694 kind: hir::ExprKind::Closure(_, return_ty, body_id, span, _),
677695 ..
678696 }) => {
679- let mut span = match return_ty.output {
680- hir::FnRetTy::DefaultReturn(_) => tcx.sess.source_map().end_point(*span),
681- hir::FnRetTy::Return(_) => return_ty.output.span(),
697+ let (mut span, mut hir_ty) = match return_ty.output {
698+ hir::FnRetTy::DefaultReturn(_) => {
699+ (tcx.sess.source_map().end_point(*span), None)
700+ }
701+ hir::FnRetTy::Return(hir_ty) => (return_ty.output.span(), Some(hir_ty)),
682702 };
683- let mir_description = match tcx. hir() .body(*body_id).generator_kind {
703+ let mir_description = match hir.body(*body_id).generator_kind {
684704 Some(hir::GeneratorKind::Async(gen)) => match gen {
685705 hir::AsyncGeneratorKind::Block => " of async block",
686706 hir::AsyncGeneratorKind::Closure => " of async closure",
687707 hir::AsyncGeneratorKind::Fn => {
688- span = tcx
689- .hir()
690- .get(tcx.hir().get_parent_item(mir_hir_id))
708+ let parent_item = hir.get(hir.get_parent_item(mir_hir_id));
709+ let output = &parent_item
691710 .fn_decl()
692711 .expect("generator lowered from async fn should be in fn")
693- .output
694- .span();
712+ .output;
713+ span = output.span();
714+ if let hir::FnRetTy::Return(ret) = output {
715+ hir_ty = Some(self.get_future_inner_return_ty(*ret));
716+ }
695717 " of async function"
696718 }
697719 },
698720 Some(hir::GeneratorKind::Gen) => " of generator",
699721 None => " of closure",
700722 };
701- (span, mir_description)
723+ (span, mir_description, hir_ty )
702724 }
703- hir::Node::ImplItem(hir::ImplItem {
704- kind: hir::ImplItemKind::Fn(method_sig, _),
705- ..
706- }) => (method_sig.decl.output.span(), ""),
707- _ => (self.body.span, ""),
725+ node => match node.fn_decl() {
726+ Some(fn_decl) => {
727+ let hir_ty = match fn_decl.output {
728+ hir::FnRetTy::DefaultReturn(_) => None,
729+ hir::FnRetTy::Return(ty) => Some(ty),
730+ };
731+ (fn_decl.output.span(), "", hir_ty)
732+ }
733+ None => (self.body.span, "", None),
734+ },
708735 };
709736
737+ let highlight = hir_ty
738+ .and_then(|hir_ty| self.highlight_if_we_can_match_hir_ty(fr, return_ty, hir_ty))
739+ .unwrap_or_else(|| {
740+ // `highlight_if_we_cannot_match_hir_ty` needs to know the number we will give to
741+ // the anonymous region. If it succeeds, the `synthesize_region_name` call below
742+ // will increment the counter, "reserving" the number we just used.
743+ let counter = *self.next_region_name.try_borrow().unwrap();
744+ self.highlight_if_we_cannot_match_hir_ty(fr, return_ty, return_span, counter)
745+ });
746+
710747 Some(RegionName {
711- // This counter value will already have been used, so this function will increment it
712- // so the next value will be used next and return the region name that would have been
713- // used.
714748 name: self.synthesize_region_name(),
715- source: RegionNameSource::AnonRegionFromOutput(
716- return_span,
717- mir_description.to_string(),
718- type_name,
719- ),
749+ source: RegionNameSource::AnonRegionFromOutput(highlight, mir_description.to_string()),
720750 })
721751 }
722752
753+ /// From the [`hir::Ty`] of an async function's lowered return type,
754+ /// retrieve the `hir::Ty` representing the type the user originally wrote.
755+ ///
756+ /// e.g. given the function:
757+ ///
758+ /// ```
759+ /// async fn foo() -> i32 {}
760+ /// ```
761+ ///
762+ /// this function, given the lowered return type of `foo`, an [`OpaqueDef`] that implements `Future<Output=i32>`,
763+ /// returns the `i32`.
764+ ///
765+ /// [`OpaqueDef`]: hir::TyKind::OpaqueDef
766+ fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
767+ let hir = self.infcx.tcx.hir();
768+
769+ if let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind {
770+ let opaque_ty = hir.item(id.id);
771+ if let hir::ItemKind::OpaqueTy(hir::OpaqueTy {
772+ bounds:
773+ [hir::GenericBound::LangItemTrait(
774+ hir::LangItem::Future,
775+ _,
776+ _,
777+ hir::GenericArgs {
778+ bindings:
779+ [hir::TypeBinding {
780+ ident: Ident { name: sym::Output, .. },
781+ kind: hir::TypeBindingKind::Equality { ty },
782+ ..
783+ }],
784+ ..
785+ },
786+ )],
787+ ..
788+ }) = opaque_ty.kind
789+ {
790+ ty
791+ } else {
792+ span_bug!(
793+ hir_ty.span,
794+ "bounds from lowered return type of async fn did not match expected format: {:?}",
795+ opaque_ty
796+ );
797+ }
798+ } else {
799+ span_bug!(
800+ hir_ty.span,
801+ "lowered return type of async fn is not OpaqueDef: {:?}",
802+ hir_ty
803+ );
804+ }
805+ }
806+
723807 fn give_name_if_anonymous_region_appears_in_yield_ty(
724808 &self,
725809 fr: RegionVid,
0 commit comments