@@ -679,7 +679,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
679679
680680            // If the trait has a single item (which wasn't matched by Levenshtein), suggest it 
681681            let  suggestion = self . get_single_associated_item ( & path,  & source,  is_expected) ; 
682-             self . r . add_typo_suggestion ( err,  suggestion,  ident_span) ; 
682+             if  !self . r . add_typo_suggestion ( err,  suggestion,  ident_span)  { 
683+                 fallback = !self . let_binding_suggestion ( err,  ident_span) ; 
684+             } 
683685        } 
684686        fallback
685687    } 
@@ -1076,41 +1078,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
10761078        // where a brace being opened means a block is being started. Look 
10771079        // ahead for the next text to see if `span` is followed by a `{`. 
10781080        let  sm = self . r . session . source_map ( ) ; 
1079-         let  mut  sp = span; 
1080-         loop  { 
1081-             sp = sm. next_point ( sp) ; 
1082-             match  sm. span_to_snippet ( sp)  { 
1083-                 Ok ( ref  snippet)  => { 
1084-                     if  snippet. chars ( ) . any ( |c| !c. is_whitespace ( ) )  { 
1085-                         break ; 
1086-                     } 
1087-                 } 
1088-                 _ => break , 
1089-             } 
1090-         } 
1081+         let  sp = sm. span_look_ahead ( span,  None ,  Some ( 50 ) ) ; 
10911082        let  followed_by_brace = matches ! ( sm. span_to_snippet( sp) ,  Ok ( ref snippet)  if  snippet == "{" ) ; 
10921083        // In case this could be a struct literal that needs to be surrounded 
10931084        // by parentheses, find the appropriate span. 
1094-         let  mut  i = 0 ; 
1095-         let  mut  closing_brace = None ; 
1096-         loop  { 
1097-             sp = sm. next_point ( sp) ; 
1098-             match  sm. span_to_snippet ( sp)  { 
1099-                 Ok ( ref  snippet)  => { 
1100-                     if  snippet == "}"  { 
1101-                         closing_brace = Some ( span. to ( sp) ) ; 
1102-                         break ; 
1103-                     } 
1104-                 } 
1105-                 _ => break , 
1106-             } 
1107-             i += 1 ; 
1108-             // The bigger the span, the more likely we're incorrect -- 
1109-             // bound it to 100 chars long. 
1110-             if  i > 100  { 
1111-                 break ; 
1112-             } 
1113-         } 
1085+         let  closing_span = sm. span_look_ahead ( span,  Some ( "}" ) ,  Some ( 50 ) ) ; 
1086+         let  closing_brace:  Option < Span >  = sm
1087+             . span_to_snippet ( closing_span) 
1088+             . map_or ( None ,  |s| if  s == "}"  {  Some ( span. to ( closing_span) )  }  else  {  None  } ) ; 
11141089        ( followed_by_brace,  closing_brace) 
11151090    } 
11161091
@@ -1727,26 +1702,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
17271702                            } 
17281703                        } 
17291704                        if  let  Ok ( base_snippet)  = base_snippet { 
1730-                             let  mut  sp = after_colon_sp; 
1731-                             for  _ in  0 ..100  { 
1732-                                 // Try to find an assignment 
1733-                                 sp = sm. next_point ( sp) ; 
1734-                                 let  snippet = sm. span_to_snippet ( sp) ; 
1735-                                 match  snippet { 
1736-                                     Ok ( ref  x)  if  x. as_str ( )  == "="  => { 
1737-                                         err. span_suggestion ( 
1738-                                             base_span, 
1739-                                             "maybe you meant to write an assignment here" , 
1740-                                             format ! ( "let {}" ,  base_snippet) , 
1741-                                             Applicability :: MaybeIncorrect , 
1742-                                         ) ; 
1743-                                         show_label = false ; 
1744-                                         break ; 
1745-                                     } 
1746-                                     Ok ( ref  x)  if  x. as_str ( )  == "\n "  => break , 
1747-                                     Err ( _)  => break , 
1748-                                     Ok ( _)  => { } 
1749-                                 } 
1705+                             // Try to find an assignment 
1706+                             let  eq_span = sm. span_look_ahead ( after_colon_sp,  Some ( "=" ) ,  Some ( 50 ) ) ; 
1707+                             if  let  Ok ( ref  snippet)  = sm. span_to_snippet ( eq_span)  && snippet == "="  { 
1708+                                 err. span_suggestion ( 
1709+                                     base_span, 
1710+                                     "maybe you meant to write an assignment here" , 
1711+                                     format ! ( "let {}" ,  base_snippet) , 
1712+                                     Applicability :: MaybeIncorrect , 
1713+                                 ) ; 
1714+                                 show_label = false ; 
17501715                            } 
17511716                        } 
17521717                    } 
@@ -1763,6 +1728,31 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
17631728        false 
17641729    } 
17651730
1731+     fn  let_binding_suggestion ( & self ,  err :  & mut  Diagnostic ,  ident_span :  Span )  -> bool  { 
1732+         // try to give a suggestion for this pattern: `name = 1`, which is common in other languages 
1733+         let  mut  added_suggestion = false ; 
1734+         if  let  Some ( Expr  {  kind :  ExprKind :: Assign ( lhs,  _rhs,  _) ,  .. } )  = self . diagnostic_metadata . in_assignment  &&
1735+             let  ast:: ExprKind :: Path ( None ,  _)  = lhs. kind  { 
1736+                 let  sm = self . r . session . source_map ( ) ; 
1737+                 let  line_span = sm. span_extend_to_line ( ident_span) ; 
1738+                 let  ident_name = sm. span_to_snippet ( ident_span) . unwrap ( ) ; 
1739+                 // HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros 
1740+                 if  sm
1741+                     . span_to_snippet ( line_span) 
1742+                     . map_or ( false ,  |s| s. trim ( ) . starts_with ( & ident_name) ) 
1743+                 { 
1744+                     err. span_suggestion_verbose ( 
1745+                         ident_span. shrink_to_lo ( ) , 
1746+                         "you might have meant to introduce a new binding" , 
1747+                         "let " . to_string ( ) , 
1748+                         Applicability :: MaybeIncorrect , 
1749+                     ) ; 
1750+                     added_suggestion = true ; 
1751+                 } 
1752+             } 
1753+         added_suggestion
1754+     } 
1755+ 
17661756    fn  find_module ( & mut  self ,  def_id :  DefId )  -> Option < ( Module < ' a > ,  ImportSuggestion ) >  { 
17671757        let  mut  result = None ; 
17681758        let  mut  seen_modules = FxHashSet :: default ( ) ; 
0 commit comments