Skip to content

Commit c69872b

Browse files
committed
add 'is_assign_rhs' to avoid weird suggesting 'let'
1 parent 5689f9c commit c69872b

File tree

3 files changed

+41
-29
lines changed

3 files changed

+41
-29
lines changed

compiler/rustc_resolve/src/late.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ struct DiagnosticMetadata<'ast> {
527527

528528
/// Used to detect possible new binding written without `let` and to provide structured suggestion.
529529
in_assignment: Option<&'ast Expr>,
530+
is_assign_rhs: bool,
530531

531532
/// If we are currently in a trait object definition. Used to point at the bounds when
532533
/// encountering a struct or enum.
@@ -3963,10 +3964,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
39633964
self.resolve_expr(elem, Some(expr));
39643965
self.visit_expr(idx);
39653966
}
3966-
ExprKind::Assign(..) => {
3967-
let old = self.diagnostic_metadata.in_assignment.replace(expr);
3968-
visit::walk_expr(self, expr);
3969-
self.diagnostic_metadata.in_assignment = old;
3967+
ExprKind::Assign(ref lhs, ref rhs, _) => {
3968+
if !self.diagnostic_metadata.is_assign_rhs {
3969+
self.diagnostic_metadata.in_assignment = Some(expr);
3970+
}
3971+
self.visit_expr(lhs);
3972+
self.diagnostic_metadata.is_assign_rhs = true;
3973+
self.diagnostic_metadata.in_assignment = None;
3974+
self.visit_expr(rhs);
3975+
self.diagnostic_metadata.is_assign_rhs = false;
39703976
}
39713977
_ => {
39723978
visit::walk_expr(self, expr);

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,36 +1810,22 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
18101810
false
18111811
}
18121812

1813+
// try to give a suggestion for this pattern: `name = blah`, which is common in other languages
1814+
// suggest `let name = blah` to introduce a new binding
18131815
fn let_binding_suggestion(&mut self, err: &mut Diagnostic, ident_span: Span) -> bool {
1814-
// try to give a suggestion for this pattern: `name = 1`, which is common in other languages
1815-
let mut added_suggestion = false;
1816-
if let Some(Expr { kind: ExprKind::Assign(lhs, rhs, _), .. }) =
1817-
self.diagnostic_metadata.in_assignment
1818-
{
1819-
let is_rhs_assign = matches!(rhs.kind, ExprKind::Assign(..));
1820-
if let ast::ExprKind::Path(None, _) = lhs.kind && !is_rhs_assign {
1821-
let sm = self.r.session.source_map();
1822-
let line_span = sm.span_extend_to_line(ident_span);
1823-
let ident_name = sm.span_to_snippet(ident_span).unwrap();
1824-
// HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros,
1825-
// and avoid some special cases like `x = x = x`
1826-
if let Ok(line) = sm.span_to_snippet(line_span) &&
1827-
let stripped = line.split_whitespace().collect::<String>() &&
1828-
stripped.trim().starts_with(&ident_name) &&
1829-
stripped.matches(&format!("{}=", &ident_name)).count() == 1
1830-
{
1816+
if let Some(Expr { kind: ExprKind::Assign(lhs, .. ), .. }) = self.diagnostic_metadata.in_assignment &&
1817+
let ast::ExprKind::Path(None, _) = lhs.kind {
1818+
if !ident_span.from_expansion() {
18311819
err.span_suggestion_verbose(
18321820
ident_span.shrink_to_lo(),
18331821
"you might have meant to introduce a new binding",
18341822
"let ".to_string(),
18351823
Applicability::MaybeIncorrect,
18361824
);
1837-
added_suggestion = true;
1825+
return true;
18381826
}
18391827
}
1840-
self.diagnostic_metadata.in_assignment = None;
1841-
}
1842-
added_suggestion
1828+
false
18431829
}
18441830

18451831
fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {

src/test/ui/suggestions/issue-104086-suggest-let.stderr

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ error[E0425]: cannot find value `x` in this scope
22
--> $DIR/issue-104086-suggest-let.rs:2:5
33
|
44
LL | x = x = x;
5-
| ^ not found in this scope
5+
| ^
6+
|
7+
help: you might have meant to introduce a new binding
8+
|
9+
LL | let x = x = x;
10+
| +++
611

712
error[E0425]: cannot find value `x` in this scope
813
--> $DIR/issue-104086-suggest-let.rs:2:9
@@ -20,7 +25,12 @@ error[E0425]: cannot find value `x` in this scope
2025
--> $DIR/issue-104086-suggest-let.rs:7:5
2126
|
2227
LL | x = y = y = y;
23-
| ^ not found in this scope
28+
| ^
29+
|
30+
help: you might have meant to introduce a new binding
31+
|
32+
LL | let x = y = y = y;
33+
| +++
2434

2535
error[E0425]: cannot find value `y` in this scope
2636
--> $DIR/issue-104086-suggest-let.rs:7:9
@@ -44,7 +54,12 @@ error[E0425]: cannot find value `x` in this scope
4454
--> $DIR/issue-104086-suggest-let.rs:13:5
4555
|
4656
LL | x = y = y;
47-
| ^ not found in this scope
57+
| ^
58+
|
59+
help: you might have meant to introduce a new binding
60+
|
61+
LL | let x = y = y;
62+
| +++
4863

4964
error[E0425]: cannot find value `y` in this scope
5065
--> $DIR/issue-104086-suggest-let.rs:13:9
@@ -62,7 +77,12 @@ error[E0425]: cannot find value `x` in this scope
6277
--> $DIR/issue-104086-suggest-let.rs:18:5
6378
|
6479
LL | x = x = y;
65-
| ^ not found in this scope
80+
| ^
81+
|
82+
help: you might have meant to introduce a new binding
83+
|
84+
LL | let x = x = y;
85+
| +++
6686

6787
error[E0425]: cannot find value `x` in this scope
6888
--> $DIR/issue-104086-suggest-let.rs:18:9

0 commit comments

Comments
 (0)