@@ -679,7 +679,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
679
679
680
680
// If the trait has a single item (which wasn't matched by Levenshtein), suggest it
681
681
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
+ }
683
685
}
684
686
fallback
685
687
}
@@ -1076,41 +1078,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
1076
1078
// where a brace being opened means a block is being started. Look
1077
1079
// ahead for the next text to see if `span` is followed by a `{`.
1078
1080
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 ) ) ;
1091
1082
let followed_by_brace = matches ! ( sm. span_to_snippet( sp) , Ok ( ref snippet) if snippet == "{" ) ;
1092
1083
// In case this could be a struct literal that needs to be surrounded
1093
1084
// 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 } ) ;
1114
1089
( followed_by_brace, closing_brace)
1115
1090
}
1116
1091
@@ -1727,26 +1702,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
1727
1702
}
1728
1703
}
1729
1704
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 ;
1750
1715
}
1751
1716
}
1752
1717
}
@@ -1763,6 +1728,31 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
1763
1728
false
1764
1729
}
1765
1730
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
+
1766
1756
fn find_module ( & mut self , def_id : DefId ) -> Option < ( Module < ' a > , ImportSuggestion ) > {
1767
1757
let mut result = None ;
1768
1758
let mut seen_modules = FxHashSet :: default ( ) ;
0 commit comments