@@ -708,7 +708,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
708
708
709
709
// If the trait has a single item (which wasn't matched by Levenshtein), suggest it
710
710
let suggestion = self . get_single_associated_item ( & path, & source, is_expected) ;
711
- self . r . add_typo_suggestion ( err, suggestion, ident_span) ;
711
+ if !self . r . add_typo_suggestion ( err, suggestion, ident_span) {
712
+ fallback = !self . let_binding_suggestion ( err, ident_span) ;
713
+ }
712
714
}
713
715
fallback
714
716
}
@@ -1105,41 +1107,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
1105
1107
// where a brace being opened means a block is being started. Look
1106
1108
// ahead for the next text to see if `span` is followed by a `{`.
1107
1109
let sm = self . r . session . source_map ( ) ;
1108
- let mut sp = span;
1109
- loop {
1110
- sp = sm. next_point ( sp) ;
1111
- match sm. span_to_snippet ( sp) {
1112
- Ok ( ref snippet) => {
1113
- if snippet. chars ( ) . any ( |c| !c. is_whitespace ( ) ) {
1114
- break ;
1115
- }
1116
- }
1117
- _ => break ,
1118
- }
1119
- }
1110
+ let sp = sm. span_look_ahead ( span, None , Some ( 50 ) ) ;
1120
1111
let followed_by_brace = matches ! ( sm. span_to_snippet( sp) , Ok ( ref snippet) if snippet == "{" ) ;
1121
1112
// In case this could be a struct literal that needs to be surrounded
1122
1113
// by parentheses, find the appropriate span.
1123
- let mut i = 0 ;
1124
- let mut closing_brace = None ;
1125
- loop {
1126
- sp = sm. next_point ( sp) ;
1127
- match sm. span_to_snippet ( sp) {
1128
- Ok ( ref snippet) => {
1129
- if snippet == "}" {
1130
- closing_brace = Some ( span. to ( sp) ) ;
1131
- break ;
1132
- }
1133
- }
1134
- _ => break ,
1135
- }
1136
- i += 1 ;
1137
- // The bigger the span, the more likely we're incorrect --
1138
- // bound it to 100 chars long.
1139
- if i > 100 {
1140
- break ;
1141
- }
1142
- }
1114
+ let closing_span = sm. span_look_ahead ( span, Some ( "}" ) , Some ( 50 ) ) ;
1115
+ let closing_brace: Option < Span > = sm
1116
+ . span_to_snippet ( closing_span)
1117
+ . map_or ( None , |s| if s == "}" { Some ( span. to ( closing_span) ) } else { None } ) ;
1143
1118
( followed_by_brace, closing_brace)
1144
1119
}
1145
1120
@@ -1779,26 +1754,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
1779
1754
}
1780
1755
}
1781
1756
if let Ok ( base_snippet) = base_snippet {
1782
- let mut sp = after_colon_sp;
1783
- for _ in 0 ..100 {
1784
- // Try to find an assignment
1785
- sp = sm. next_point ( sp) ;
1786
- let snippet = sm. span_to_snippet ( sp) ;
1787
- match snippet {
1788
- Ok ( ref x) if x. as_str ( ) == "=" => {
1789
- err. span_suggestion (
1790
- base_span,
1791
- "maybe you meant to write an assignment here" ,
1792
- format ! ( "let {}" , base_snippet) ,
1793
- Applicability :: MaybeIncorrect ,
1794
- ) ;
1795
- show_label = false ;
1796
- break ;
1797
- }
1798
- Ok ( ref x) if x. as_str ( ) == "\n " => break ,
1799
- Err ( _) => break ,
1800
- Ok ( _) => { }
1801
- }
1757
+ // Try to find an assignment
1758
+ let eq_span = sm. span_look_ahead ( after_colon_sp, Some ( "=" ) , Some ( 50 ) ) ;
1759
+ if let Ok ( ref snippet) = sm. span_to_snippet ( eq_span) && snippet == "=" {
1760
+ err. span_suggestion (
1761
+ base_span,
1762
+ "maybe you meant to write an assignment here" ,
1763
+ format ! ( "let {}" , base_snippet) ,
1764
+ Applicability :: MaybeIncorrect ,
1765
+ ) ;
1766
+ show_label = false ;
1802
1767
}
1803
1768
}
1804
1769
}
@@ -1815,6 +1780,31 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
1815
1780
false
1816
1781
}
1817
1782
1783
+ fn let_binding_suggestion ( & self , err : & mut Diagnostic , ident_span : Span ) -> bool {
1784
+ // try to give a suggestion for this pattern: `name = 1`, which is common in other languages
1785
+ let mut added_suggestion = false ;
1786
+ if let Some ( Expr { kind : ExprKind :: Assign ( lhs, _rhs, _) , .. } ) = self . diagnostic_metadata . in_assignment &&
1787
+ let ast:: ExprKind :: Path ( None , _) = lhs. kind {
1788
+ let sm = self . r . session . source_map ( ) ;
1789
+ let line_span = sm. span_extend_to_line ( ident_span) ;
1790
+ let ident_name = sm. span_to_snippet ( ident_span) . unwrap ( ) ;
1791
+ // HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros
1792
+ if sm
1793
+ . span_to_snippet ( line_span)
1794
+ . map_or ( false , |s| s. trim ( ) . starts_with ( & ident_name) )
1795
+ {
1796
+ err. span_suggestion_verbose (
1797
+ ident_span. shrink_to_lo ( ) ,
1798
+ "you might have meant to introduce a new binding" ,
1799
+ "let " . to_string ( ) ,
1800
+ Applicability :: MaybeIncorrect ,
1801
+ ) ;
1802
+ added_suggestion = true ;
1803
+ }
1804
+ }
1805
+ added_suggestion
1806
+ }
1807
+
1818
1808
fn find_module ( & mut self , def_id : DefId ) -> Option < ( Module < ' a > , ImportSuggestion ) > {
1819
1809
let mut result = None ;
1820
1810
let mut seen_modules = FxHashSet :: default ( ) ;
0 commit comments