@@ -14,6 +14,7 @@ use infer::InferCtxt;
14
14
use ty:: { self , Region } ;
15
15
use infer:: region_inference:: RegionResolutionError :: * ;
16
16
use infer:: region_inference:: RegionResolutionError ;
17
+ use hir:: map as hir_map;
17
18
18
19
impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
19
20
// This method walks the Type of the function body arguments using
@@ -23,12 +24,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
23
24
// Currently only the case where the function declaration consists of
24
25
// one named region and one anonymous region is handled.
25
26
// Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32`
26
- // Here, the `y` and the `Ty` of `y` is returned after being substituted
27
- // by that of the named region.
28
- pub fn find_arg_with_anonymous_region ( & self ,
29
- anon_region : Region < ' tcx > ,
30
- named_region : Region < ' tcx > )
31
- -> Option < ( & hir:: Arg , ty:: Ty < ' tcx > ) > {
27
+ // Here, we would return the hir::Arg for y, and we return the type &'a
28
+ // i32, which is the type of y but with the anonymous region replaced
29
+ // with 'a.
30
+ fn find_arg_with_anonymous_region ( & self ,
31
+ anon_region : Region < ' tcx > ,
32
+ named_region : Region < ' tcx > )
33
+ -> Option < ( & hir:: Arg , ty:: Ty < ' tcx > ) > {
32
34
33
35
match * anon_region {
34
36
ty:: ReFree ( ref free_region) => {
@@ -70,29 +72,35 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
70
72
// This method generates the error message for the case when
71
73
// the function arguments consist of a named region and an anonymous
72
74
// region and corresponds to `ConcreteFailure(..)`
73
- pub fn report_named_anon_conflict ( & self , error : & RegionResolutionError < ' tcx > ) -> bool {
75
+ pub fn try_report_named_anon_conflict ( & self , error : & RegionResolutionError < ' tcx > ) -> bool {
74
76
75
77
let ( span, sub, sup) = match * error {
76
78
ConcreteFailure ( ref origin, sub, sup) => ( origin. span ( ) , sub, sup) ,
77
79
_ => return false , // inapplicable
78
80
} ;
79
81
80
- let ( named, ( var, new_ty) ) =
81
- if self . is_named_region ( sub) && self . is_anonymous_region ( sup) {
82
+ // Determine whether the sub and sup consist of one named region ('a)
83
+ // and one anonymous (elided) region. If so, find the parameter arg
84
+ // where the anonymous region appears (there must always be one; we
85
+ // only introduced anonymous regions in parameters) as well as a
86
+ // version new_ty of its type where the anonymous region is replaced
87
+ // with the named one.
88
+ let ( named, ( arg, new_ty) ) =
89
+ if self . is_named_region ( sub) && self . is_suitable_anonymous_region ( sup) {
82
90
( sub, self . find_arg_with_anonymous_region ( sup, sub) . unwrap ( ) )
83
- } else if self . is_named_region ( sup) && self . is_anonymous_region ( sub) {
91
+ } else if self . is_named_region ( sup) && self . is_suitable_anonymous_region ( sub) {
84
92
( sup, self . find_arg_with_anonymous_region ( sub, sup) . unwrap ( ) )
85
93
} else {
86
94
return false ; // inapplicable
87
95
} ;
88
96
89
- if let Some ( simple_name) = var . pat . simple_name ( ) {
97
+ if let Some ( simple_name) = arg . pat . simple_name ( ) {
90
98
struct_span_err ! ( self . tcx. sess,
91
99
span,
92
100
E0611 ,
93
101
"explicit lifetime required in the type of `{}`" ,
94
102
simple_name)
95
- . span_label ( var . pat . span ,
103
+ . span_label ( arg . pat . span ,
96
104
format ! ( "consider changing the type of `{}` to `{}`" ,
97
105
simple_name,
98
106
new_ty) )
@@ -104,12 +112,55 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
104
112
span,
105
113
E0611 ,
106
114
"explicit lifetime required in parameter type" )
107
- . span_label ( var . pat . span ,
115
+ . span_label ( arg . pat . span ,
108
116
format ! ( "consider changing type to `{}`" , new_ty) )
109
117
. span_label ( span, format ! ( "lifetime `{}` required" , named) )
110
118
. emit ( ) ;
111
119
}
112
120
return true ;
113
121
114
122
}
123
+
124
+ // This method returns whether the given Region is Anonymous
125
+ pub fn is_suitable_anonymous_region ( & self , region : Region < ' tcx > ) -> bool {
126
+
127
+ match * region {
128
+ ty:: ReFree ( ref free_region) => {
129
+ match free_region. bound_region {
130
+ ty:: BrAnon ( ..) => {
131
+ let anonymous_region_binding_scope = free_region. scope ;
132
+ let node_id = self . tcx
133
+ . hir
134
+ . as_local_node_id ( anonymous_region_binding_scope)
135
+ . unwrap ( ) ;
136
+ match self . tcx . hir . find ( node_id) {
137
+ Some ( hir_map:: NodeItem ( ..) ) |
138
+ Some ( hir_map:: NodeTraitItem ( ..) ) => {
139
+ // proceed ahead //
140
+ }
141
+ Some ( hir_map:: NodeImplItem ( ..) ) => {
142
+ if self . tcx . impl_trait_ref ( self . tcx .
143
+ associated_item ( anonymous_region_binding_scope) . container . id ( ) ) . is_some ( ) {
144
+ // For now, we do not try to target impls of traits. This is
145
+ // because this message is going to suggest that the user
146
+ // change the fn signature, but they may not be free to do so,
147
+ // since the signature must match the trait.
148
+ //
149
+ // FIXME(#42706) -- in some cases, we could do better here.
150
+ return false ; //None;
151
+ }
152
+ else { }
153
+
154
+ }
155
+ _ => return false , // inapplicable
156
+ // we target only top-level functions
157
+ }
158
+ return true ;
159
+ }
160
+ _ => false ,
161
+ }
162
+ }
163
+ _ => false ,
164
+ }
165
+ }
115
166
}
0 commit comments