@@ -7,52 +7,59 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
77use rustc_hir:: { Body , Expr , ExprKind , FnRetTy , HirId , Local , Pat } ;
88use rustc_middle:: hir:: map:: Map ;
99use 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 } ;
1112use rustc_span:: source_map:: DesugaringKind ;
1213use rustc_span:: symbol:: kw;
1314use rustc_span:: Span ;
1415use std:: borrow:: Cow ;
1516
16- struct FindLocalByTypeVisitor < ' a , ' tcx > {
17+ struct FindHirNodeVisitor < ' a , ' tcx > {
1718 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 > > ,
2021 found_local_pattern : Option < & ' tcx Pat < ' tcx > > ,
2122 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 > > ,
2424 found_method_call : Option < & ' tcx Expr < ' tcx > > ,
2525}
2626
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 {
2929 Self {
3030 infcx,
31- target_ty ,
32- hir_map ,
31+ target ,
32+ found_node_ty : None ,
3333 found_local_pattern : None ,
3434 found_arg_pattern : None ,
35- found_ty : None ,
3635 found_closure : None ,
3736 found_method_call : None ,
3837 }
3938 }
4039
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 > > {
4241 let ty_opt =
4342 self . infcx . in_progress_tables . and_then ( |tables| tables. borrow ( ) . node_type_opt ( hir_id) ) ;
4443 match ty_opt {
4544 Some ( ty) => {
4645 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+ }
5663 _ => false ,
5764 }
5865 } ) {
@@ -66,36 +73,39 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
6673 }
6774}
6875
69- impl < ' a , ' tcx > Visitor < ' tcx > for FindLocalByTypeVisitor < ' a , ' tcx > {
76+ impl < ' a , ' tcx > Visitor < ' tcx > for FindHirNodeVisitor < ' a , ' tcx > {
7077 type Map = Map < ' tcx > ;
7178
7279 fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > {
73- NestedVisitorMap :: OnlyBodies ( self . hir_map )
80+ NestedVisitorMap :: OnlyBodies ( self . infcx . tcx . hir ( ) )
7481 }
7582
7683 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+ {
7887 self . found_local_pattern = Some ( & * local. pat ) ;
79- self . found_ty = Some ( ty) ;
88+ self . found_node_ty = Some ( ty) ;
8089 }
8190 intravisit:: walk_local ( self , local) ;
8291 }
8392
8493 fn visit_body ( & mut self , body : & ' tcx Body < ' tcx > ) {
8594 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 ) )
8797 {
8898 self . found_arg_pattern = Some ( & * param. pat ) ;
89- self . found_ty = Some ( ty) ;
99+ self . found_node_ty = Some ( ty) ;
90100 }
91101 }
92102 intravisit:: walk_body ( self , body) ;
93103 }
94104
95105 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 ( ) {
97107 match expr. kind {
98- ExprKind :: Closure ( ..) => self . found_closure = Some ( & expr. kind ) ,
108+ ExprKind :: Closure ( ..) => self . found_closure = Some ( & expr) ,
99109 ExprKind :: MethodCall ( ..) => self . found_method_call = Some ( & expr) ,
100110 _ => { }
101111 }
@@ -213,6 +223,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
213223 ( s, None , ty. prefix_string ( ) , None , None )
214224 }
215225
226+ // FIXME(eddyb) generalize all of this to handle `ty::Const` inference variables as well.
216227 pub fn need_type_info_err (
217228 & self ,
218229 body_id : Option < hir:: BodyId > ,
@@ -223,7 +234,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
223234 let ty = self . resolve_vars_if_possible ( & ty) ;
224235 let ( name, name_sp, descr, parent_name, parent_descr) = self . extract_type_name ( & ty, None ) ;
225236
226- let mut local_visitor = FindLocalByTypeVisitor :: new ( & self , ty, self . tcx . hir ( ) ) ;
237+ let mut local_visitor = FindHirNodeVisitor :: new ( & self , ty. into ( ) ) ;
227238 let ty_to_string = |ty : Ty < ' tcx > | -> String {
228239 let mut s = String :: new ( ) ;
229240 let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS ) ;
@@ -276,7 +287,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
276287 ( !ty. is_impl_trait ( ) || self . tcx . features ( ) . impl_trait_in_bindings )
277288 } ;
278289
279- let ty_msg = match local_visitor. found_ty {
290+ let ty_msg = match local_visitor. found_node_ty {
280291 Some ( ty:: TyS { kind : ty:: Closure ( _, substs) , .. } ) => {
281292 let fn_sig = substs. as_closure ( ) . sig ( ) ;
282293 let args = closure_args ( & fn_sig) ;
@@ -310,28 +321,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
310321 error_code,
311322 ) ;
312323
313- let suffix = match local_visitor. found_ty {
324+ let suffix = match local_visitor. found_node_ty {
314325 Some ( ty:: TyS { kind : ty:: Closure ( _, substs) , .. } ) => {
315326 let fn_sig = substs. as_closure ( ) . sig ( ) ;
316327 let ret = fn_sig. output ( ) . skip_binder ( ) . to_string ( ) ;
317328
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;
335350 }
336351
337352 // This shouldn't be reachable, but just in case we leave a reasonable fallback.
0 commit comments