22//! anonymous regions.
33
44use crate :: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
5+ use crate :: infer:: TyCtxt ;
56use rustc_hir as hir;
67use rustc_hir:: def_id:: LocalDefId ;
78use rustc_middle:: ty:: { self , Binder , DefIdTree , Region , Ty , TypeFoldable } ;
89use rustc_span:: Span ;
910
1011/// Information about the anonymous region we are searching for.
1112#[ derive( Debug ) ]
12- pub ( super ) struct AnonymousParamInfo < ' tcx > {
13+ pub struct AnonymousParamInfo < ' tcx > {
1314 /// The parameter corresponding to the anonymous region.
1415 pub param : & ' tcx hir:: Param < ' tcx > ,
1516 /// The type corresponding to the anonymous region parameter.
@@ -22,76 +23,83 @@ pub(super) struct AnonymousParamInfo<'tcx> {
2223 pub is_first : bool ,
2324}
2425
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+
2596impl < ' 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.
3797 pub ( super ) fn find_param_with_region (
3898 & self ,
3999 anon_region : Region < ' tcx > ,
40100 replace_region : Region < ' tcx > ,
41101 ) -> 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)
95103 }
96104
97105 // Here, we check for the case where the anonymous region
0 commit comments