@@ -6,8 +6,8 @@ use rustc_hir::def::{DefKind, Res};
6
6
use rustc_middle:: ty:: print:: RegionHighlightMode ;
7
7
use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
8
8
use 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 } ;
11
11
12
12
use crate :: borrow_check:: { nll:: ToRegionVid , universal_regions:: DefiningTy , MirBorrowckCtxt } ;
13
13
@@ -39,7 +39,7 @@ crate enum RegionNameSource {
39
39
/// The region corresponding to a closure upvar.
40
40
AnonRegionFromUpvar ( Span , String ) ,
41
41
/// The region corresponding to the return type of a closure.
42
- AnonRegionFromOutput ( Span , String , String ) ,
42
+ AnonRegionFromOutput ( RegionNameHighlight , String ) ,
43
43
/// The region from a type yielded by a generator.
44
44
AnonRegionFromYieldTy ( Span , String ) ,
45
45
/// An anonymous region from an async fn.
@@ -85,10 +85,10 @@ impl RegionName {
85
85
| RegionNameSource :: NamedFreeRegion ( span)
86
86
| RegionNameSource :: SynthesizedFreeEnvRegion ( span, _)
87
87
| RegionNameSource :: AnonRegionFromUpvar ( span, _)
88
- | RegionNameSource :: AnonRegionFromOutput ( span, _, _)
89
88
| RegionNameSource :: AnonRegionFromYieldTy ( span, _)
90
89
| RegionNameSource :: AnonRegionFromAsyncFn ( span) => Some ( span) ,
91
- RegionNameSource :: AnonRegionFromArgument ( ref highlight) => match * highlight {
90
+ RegionNameSource :: AnonRegionFromArgument ( ref highlight)
91
+ | RegionNameSource :: AnonRegionFromOutput ( ref highlight, _) => match * highlight {
92
92
RegionNameHighlight :: MatchedHirTy ( span)
93
93
| RegionNameHighlight :: MatchedAdtAndSegment ( span)
94
94
| RegionNameHighlight :: CannotMatchHirTy ( span, _)
@@ -117,6 +117,7 @@ impl RegionName {
117
117
diag. span_label ( * span, format ! ( "has type `{}`" , type_name) ) ;
118
118
}
119
119
RegionNameSource :: AnonRegionFromArgument ( RegionNameHighlight :: MatchedHirTy ( span) )
120
+ | RegionNameSource :: AnonRegionFromOutput ( RegionNameHighlight :: MatchedHirTy ( span) , _)
120
121
| RegionNameSource :: AnonRegionFromAsyncFn ( span) => {
121
122
diag. span_label (
122
123
* span,
@@ -125,6 +126,10 @@ impl RegionName {
125
126
}
126
127
RegionNameSource :: AnonRegionFromArgument (
127
128
RegionNameHighlight :: MatchedAdtAndSegment ( span) ,
129
+ )
130
+ | RegionNameSource :: AnonRegionFromOutput (
131
+ RegionNameHighlight :: MatchedAdtAndSegment ( span) ,
132
+ _,
128
133
) => {
129
134
diag. span_label ( * span, format ! ( "let's call this `{}`" , self ) ) ;
130
135
}
@@ -137,13 +142,28 @@ impl RegionName {
137
142
format ! ( "lifetime `{}` appears in the type {}" , self , type_name) ,
138
143
) ;
139
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
+ }
140
157
RegionNameSource :: AnonRegionFromUpvar ( span, upvar_name) => {
141
158
diag. span_label (
142
159
* span,
143
160
format ! ( "lifetime `{}` appears in the type of `{}`" , self , upvar_name) ,
144
161
) ;
145
162
}
146
- RegionNameSource :: AnonRegionFromOutput ( span, mir_description, type_name) => {
163
+ RegionNameSource :: AnonRegionFromOutput (
164
+ RegionNameHighlight :: CannotMatchHirTy ( span, type_name) ,
165
+ mir_description,
166
+ ) => {
147
167
diag. span_label ( * span, format ! ( "return type{} is {}" , mir_description, type_name) ) ;
148
168
}
149
169
RegionNameSource :: AnonRegionFromYieldTy ( span, type_name) => {
@@ -659,67 +679,131 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
659
679
/// or be early bound (named, not in argument).
660
680
fn give_name_if_anonymous_region_appears_in_output ( & self , fr : RegionVid ) -> Option < RegionName > {
661
681
let tcx = self . infcx . tcx ;
682
+ let hir = tcx. hir ( ) ;
662
683
663
684
let return_ty = self . regioncx . universal_regions ( ) . unnormalized_output_ty ;
664
685
debug ! ( "give_name_if_anonymous_region_appears_in_output: return_ty = {:?}" , return_ty) ;
665
686
if !tcx. any_free_region_meets ( & return_ty, |r| r. to_region_vid ( ) == fr) {
666
687
return None ;
667
688
}
668
689
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 ( ) ;
673
691
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) {
675
693
hir:: Node :: Expr ( hir:: Expr {
676
694
kind : hir:: ExprKind :: Closure ( _, return_ty, body_id, span, _) ,
677
695
..
678
696
} ) => {
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) ) ,
682
702
} ;
683
- let mir_description = match tcx . hir ( ) . body ( * body_id) . generator_kind {
703
+ let mir_description = match hir. body ( * body_id) . generator_kind {
684
704
Some ( hir:: GeneratorKind :: Async ( gen) ) => match gen {
685
705
hir:: AsyncGeneratorKind :: Block => " of async block" ,
686
706
hir:: AsyncGeneratorKind :: Closure => " of async closure" ,
687
707
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
691
710
. fn_decl ( )
692
711
. 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
+ }
695
717
" of async function"
696
718
}
697
719
} ,
698
720
Some ( hir:: GeneratorKind :: Gen ) => " of generator" ,
699
721
None => " of closure" ,
700
722
} ;
701
- ( span, mir_description)
723
+ ( span, mir_description, hir_ty )
702
724
}
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
+ } ,
708
735
} ;
709
736
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
+
710
747
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.
714
748
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 ( ) ) ,
720
750
} )
721
751
}
722
752
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
+
723
807
fn give_name_if_anonymous_region_appears_in_yield_ty (
724
808
& self ,
725
809
fr : RegionVid ,
0 commit comments