@@ -18,6 +18,7 @@ use infer::region_inference::RegionResolutionError;
18
18
use hir:: map as hir_map;
19
19
use middle:: resolve_lifetime as rl;
20
20
use hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
21
+ use infer:: error_reporting:: util:: AnonymousArgInfo ;
21
22
22
23
impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
23
24
// This method prints the error message for lifetime errors when both the concerned regions
@@ -57,6 +58,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
57
58
let ty_sup = or_false ! ( self . find_anon_type( sup, & bregion_sup) ) ;
58
59
59
60
let ty_sub = or_false ! ( self . find_anon_type( sub, & bregion_sub) ) ;
61
+
60
62
debug ! ( "try_report_anon_anon_conflict: found_arg1={:?} sup={:?} br1={:?}" ,
61
63
ty_sub,
62
64
sup,
@@ -66,56 +68,78 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
66
68
sub,
67
69
bregion_sub) ;
68
70
69
- let ( main_label , label1 , label2 ) = if let ( Some ( sup_arg ) , Some ( sub_arg ) ) =
70
- ( self . find_arg_with_region ( sup , sup ) , self . find_arg_with_region ( sub , sub ) ) {
71
+ let ( ty_sup , ty_fndecl_sup ) = ty_sup ;
72
+ let ( ty_sub , ty_fndecl_sub ) = ty_sub ;
71
73
72
- let ( anon_arg_sup, is_first_sup, anon_arg_sub, is_first_sub) =
73
- ( sup_arg. arg , sup_arg. is_first , sub_arg. arg , sub_arg. is_first ) ;
74
- if self . is_self_anon ( is_first_sup, scope_def_id_sup) ||
75
- self . is_self_anon ( is_first_sub, scope_def_id_sub) {
76
- return false ;
77
- }
74
+ let AnonymousArgInfo { arg : anon_arg_sup, .. } =
75
+ or_false ! ( self . find_arg_with_region( sup, sup) ) ;
76
+ let AnonymousArgInfo { arg : anon_arg_sub, .. } =
77
+ or_false ! ( self . find_arg_with_region( sub, sub) ) ;
78
78
79
- if self . is_return_type_anon ( scope_def_id_sup , bregion_sup ) ||
80
- self . is_return_type_anon ( scope_def_id_sub , bregion_sub ) {
81
- return false ;
82
- }
79
+ let sup_is_ret_type =
80
+ self . is_return_type_anon ( scope_def_id_sup , bregion_sup , ty_fndecl_sup ) ;
81
+ let sub_is_ret_type =
82
+ self . is_return_type_anon ( scope_def_id_sub , bregion_sub , ty_fndecl_sub ) ;
83
83
84
- if anon_arg_sup == anon_arg_sub {
85
- ( format ! ( "this type was declared with multiple lifetimes..." ) ,
86
- format ! ( " with one lifetime" ) ,
87
- format ! ( " into the other" ) )
88
- } else {
89
- let span_label_var1 = if let Some ( simple_name) = anon_arg_sup. pat . simple_name ( ) {
90
- format ! ( " from `{}`" , simple_name)
91
- } else {
92
- format ! ( "" )
93
- } ;
84
+ let span_label_var1 = if let Some ( simple_name) = anon_arg_sup. pat . simple_name ( ) {
85
+ format ! ( " flows from `{}`" , simple_name)
86
+ } else {
87
+ format ! ( "" )
88
+ } ;
89
+
90
+ let span_label_var2 = if let Some ( simple_name) = anon_arg_sub. pat . simple_name ( ) {
91
+ format ! ( " into `{}`" , simple_name)
92
+ } else {
93
+ format ! ( "" )
94
+ } ;
94
95
95
- let span_label_var2 = if let Some ( simple_name) = anon_arg_sub. pat . simple_name ( ) {
96
- format ! ( " into `{}`" , simple_name)
97
- } else {
98
- format ! ( "" )
99
- } ;
100
96
101
- let span_label =
102
- format ! ( "these two types are declared with different lifetimes..." , ) ;
97
+ let ( span_1, span_2, main_label, span_label) = match ( sup_is_ret_type, sub_is_ret_type) {
98
+ ( None , None ) => {
99
+ let ( main_label_1, span_label_1) = if ty_sup == ty_sub {
103
100
104
- ( span_label, span_label_var1, span_label_var2)
101
+ ( format ! ( "this type was declared with multiple lifetimes..." ) ,
102
+ format ! ( "...but data{} flows{} here" ,
103
+ format!( " with one lifetime" ) ,
104
+ format!( " into the other" ) ) )
105
+ } else {
106
+ ( format ! ( "these two types was declared with multiple lifetimes..." ) ,
107
+ format ! ( "...but data{} flows{} here" ,
108
+ span_label_var1,
109
+ span_label_var2) )
110
+ } ;
111
+ ( ty_sup. span , ty_sub. span , main_label_1, span_label_1)
112
+ }
113
+ ( Some ( ret_span1) , Some ( ret_span2) ) => {
114
+ ( ret_span1,
115
+ ret_span2,
116
+ format ! ( "the return type is declared with different lifetimes..." ) ,
117
+ format ! ( "...but data{} flows{} here" ,
118
+ format!( " with one lifetime" ) ,
119
+ format!( " into the other" ) ) )
120
+ }
121
+
122
+ ( Some ( ret_span) , _) => {
123
+ ( ty_sub. span ,
124
+ ret_span,
125
+ format ! ( "this parameter and the return type are declared
126
+ with different lifetimes..." , ) ,
127
+ format ! ( "...but data{} is returned here" , span_label_var1) )
128
+ }
129
+ ( _, Some ( ret_span) ) => {
130
+ ( ty_sup. span ,
131
+ ret_span,
132
+ format ! ( "this parameter and the return type are declared
133
+ with different lifetimes..." , ) ,
134
+ format ! ( "...but data{} is returned here" , span_label_var1) )
105
135
}
106
- } else {
107
- debug ! ( "no arg with anon region found" ) ;
108
- debug ! ( "try_report_anon_anon_conflict: is_suitable(sub) = {:?}" ,
109
- self . is_suitable_region( sub) ) ;
110
- debug ! ( "try_report_anon_anon_conflict: is_suitable(sup) = {:?}" ,
111
- self . is_suitable_region( sup) ) ;
112
- return false ;
113
136
} ;
114
137
138
+
115
139
struct_span_err ! ( self . tcx. sess, span, E0623 , "lifetime mismatch" )
116
- . span_label ( ty_sup . span , main_label)
117
- . span_label ( ty_sub . span , format ! ( "" ) )
118
- . span_label ( span, format ! ( "...but data{} flows{} here" , label1 , label2 ) )
140
+ . span_label ( span_1 , main_label)
141
+ . span_label ( span_2 , format ! ( "" ) )
142
+ . span_label ( span, span_label )
119
143
. emit ( ) ;
120
144
return true ;
121
145
}
@@ -135,28 +159,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
135
159
/// ```
136
160
/// The function returns the nested type corresponding to the anonymous region
137
161
/// for e.g. `&u8` and Vec<`&u8`.
138
- pub fn find_anon_type ( & self , region : Region < ' tcx > , br : & ty:: BoundRegion ) -> Option < & hir:: Ty > {
162
+ pub fn find_anon_type ( & self ,
163
+ region : Region < ' tcx > ,
164
+ br : & ty:: BoundRegion )
165
+ -> Option < ( & hir:: Ty , & hir:: FnDecl ) > {
139
166
if let Some ( anon_reg) = self . is_suitable_region ( region) {
140
167
let def_id = anon_reg. def_id ;
141
168
if let Some ( node_id) = self . tcx . hir . as_local_node_id ( def_id) {
142
- let inputs : & [ _ ] = match self . tcx . hir . get ( node_id) {
169
+ let fndecl = match self . tcx . hir . get ( node_id) {
143
170
hir_map:: NodeItem ( & hir:: Item { node : hir:: ItemFn ( ref fndecl, ..) , .. } ) => {
144
- & fndecl. inputs
171
+ & fndecl
145
172
}
146
173
hir_map:: NodeTraitItem ( & hir:: TraitItem {
147
- node : hir:: TraitItemKind :: Method ( ref fndecl , ..) , ..
148
- } ) => & fndecl . decl . inputs ,
174
+ node : hir:: TraitItemKind :: Method ( ref m , ..) , ..
175
+ } ) |
149
176
hir_map:: NodeImplItem ( & hir:: ImplItem {
150
- node : hir:: ImplItemKind :: Method ( ref fndecl, ..) , ..
151
- } ) => & fndecl. decl . inputs ,
152
-
153
- _ => & [ ] ,
177
+ node : hir:: ImplItemKind :: Method ( ref m, ..) , ..
178
+ } ) => & m. decl ,
179
+ _ => return None ,
154
180
} ;
155
181
156
- return inputs
182
+ return fndecl
183
+ . inputs
157
184
. iter ( )
158
- . filter_map ( |arg| self . find_component_for_bound_region ( & * * arg, br) )
159
- . next ( ) ;
185
+ . filter_map ( |arg| self . find_component_for_bound_region ( arg, br) )
186
+ . next ( )
187
+ . map ( |ty| ( ty, & * * fndecl) ) ;
160
188
}
161
189
}
162
190
None
0 commit comments