@@ -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