2
2
//! anonymous regions.
3
3
4
4
use crate :: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
5
+ use crate :: infer:: TyCtxt ;
5
6
use rustc_hir as hir;
6
7
use rustc_hir:: def_id:: LocalDefId ;
7
8
use rustc_middle:: ty:: { self , Binder , DefIdTree , Region , Ty , TypeFoldable } ;
8
9
use rustc_span:: Span ;
9
10
10
11
/// Information about the anonymous region we are searching for.
11
12
#[ derive( Debug ) ]
12
- pub ( super ) struct AnonymousParamInfo < ' tcx > {
13
+ pub struct AnonymousParamInfo < ' tcx > {
13
14
/// The parameter corresponding to the anonymous region.
14
15
pub param : & ' tcx hir:: Param < ' tcx > ,
15
16
/// The type corresponding to the anonymous region parameter.
@@ -22,76 +23,83 @@ pub(super) struct AnonymousParamInfo<'tcx> {
22
23
pub is_first : bool ,
23
24
}
24
25
26
+ // This method walks the Type of the function body parameters using
27
+ // `fold_regions()` function and returns the
28
+ // &hir::Param of the function parameter corresponding to the anonymous
29
+ // region and the Ty corresponding to the named region.
30
+ // Currently only the case where the function declaration consists of
31
+ // one named region and one anonymous region is handled.
32
+ // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32`
33
+ // Here, we would return the hir::Param for y, we return the type &'a
34
+ // i32, which is the type of y but with the anonymous region replaced
35
+ // with 'a, the corresponding bound region and is_first which is true if
36
+ // the hir::Param is the first parameter in the function declaration.
37
+ pub fn find_param_with_region < ' tcx > (
38
+ tcx : TyCtxt < ' tcx > ,
39
+ anon_region : Region < ' tcx > ,
40
+ replace_region : Region < ' tcx > ,
41
+ ) -> Option < AnonymousParamInfo < ' tcx > > {
42
+ let ( id, bound_region) = match * anon_region {
43
+ ty:: ReFree ( ref free_region) => ( free_region. scope , free_region. bound_region ) ,
44
+ ty:: ReEarlyBound ( ebr) => {
45
+ ( tcx. parent ( ebr. def_id ) . unwrap ( ) , ty:: BoundRegionKind :: BrNamed ( ebr. def_id , ebr. name ) )
46
+ }
47
+ _ => return None , // not a free region
48
+ } ;
49
+
50
+ let hir = & tcx. hir ( ) ;
51
+ let hir_id = hir. local_def_id_to_hir_id ( id. as_local ( ) ?) ;
52
+ let body_id = hir. maybe_body_owned_by ( hir_id) ?;
53
+ let body = hir. body ( body_id) ;
54
+ let owner_id = hir. body_owner ( body_id) ;
55
+ let fn_decl = hir. fn_decl_by_hir_id ( owner_id) . unwrap ( ) ;
56
+ let poly_fn_sig = tcx. fn_sig ( id) ;
57
+ let fn_sig = tcx. liberate_late_bound_regions ( id, poly_fn_sig) ;
58
+ body. params
59
+ . iter ( )
60
+ . take ( if fn_sig. c_variadic {
61
+ fn_sig. inputs ( ) . len ( )
62
+ } else {
63
+ assert_eq ! ( fn_sig. inputs( ) . len( ) , body. params. len( ) ) ;
64
+ body. params . len ( )
65
+ } )
66
+ . enumerate ( )
67
+ . find_map ( |( index, param) | {
68
+ // May return None; sometimes the tables are not yet populated.
69
+ let ty = fn_sig. inputs ( ) [ index] ;
70
+ let mut found_anon_region = false ;
71
+ let new_param_ty = tcx. fold_regions ( ty, & mut false , |r, _| {
72
+ if r == anon_region {
73
+ found_anon_region = true ;
74
+ replace_region
75
+ } else {
76
+ r
77
+ }
78
+ } ) ;
79
+ if found_anon_region {
80
+ let ty_hir_id = fn_decl. inputs [ index] . hir_id ;
81
+ let param_ty_span = hir. span ( ty_hir_id) ;
82
+ let is_first = index == 0 ;
83
+ Some ( AnonymousParamInfo {
84
+ param,
85
+ param_ty : new_param_ty,
86
+ param_ty_span,
87
+ bound_region,
88
+ is_first,
89
+ } )
90
+ } else {
91
+ None
92
+ }
93
+ } )
94
+ }
95
+
25
96
impl < ' a , ' tcx > NiceRegionError < ' a , ' tcx > {
26
- // This method walks the Type of the function body parameters using
27
- // `fold_regions()` function and returns the
28
- // &hir::Param of the function parameter corresponding to the anonymous
29
- // region and the Ty corresponding to the named region.
30
- // Currently only the case where the function declaration consists of
31
- // one named region and one anonymous region is handled.
32
- // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32`
33
- // Here, we would return the hir::Param for y, we return the type &'a
34
- // i32, which is the type of y but with the anonymous region replaced
35
- // with 'a, the corresponding bound region and is_first which is true if
36
- // the hir::Param is the first parameter in the function declaration.
37
97
pub ( super ) fn find_param_with_region (
38
98
& self ,
39
99
anon_region : Region < ' tcx > ,
40
100
replace_region : Region < ' tcx > ,
41
101
) -> Option < AnonymousParamInfo < ' _ > > {
42
- let ( id, bound_region) = match * anon_region {
43
- ty:: ReFree ( ref free_region) => ( free_region. scope , free_region. bound_region ) ,
44
- ty:: ReEarlyBound ( ebr) => (
45
- self . tcx ( ) . parent ( ebr. def_id ) . unwrap ( ) ,
46
- ty:: BoundRegionKind :: BrNamed ( ebr. def_id , ebr. name ) ,
47
- ) ,
48
- _ => return None , // not a free region
49
- } ;
50
-
51
- let hir = & self . tcx ( ) . hir ( ) ;
52
- let hir_id = hir. local_def_id_to_hir_id ( id. as_local ( ) ?) ;
53
- let body_id = hir. maybe_body_owned_by ( hir_id) ?;
54
- let body = hir. body ( body_id) ;
55
- let owner_id = hir. body_owner ( body_id) ;
56
- let fn_decl = hir. fn_decl_by_hir_id ( owner_id) . unwrap ( ) ;
57
- let poly_fn_sig = self . tcx ( ) . fn_sig ( id) ;
58
- let fn_sig = self . tcx ( ) . liberate_late_bound_regions ( id, poly_fn_sig) ;
59
- body. params
60
- . iter ( )
61
- . take ( if fn_sig. c_variadic {
62
- fn_sig. inputs ( ) . len ( )
63
- } else {
64
- assert_eq ! ( fn_sig. inputs( ) . len( ) , body. params. len( ) ) ;
65
- body. params . len ( )
66
- } )
67
- . enumerate ( )
68
- . find_map ( |( index, param) | {
69
- // May return None; sometimes the tables are not yet populated.
70
- let ty = fn_sig. inputs ( ) [ index] ;
71
- let mut found_anon_region = false ;
72
- let new_param_ty = self . tcx ( ) . fold_regions ( ty, & mut false , |r, _| {
73
- if r == anon_region {
74
- found_anon_region = true ;
75
- replace_region
76
- } else {
77
- r
78
- }
79
- } ) ;
80
- if found_anon_region {
81
- let ty_hir_id = fn_decl. inputs [ index] . hir_id ;
82
- let param_ty_span = hir. span ( ty_hir_id) ;
83
- let is_first = index == 0 ;
84
- Some ( AnonymousParamInfo {
85
- param,
86
- param_ty : new_param_ty,
87
- param_ty_span,
88
- bound_region,
89
- is_first,
90
- } )
91
- } else {
92
- None
93
- }
94
- } )
102
+ find_param_with_region ( self . tcx ( ) , anon_region, replace_region)
95
103
}
96
104
97
105
// Here, we check for the case where the anonymous region
0 commit comments