about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs25
-rw-r--r--src/test/ui/suggestions/issue-104086-suggest-let.rs10
-rw-r--r--src/test/ui/suggestions/issue-104086-suggest-let.stderr81
3 files changed, 109 insertions, 7 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index a1338dcd477..45c11fc9eb0 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1810,18 +1810,27 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         false
     }
 
-    fn let_binding_suggestion(&self, err: &mut Diagnostic, ident_span: Span) -> bool {
+    fn let_binding_suggestion(&mut self, err: &mut Diagnostic, ident_span: Span) -> bool {
         // try to give a suggestion for this pattern: `name = 1`, which is common in other languages
         let mut added_suggestion = false;
-        if let Some(Expr { kind: ExprKind::Assign(lhs, _rhs, _), .. }) = self.diagnostic_metadata.in_assignment &&
-            let ast::ExprKind::Path(None, _) = lhs.kind {
+        if let Some(Expr { kind: ExprKind::Assign(lhs, rhs, _), .. }) =
+            self.diagnostic_metadata.in_assignment
+        {
+            let is_rhs_assign = match rhs.kind {
+                ExprKind::Assign(..) => true,
+                _ => false,
+            };
+
+            if let ast::ExprKind::Path(None, _) = lhs.kind && !is_rhs_assign {
                 let sm = self.r.session.source_map();
                 let line_span = sm.span_extend_to_line(ident_span);
                 let ident_name = sm.span_to_snippet(ident_span).unwrap();
-                // HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros
-                if sm
-                    .span_to_snippet(line_span)
-                    .map_or(false, |s| s.trim().starts_with(&ident_name))
+                // HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros,
+                // and avoid some special cases like `x = x = x`
+                if let Ok(line) = sm.span_to_snippet(line_span) &&
+                    let stripped = line.split_whitespace().collect::<String>() &&
+                    stripped.trim().starts_with(&ident_name) &&
+                    stripped.matches(&format!("{}=", &ident_name)).count() == 1
                 {
                     err.span_suggestion_verbose(
                         ident_span.shrink_to_lo(),
@@ -1832,6 +1841,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     added_suggestion = true;
                 }
             }
+            self.diagnostic_metadata.in_assignment = None;
+        }
         added_suggestion
     }
 
diff --git a/src/test/ui/suggestions/issue-104086-suggest-let.rs b/src/test/ui/suggestions/issue-104086-suggest-let.rs
new file mode 100644
index 00000000000..e23109a3be6
--- /dev/null
+++ b/src/test/ui/suggestions/issue-104086-suggest-let.rs
@@ -0,0 +1,10 @@
+// error-pattern: not found in this scope
+
+fn main() {
+    x = x = x;
+    x = y = y = y;
+    x = y = y;
+    x = x = y;
+    x = x; // will suggest add `let`
+    x = y // will suggest add `let`
+}
diff --git a/src/test/ui/suggestions/issue-104086-suggest-let.stderr b/src/test/ui/suggestions/issue-104086-suggest-let.stderr
new file mode 100644
index 00000000000..2af9c142ec6
--- /dev/null
+++ b/src/test/ui/suggestions/issue-104086-suggest-let.stderr
@@ -0,0 +1,81 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:4:5
+   |
+LL |     x = x = x;
+   |     ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:4:9
+   |
+LL |     x = x = x;
+   |         ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:4:13
+   |
+LL |     x = x = x;
+   |             ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:5:5
+   |
+LL |     x = y = y = y;
+   |     ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:5:9
+   |
+LL |     x = y = y = y;
+   |         ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:5:13
+   |
+LL |     x = y = y = y;
+   |             ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:5:17
+   |
+LL |     x = y = y = y;
+   |                 ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:6:5
+   |
+LL |     x = y = y;
+   |     ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:6:9
+   |
+LL |     x = y = y;
+   |         ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:6:13
+   |
+LL |     x = y = y;
+   |             ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:7:5
+   |
+LL |     x = x = y;
+   |     ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:7:9
+   |
+LL |     x = x = y;
+   |         ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/issue-104086-suggest-let.rs:7:13
+   |
+LL |     x = x = y;
+   |             ^ not found in this scope
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0425`.