@@ -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.
@@ -57,6 +57,10 @@ crate enum RegionNameHighlight {
57
57
/// The anonymous region corresponds to a region where the type annotation is completely missing
58
58
/// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference.
59
59
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 ) ,
60
64
}
61
65
62
66
impl RegionName {
@@ -81,13 +85,14 @@ impl RegionName {
81
85
| RegionNameSource :: NamedFreeRegion ( span)
82
86
| RegionNameSource :: SynthesizedFreeEnvRegion ( span, _)
83
87
| RegionNameSource :: AnonRegionFromUpvar ( span, _)
84
- | RegionNameSource :: AnonRegionFromOutput ( span, _, _)
85
88
| RegionNameSource :: AnonRegionFromYieldTy ( span, _)
86
89
| RegionNameSource :: AnonRegionFromAsyncFn ( span) => Some ( span) ,
87
- RegionNameSource :: AnonRegionFromArgument ( ref highlight) => match * highlight {
90
+ RegionNameSource :: AnonRegionFromArgument ( ref highlight)
91
+ | RegionNameSource :: AnonRegionFromOutput ( ref highlight, _) => match * highlight {
88
92
RegionNameHighlight :: MatchedHirTy ( span)
89
93
| RegionNameHighlight :: MatchedAdtAndSegment ( span)
90
- | RegionNameHighlight :: CannotMatchHirTy ( span, _) => Some ( span) ,
94
+ | RegionNameHighlight :: CannotMatchHirTy ( span, _)
95
+ | RegionNameHighlight :: Occluded ( span, _) => Some ( span) ,
91
96
} ,
92
97
}
93
98
}
@@ -112,6 +117,7 @@ impl RegionName {
112
117
diag. span_label ( * span, format ! ( "has type `{}`" , type_name) ) ;
113
118
}
114
119
RegionNameSource :: AnonRegionFromArgument ( RegionNameHighlight :: MatchedHirTy ( span) )
120
+ | RegionNameSource :: AnonRegionFromOutput ( RegionNameHighlight :: MatchedHirTy ( span) , _)
115
121
| RegionNameSource :: AnonRegionFromAsyncFn ( span) => {
116
122
diag. span_label (
117
123
* span,
@@ -120,16 +126,44 @@ impl RegionName {
120
126
}
121
127
RegionNameSource :: AnonRegionFromArgument (
122
128
RegionNameHighlight :: MatchedAdtAndSegment ( span) ,
129
+ )
130
+ | RegionNameSource :: AnonRegionFromOutput (
131
+ RegionNameHighlight :: MatchedAdtAndSegment ( span) ,
132
+ _,
123
133
) => {
124
134
diag. span_label ( * span, format ! ( "let's call this `{}`" , self ) ) ;
125
135
}
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
+ }
126
157
RegionNameSource :: AnonRegionFromUpvar ( span, upvar_name) => {
127
158
diag. span_label (
128
159
* span,
129
160
format ! ( "lifetime `{}` appears in the type of `{}`" , self , upvar_name) ,
130
161
) ;
131
162
}
132
- RegionNameSource :: AnonRegionFromOutput ( span, mir_description, type_name) => {
163
+ RegionNameSource :: AnonRegionFromOutput (
164
+ RegionNameHighlight :: CannotMatchHirTy ( span, type_name) ,
165
+ mir_description,
166
+ ) => {
133
167
diag. span_label ( * span, format ! ( "return type{} is {}" , mir_description, type_name) ) ;
134
168
}
135
169
RegionNameSource :: AnonRegionFromYieldTy ( span, type_name) => {
@@ -349,19 +383,21 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
349
383
argument_index,
350
384
) ;
351
385
352
- self . get_argument_hir_ty_for_highlighting ( argument_index)
386
+ let highlight = self
387
+ . get_argument_hir_ty_for_highlighting ( argument_index)
353
388
. 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 ( || {
355
390
// `highlight_if_we_cannot_match_hir_ty` needs to know the number we will give to
356
391
// the anonymous region. If it succeeds, the `synthesize_region_name` call below
357
392
// will increment the counter, "reserving" the number we just used.
358
393
let counter = * self . next_region_name . try_borrow ( ) . unwrap ( ) ;
359
394
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
+ } )
365
401
}
366
402
367
403
fn get_argument_hir_ty_for_highlighting (
@@ -399,7 +435,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
399
435
ty : Ty < ' tcx > ,
400
436
span : Span ,
401
437
counter : usize ,
402
- ) -> Option < RegionNameHighlight > {
438
+ ) -> RegionNameHighlight {
403
439
let mut highlight = RegionHighlightMode :: default ( ) ;
404
440
highlight. highlighting_region_vid ( needle_fr, counter) ;
405
441
let type_name =
@@ -411,9 +447,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
411
447
) ;
412
448
if type_name. find ( & format ! ( "'{}" , counter) ) . is_some ( ) {
413
449
// 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)
415
451
} else {
416
- None
452
+ RegionNameHighlight :: Occluded ( span , type_name )
417
453
}
418
454
}
419
455
@@ -643,49 +679,131 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
643
679
/// or be early bound (named, not in argument).
644
680
fn give_name_if_anonymous_region_appears_in_output ( & self , fr : RegionVid ) -> Option < RegionName > {
645
681
let tcx = self . infcx . tcx ;
682
+ let hir = tcx. hir ( ) ;
646
683
647
684
let return_ty = self . regioncx . universal_regions ( ) . unnormalized_output_ty ;
648
685
debug ! ( "give_name_if_anonymous_region_appears_in_output: return_ty = {:?}" , return_ty) ;
649
686
if !tcx. any_free_region_meets ( & return_ty, |r| r. to_region_vid ( ) == fr) {
650
687
return None ;
651
688
}
652
689
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 ( ) ;
657
691
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) {
659
693
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, _) ,
671
695
..
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
+ } ,
674
735
} ;
675
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
+
676
747
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.
680
748
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 ( ) ) ,
686
750
} )
687
751
}
688
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
+
689
807
fn give_name_if_anonymous_region_appears_in_yield_ty (
690
808
& self ,
691
809
fr : RegionVid ,
0 commit comments