@@ -5,6 +5,7 @@ use crate::errors;
55use  crate :: FnCtxt ; 
66use  rustc_ast:: ast:: Mutability ; 
77use  rustc_data_structures:: fx:: { FxHashMap ,  FxHashSet } ; 
8+ use  rustc_errors:: StashKey ; 
89use  rustc_errors:: { 
910    pluralize,  struct_span_err,  Applicability ,  Diagnostic ,  DiagnosticBuilder ,  ErrorGuaranteed , 
1011    MultiSpan , 
@@ -13,6 +14,8 @@ use rustc_hir as hir;
1314use  rustc_hir:: def:: DefKind ; 
1415use  rustc_hir:: def_id:: DefId ; 
1516use  rustc_hir:: lang_items:: LangItem ; 
17+ use  rustc_hir:: PatKind :: Binding ; 
18+ use  rustc_hir:: PathSegment ; 
1619use  rustc_hir:: { ExprKind ,  Node ,  QPath } ; 
1720use  rustc_infer:: infer:: { 
1821    type_variable:: { TypeVariableOrigin ,  TypeVariableOriginKind } , 
@@ -35,11 +38,11 @@ use rustc_trait_selection::traits::{
3538    FulfillmentError ,  Obligation ,  ObligationCause ,  ObligationCauseCode , 
3639} ; 
3740
38- use  std:: cmp:: Ordering ; 
39- use  std:: iter; 
40- 
4141use  super :: probe:: { AutorefOrPtrAdjustment ,  IsSuggestion ,  Mode ,  ProbeScope } ; 
4242use  super :: { CandidateSource ,  MethodError ,  NoMatchData } ; 
43+ use  rustc_hir:: intravisit:: Visitor ; 
44+ use  std:: cmp:: Ordering ; 
45+ use  std:: iter; 
4346
4447impl < ' a ,  ' tcx >  FnCtxt < ' a ,  ' tcx >  { 
4548    fn  is_fn_ty ( & self ,  ty :  Ty < ' tcx > ,  span :  Span )  -> bool  { 
@@ -1470,6 +1473,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14701473        false 
14711474    } 
14721475
1476+     /// For code `rect::area(...)`, 
1477+ /// if `rect` is a local variable and `area` is a valid assoc method for it, 
1478+ /// we try to suggest `rect.area()` 
1479+ pub ( crate )  fn  suggest_assoc_method_call ( & self ,  segs :  & [ PathSegment < ' _ > ] )  { 
1480+         debug ! ( "suggest_assoc_method_call segs: {:?}" ,  segs) ; 
1481+         let  [ seg1,  seg2]  = segs else  {  return ;  } ; 
1482+         let  Some ( mut  diag)  =
1483+                 self . tcx . sess . diagnostic ( ) . steal_diagnostic ( seg1. ident . span ,  StashKey :: CallAssocMethod ) 
1484+                 else  {  return  } ; 
1485+ 
1486+         let  map = self . infcx . tcx . hir ( ) ; 
1487+         let  body = map. body ( rustc_hir:: BodyId  {  hir_id :  self . body_id  } ) ; 
1488+         struct  LetVisitor < ' a >  { 
1489+             result :  Option < & ' a  hir:: Expr < ' a > > , 
1490+             ident_name :  Symbol , 
1491+         } 
1492+ 
1493+         impl < ' v >  Visitor < ' v >  for  LetVisitor < ' v >  { 
1494+             fn  visit_stmt ( & mut  self ,  ex :  & ' v  hir:: Stmt < ' v > )  { 
1495+                 if  let  hir:: StmtKind :: Local ( hir:: Local  {  pat,  init,  .. } )  = & ex. kind  { 
1496+                     if  let  Binding ( _,  _,  ident,  ..)  = pat. kind  &&
1497+                         ident. name  == self . ident_name  { 
1498+                         self . result  = * init; 
1499+                     } 
1500+                 } 
1501+                 hir:: intravisit:: walk_stmt ( self ,  ex) ; 
1502+             } 
1503+         } 
1504+ 
1505+         let  mut  visitor = LetVisitor  {  result :  None ,  ident_name :  seg1. ident . name  } ; 
1506+         visitor. visit_body ( & body) ; 
1507+ 
1508+         let  parent = self . tcx . hir ( ) . get_parent_node ( seg1. hir_id ) ; 
1509+         if  let  Some ( Node :: Expr ( call_expr) )  = self . tcx . hir ( ) . find ( parent)  &&
1510+             let  Some ( expr)  = visitor. result  { 
1511+             let  self_ty = self . node_ty ( expr. hir_id ) ; 
1512+             let  probe = self . lookup_probe ( 
1513+                 seg2. ident , 
1514+                 self_ty, 
1515+                 call_expr, 
1516+                 ProbeScope :: TraitsInScope , 
1517+             ) ; 
1518+             if  probe. is_ok ( )  { 
1519+                 let  sm = self . infcx . tcx . sess . source_map ( ) ; 
1520+                 diag. span_suggestion_verbose ( 
1521+                     sm. span_extend_while ( seg1. ident . span . shrink_to_hi ( ) ,  |c| c == ':' ) . unwrap ( ) , 
1522+                     "maybe you meant to call instance method" , 
1523+                     "." . to_string ( ) , 
1524+                     Applicability :: MaybeIncorrect 
1525+                 ) ; 
1526+             } 
1527+         } 
1528+         diag. emit ( ) ; 
1529+     } 
1530+ 
14731531    /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()` 
14741532fn  suggest_calling_method_on_field ( 
14751533        & self , 
0 commit comments