@@ -7,52 +7,59 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
7
7
use rustc_hir:: { Body , Expr , ExprKind , FnRetTy , HirId , Local , Pat } ;
8
8
use rustc_middle:: hir:: map:: Map ;
9
9
use rustc_middle:: ty:: print:: Print ;
10
- use rustc_middle:: ty:: { self , DefIdTree , Infer , Ty , TyVar } ;
10
+ use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind } ;
11
+ use rustc_middle:: ty:: { self , DefIdTree , Ty } ;
11
12
use rustc_span:: source_map:: DesugaringKind ;
12
13
use rustc_span:: symbol:: kw;
13
14
use rustc_span:: Span ;
14
15
use std:: borrow:: Cow ;
15
16
16
- struct FindLocalByTypeVisitor < ' a , ' tcx > {
17
+ struct FindHirNodeVisitor < ' a , ' tcx > {
17
18
infcx : & ' a InferCtxt < ' a , ' tcx > ,
18
- target_ty : Ty < ' tcx > ,
19
- hir_map : Map < ' tcx > ,
19
+ target : GenericArg < ' tcx > ,
20
+ found_node_ty : Option < Ty < ' tcx > > ,
20
21
found_local_pattern : Option < & ' tcx Pat < ' tcx > > ,
21
22
found_arg_pattern : Option < & ' tcx Pat < ' tcx > > ,
22
- found_ty : Option < Ty < ' tcx > > ,
23
- found_closure : Option < & ' tcx ExprKind < ' tcx > > ,
23
+ found_closure : Option < & ' tcx Expr < ' tcx > > ,
24
24
found_method_call : Option < & ' tcx Expr < ' tcx > > ,
25
25
}
26
26
27
- impl < ' a , ' tcx > FindLocalByTypeVisitor < ' a , ' tcx > {
28
- fn new ( infcx : & ' a InferCtxt < ' a , ' tcx > , target_ty : Ty < ' tcx > , hir_map : Map < ' tcx > ) -> Self {
27
+ impl < ' a , ' tcx > FindHirNodeVisitor < ' a , ' tcx > {
28
+ fn new ( infcx : & ' a InferCtxt < ' a , ' tcx > , target : GenericArg < ' tcx > ) -> Self {
29
29
Self {
30
30
infcx,
31
- target_ty ,
32
- hir_map ,
31
+ target ,
32
+ found_node_ty : None ,
33
33
found_local_pattern : None ,
34
34
found_arg_pattern : None ,
35
- found_ty : None ,
36
35
found_closure : None ,
37
36
found_method_call : None ,
38
37
}
39
38
}
40
39
41
- fn node_matches_type ( & mut self , hir_id : HirId ) -> Option < Ty < ' tcx > > {
40
+ fn node_ty_contains_target ( & mut self , hir_id : HirId ) -> Option < Ty < ' tcx > > {
42
41
let ty_opt =
43
42
self . infcx . in_progress_tables . and_then ( |tables| tables. borrow ( ) . node_type_opt ( hir_id) ) ;
44
43
match ty_opt {
45
44
Some ( ty) => {
46
45
let ty = self . infcx . resolve_vars_if_possible ( & ty) ;
47
- if ty. walk ( ) . any ( |inner_ty| {
48
- inner_ty == self . target_ty
49
- || match ( & inner_ty. kind , & self . target_ty . kind ) {
50
- ( & Infer ( TyVar ( a_vid) ) , & Infer ( TyVar ( b_vid) ) ) => self
51
- . infcx
52
- . inner
53
- . borrow_mut ( )
54
- . type_variables
55
- . sub_unified ( a_vid, b_vid) ,
46
+ if ty. walk ( ) . any ( |inner| {
47
+ inner == self . target
48
+ || match ( inner. unpack ( ) , self . target . unpack ( ) ) {
49
+ ( GenericArgKind :: Type ( inner_ty) , GenericArgKind :: Type ( target_ty) ) => {
50
+ match ( & inner_ty. kind , & target_ty. kind ) {
51
+ (
52
+ & ty:: Infer ( ty:: TyVar ( a_vid) ) ,
53
+ & ty:: Infer ( ty:: TyVar ( b_vid) ) ,
54
+ ) => self
55
+ . infcx
56
+ . inner
57
+ . borrow_mut ( )
58
+ . type_variables
59
+ . sub_unified ( a_vid, b_vid) ,
60
+ _ => false ,
61
+ }
62
+ }
56
63
_ => false ,
57
64
}
58
65
} ) {
@@ -66,36 +73,39 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
66
73
}
67
74
}
68
75
69
- impl < ' a , ' tcx > Visitor < ' tcx > for FindLocalByTypeVisitor < ' a , ' tcx > {
76
+ impl < ' a , ' tcx > Visitor < ' tcx > for FindHirNodeVisitor < ' a , ' tcx > {
70
77
type Map = Map < ' tcx > ;
71
78
72
79
fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > {
73
- NestedVisitorMap :: OnlyBodies ( self . hir_map )
80
+ NestedVisitorMap :: OnlyBodies ( self . infcx . tcx . hir ( ) )
74
81
}
75
82
76
83
fn visit_local ( & mut self , local : & ' tcx Local < ' tcx > ) {
77
- if let ( None , Some ( ty) ) = ( self . found_local_pattern , self . node_matches_type ( local. hir_id ) ) {
84
+ if let ( None , Some ( ty) ) =
85
+ ( self . found_local_pattern , self . node_ty_contains_target ( local. hir_id ) )
86
+ {
78
87
self . found_local_pattern = Some ( & * local. pat ) ;
79
- self . found_ty = Some ( ty) ;
88
+ self . found_node_ty = Some ( ty) ;
80
89
}
81
90
intravisit:: walk_local ( self , local) ;
82
91
}
83
92
84
93
fn visit_body ( & mut self , body : & ' tcx Body < ' tcx > ) {
85
94
for param in body. params {
86
- if let ( None , Some ( ty) ) = ( self . found_arg_pattern , self . node_matches_type ( param. hir_id ) )
95
+ if let ( None , Some ( ty) ) =
96
+ ( self . found_arg_pattern , self . node_ty_contains_target ( param. hir_id ) )
87
97
{
88
98
self . found_arg_pattern = Some ( & * param. pat ) ;
89
- self . found_ty = Some ( ty) ;
99
+ self . found_node_ty = Some ( ty) ;
90
100
}
91
101
}
92
102
intravisit:: walk_body ( self , body) ;
93
103
}
94
104
95
105
fn visit_expr ( & mut self , expr : & ' tcx Expr < ' tcx > ) {
96
- if self . node_matches_type ( expr. hir_id ) . is_some ( ) {
106
+ if self . node_ty_contains_target ( expr. hir_id ) . is_some ( ) {
97
107
match expr. kind {
98
- ExprKind :: Closure ( ..) => self . found_closure = Some ( & expr. kind ) ,
108
+ ExprKind :: Closure ( ..) => self . found_closure = Some ( & expr) ,
99
109
ExprKind :: MethodCall ( ..) => self . found_method_call = Some ( & expr) ,
100
110
_ => { }
101
111
}
@@ -213,6 +223,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
213
223
( s, None , ty. prefix_string ( ) , None , None )
214
224
}
215
225
226
+ // FIXME(eddyb) generalize all of this to handle `ty::Const` inference variables as well.
216
227
pub fn need_type_info_err (
217
228
& self ,
218
229
body_id : Option < hir:: BodyId > ,
@@ -223,7 +234,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
223
234
let ty = self . resolve_vars_if_possible ( & ty) ;
224
235
let ( name, name_sp, descr, parent_name, parent_descr) = self . extract_type_name ( & ty, None ) ;
225
236
226
- let mut local_visitor = FindLocalByTypeVisitor :: new ( & self , ty, self . tcx . hir ( ) ) ;
237
+ let mut local_visitor = FindHirNodeVisitor :: new ( & self , ty. into ( ) ) ;
227
238
let ty_to_string = |ty : Ty < ' tcx > | -> String {
228
239
let mut s = String :: new ( ) ;
229
240
let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS ) ;
@@ -276,7 +287,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
276
287
( !ty. is_impl_trait ( ) || self . tcx . features ( ) . impl_trait_in_bindings )
277
288
} ;
278
289
279
- let ty_msg = match local_visitor. found_ty {
290
+ let ty_msg = match local_visitor. found_node_ty {
280
291
Some ( ty:: TyS { kind : ty:: Closure ( _, substs) , .. } ) => {
281
292
let fn_sig = substs. as_closure ( ) . sig ( ) ;
282
293
let args = closure_args ( & fn_sig) ;
@@ -310,28 +321,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
310
321
error_code,
311
322
) ;
312
323
313
- let suffix = match local_visitor. found_ty {
324
+ let suffix = match local_visitor. found_node_ty {
314
325
Some ( ty:: TyS { kind : ty:: Closure ( _, substs) , .. } ) => {
315
326
let fn_sig = substs. as_closure ( ) . sig ( ) ;
316
327
let ret = fn_sig. output ( ) . skip_binder ( ) . to_string ( ) ;
317
328
318
- if let Some ( ExprKind :: Closure ( _, decl, body_id, ..) ) = local_visitor. found_closure {
319
- if let Some ( body) = self . tcx . hir ( ) . krate ( ) . bodies . get ( body_id) {
320
- closure_return_type_suggestion (
321
- span,
322
- & mut err,
323
- & decl. output ,
324
- & body,
325
- & descr,
326
- & name,
327
- & ret,
328
- parent_name,
329
- parent_descr,
330
- ) ;
331
- // We don't want to give the other suggestions when the problem is the
332
- // closure return type.
333
- return err;
334
- }
329
+ let closure_decl_and_body_id =
330
+ local_visitor. found_closure . and_then ( |closure| match & closure. kind {
331
+ ExprKind :: Closure ( _, decl, body_id, ..) => Some ( ( decl, * body_id) ) ,
332
+ _ => None ,
333
+ } ) ;
334
+
335
+ if let Some ( ( decl, body_id) ) = closure_decl_and_body_id {
336
+ closure_return_type_suggestion (
337
+ span,
338
+ & mut err,
339
+ & decl. output ,
340
+ self . tcx . hir ( ) . body ( body_id) ,
341
+ & descr,
342
+ & name,
343
+ & ret,
344
+ parent_name,
345
+ parent_descr,
346
+ ) ;
347
+ // We don't want to give the other suggestions when the problem is the
348
+ // closure return type.
349
+ return err;
335
350
}
336
351
337
352
// This shouldn't be reachable, but just in case we leave a reasonable fallback.
0 commit comments