@@ -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.
@@ -57,6 +57,10 @@ crate enum RegionNameHighlight {
5757 /// The anonymous region corresponds to a region where the type annotation is completely missing
5858 /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference.
5959 CannotMatchHirTy ( Span , String ) ,
60+ /// The anonymous region corresponds to a region where the type annotation is completely missing
61+ /// from the code, and *even if* we print out the full name of the type, the region name won't
62+ /// be included. This currently occurs for opaque types like `impl Future`.
63+ Occluded ( Span , String ) ,
6064}
6165
6266impl RegionName {
@@ -81,13 +85,14 @@ impl RegionName {
8185 | RegionNameSource :: NamedFreeRegion ( span)
8286 | RegionNameSource :: SynthesizedFreeEnvRegion ( span, _)
8387 | RegionNameSource :: AnonRegionFromUpvar ( span, _)
84- | RegionNameSource :: AnonRegionFromOutput ( span, _, _)
8588 | RegionNameSource :: AnonRegionFromYieldTy ( span, _)
8689 | RegionNameSource :: AnonRegionFromAsyncFn ( span) => Some ( span) ,
87- RegionNameSource :: AnonRegionFromArgument ( ref highlight) => match * highlight {
90+ RegionNameSource :: AnonRegionFromArgument ( ref highlight)
91+ | RegionNameSource :: AnonRegionFromOutput ( ref highlight, _) => match * highlight {
8892 RegionNameHighlight :: MatchedHirTy ( span)
8993 | RegionNameHighlight :: MatchedAdtAndSegment ( span)
90- | RegionNameHighlight :: CannotMatchHirTy ( span, _) => Some ( span) ,
94+ | RegionNameHighlight :: CannotMatchHirTy ( span, _)
95+ | RegionNameHighlight :: Occluded ( span, _) => Some ( span) ,
9196 } ,
9297 }
9398 }
@@ -112,6 +117,7 @@ impl RegionName {
112117 diag. span_label ( * span, format ! ( "has type `{}`" , type_name) ) ;
113118 }
114119 RegionNameSource :: AnonRegionFromArgument ( RegionNameHighlight :: MatchedHirTy ( span) )
120+ | RegionNameSource :: AnonRegionFromOutput ( RegionNameHighlight :: MatchedHirTy ( span) , _)
115121 | RegionNameSource :: AnonRegionFromAsyncFn ( span) => {
116122 diag. span_label (
117123 * span,
@@ -120,16 +126,44 @@ impl RegionName {
120126 }
121127 RegionNameSource :: AnonRegionFromArgument (
122128 RegionNameHighlight :: MatchedAdtAndSegment ( span) ,
129+ )
130+ | RegionNameSource :: AnonRegionFromOutput (
131+ RegionNameHighlight :: MatchedAdtAndSegment ( span) ,
132+ _,
123133 ) => {
124134 diag. span_label ( * span, format ! ( "let's call this `{}`" , self ) ) ;
125135 }
136+ RegionNameSource :: AnonRegionFromArgument ( RegionNameHighlight :: Occluded (
137+ span,
138+ type_name,
139+ ) ) => {
140+ diag. span_label (
141+ * span,
142+ format ! ( "lifetime `{}` appears in the type {}" , self , type_name) ,
143+ ) ;
144+ }
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+ }
126157 RegionNameSource :: AnonRegionFromUpvar ( span, upvar_name) => {
127158 diag. span_label (
128159 * span,
129160 format ! ( "lifetime `{}` appears in the type of `{}`" , self , upvar_name) ,
130161 ) ;
131162 }
132- RegionNameSource :: AnonRegionFromOutput ( span, mir_description, type_name) => {
163+ RegionNameSource :: AnonRegionFromOutput (
164+ RegionNameHighlight :: CannotMatchHirTy ( span, type_name) ,
165+ mir_description,
166+ ) => {
133167 diag. span_label ( * span, format ! ( "return type{} is {}" , mir_description, type_name) ) ;
134168 }
135169 RegionNameSource :: AnonRegionFromYieldTy ( span, type_name) => {
@@ -349,19 +383,21 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
349383 argument_index,
350384 ) ;
351385
352- self . get_argument_hir_ty_for_highlighting ( argument_index)
386+ let highlight = self
387+ . get_argument_hir_ty_for_highlighting ( argument_index)
353388 . and_then ( |arg_hir_ty| self . highlight_if_we_can_match_hir_ty ( fr, arg_ty, arg_hir_ty) )
354- . or_else ( || {
389+ . unwrap_or_else ( || {
355390 // `highlight_if_we_cannot_match_hir_ty` needs to know the number we will give to
356391 // the anonymous region. If it succeeds, the `synthesize_region_name` call below
357392 // will increment the counter, "reserving" the number we just used.
358393 let counter = * self . next_region_name . try_borrow ( ) . unwrap ( ) ;
359394 self . highlight_if_we_cannot_match_hir_ty ( fr, arg_ty, span, counter)
360- } )
361- . map ( |highlight| RegionName {
362- name : self . synthesize_region_name ( ) ,
363- source : RegionNameSource :: AnonRegionFromArgument ( highlight) ,
364- } )
395+ } ) ;
396+
397+ Some ( RegionName {
398+ name : self . synthesize_region_name ( ) ,
399+ source : RegionNameSource :: AnonRegionFromArgument ( highlight) ,
400+ } )
365401 }
366402
367403 fn get_argument_hir_ty_for_highlighting (
@@ -399,7 +435,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
399435 ty : Ty < ' tcx > ,
400436 span : Span ,
401437 counter : usize ,
402- ) -> Option < RegionNameHighlight > {
438+ ) -> RegionNameHighlight {
403439 let mut highlight = RegionHighlightMode :: default ( ) ;
404440 highlight. highlighting_region_vid ( needle_fr, counter) ;
405441 let type_name =
@@ -411,9 +447,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
411447 ) ;
412448 if type_name. find ( & format ! ( "'{}" , counter) ) . is_some ( ) {
413449 // Only add a label if we can confirm that a region was labelled.
414- Some ( RegionNameHighlight :: CannotMatchHirTy ( span, type_name) )
450+ RegionNameHighlight :: CannotMatchHirTy ( span, type_name)
415451 } else {
416- None
452+ RegionNameHighlight :: Occluded ( span , type_name )
417453 }
418454 }
419455
@@ -643,49 +679,131 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
643679 /// or be early bound (named, not in argument).
644680 fn give_name_if_anonymous_region_appears_in_output ( & self , fr : RegionVid ) -> Option < RegionName > {
645681 let tcx = self . infcx . tcx ;
682+ let hir = tcx. hir ( ) ;
646683
647684 let return_ty = self . regioncx . universal_regions ( ) . unnormalized_output_ty ;
648685 debug ! ( "give_name_if_anonymous_region_appears_in_output: return_ty = {:?}" , return_ty) ;
649686 if !tcx. any_free_region_meets ( & return_ty, |r| r. to_region_vid ( ) == fr) {
650687 return None ;
651688 }
652689
653- let mut highlight = RegionHighlightMode :: default ( ) ;
654- highlight. highlighting_region_vid ( fr, * self . next_region_name . try_borrow ( ) . unwrap ( ) ) ;
655- let type_name =
656- self . infcx . extract_inference_diagnostics_data ( return_ty. into ( ) , Some ( highlight) ) . name ;
690+ let mir_hir_id = self . mir_hir_id ( ) ;
657691
658- 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) {
659693 hir:: Node :: Expr ( hir:: Expr {
660- kind : hir:: ExprKind :: Closure ( _, return_ty, _, span, gen_move) ,
661- ..
662- } ) => (
663- match return_ty. output {
664- hir:: FnRetTy :: DefaultReturn ( _) => tcx. sess . source_map ( ) . end_point ( * span) ,
665- hir:: FnRetTy :: Return ( _) => return_ty. output . span ( ) ,
666- } ,
667- if gen_move. is_some ( ) { " of generator" } else { " of closure" } ,
668- ) ,
669- hir:: Node :: ImplItem ( hir:: ImplItem {
670- kind : hir:: ImplItemKind :: Fn ( method_sig, _) ,
694+ kind : hir:: ExprKind :: Closure ( _, return_ty, body_id, span, _) ,
671695 ..
672- } ) => ( method_sig. decl . output . span ( ) , "" ) ,
673- _ => ( self . body . span , "" ) ,
696+ } ) => {
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) ) ,
702+ } ;
703+ let mir_description = match hir. body ( * body_id) . generator_kind {
704+ Some ( hir:: GeneratorKind :: Async ( gen) ) => match gen {
705+ hir:: AsyncGeneratorKind :: Block => " of async block" ,
706+ hir:: AsyncGeneratorKind :: Closure => " of async closure" ,
707+ hir:: AsyncGeneratorKind :: Fn => {
708+ let parent_item = hir. get ( hir. get_parent_item ( mir_hir_id) ) ;
709+ let output = & parent_item
710+ . fn_decl ( )
711+ . expect ( "generator lowered from async fn should be in fn" )
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+ }
717+ " of async function"
718+ }
719+ } ,
720+ Some ( hir:: GeneratorKind :: Gen ) => " of generator" ,
721+ None => " of closure" ,
722+ } ;
723+ ( span, mir_description, hir_ty)
724+ }
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+ } ,
674735 } ;
675736
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+
676747 Some ( RegionName {
677- // This counter value will already have been used, so this function will increment it
678- // so the next value will be used next and return the region name that would have been
679- // used.
680748 name : self . synthesize_region_name ( ) ,
681- source : RegionNameSource :: AnonRegionFromOutput (
682- return_span,
683- mir_description. to_string ( ) ,
684- type_name,
685- ) ,
749+ source : RegionNameSource :: AnonRegionFromOutput ( highlight, mir_description. to_string ( ) ) ,
686750 } )
687751 }
688752
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+
689807 fn give_name_if_anonymous_region_appears_in_yield_ty (
690808 & self ,
691809 fr : RegionVid ,
0 commit comments