diff options
| author | yukang <moorekang@gmail.com> | 2022-11-09 22:00:22 +0800 |
|---|---|---|
| committer | yukang <moorekang@gmail.com> | 2022-11-10 00:43:12 +0800 |
| commit | c69872bb6c0657241a5b3cf8944861dbd3ff7468 (patch) | |
| tree | d2708c03d37a36d4383a23e72e125ee4e57db1bc | |
| parent | 5689f9c679838a921be5a0ac64e0cd13637efc35 (diff) | |
| download | rust-c69872bb6c0657241a5b3cf8944861dbd3ff7468.tar.gz rust-c69872bb6c0657241a5b3cf8944861dbd3ff7468.zip | |
add 'is_assign_rhs' to avoid weird suggesting 'let'
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 28 | ||||
| -rw-r--r-- | src/test/ui/suggestions/issue-104086-suggest-let.stderr | 28 |
3 files changed, 41 insertions, 29 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6d2ee25df32..ede67813883 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -527,6 +527,7 @@ struct DiagnosticMetadata<'ast> { /// Used to detect possible new binding written without `let` and to provide structured suggestion. in_assignment: Option<&'ast Expr>, + is_assign_rhs: bool, /// If we are currently in a trait object definition. Used to point at the bounds when /// encountering a struct or enum. @@ -3963,10 +3964,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.resolve_expr(elem, Some(expr)); self.visit_expr(idx); } - ExprKind::Assign(..) => { - let old = self.diagnostic_metadata.in_assignment.replace(expr); - visit::walk_expr(self, expr); - self.diagnostic_metadata.in_assignment = old; + ExprKind::Assign(ref lhs, ref rhs, _) => { + if !self.diagnostic_metadata.is_assign_rhs { + self.diagnostic_metadata.in_assignment = Some(expr); + } + self.visit_expr(lhs); + self.diagnostic_metadata.is_assign_rhs = true; + self.diagnostic_metadata.in_assignment = None; + self.visit_expr(rhs); + self.diagnostic_metadata.is_assign_rhs = false; } _ => { visit::walk_expr(self, expr); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 9e47f4bc6c1..ec1ac015daf 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1810,36 +1810,22 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { false } + // try to give a suggestion for this pattern: `name = blah`, which is common in other languages + // suggest `let name = blah` to introduce a new binding 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 is_rhs_assign = matches!(rhs.kind, ExprKind::Assign(..)); - 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, - // 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 - { + if let Some(Expr { kind: ExprKind::Assign(lhs, .. ), .. }) = self.diagnostic_metadata.in_assignment && + let ast::ExprKind::Path(None, _) = lhs.kind { + if !ident_span.from_expansion() { err.span_suggestion_verbose( ident_span.shrink_to_lo(), "you might have meant to introduce a new binding", "let ".to_string(), Applicability::MaybeIncorrect, ); - added_suggestion = true; + return true; } } - self.diagnostic_metadata.in_assignment = None; - } - added_suggestion + false } fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> { diff --git a/src/test/ui/suggestions/issue-104086-suggest-let.stderr b/src/test/ui/suggestions/issue-104086-suggest-let.stderr index d37a18f005f..fb4ea3121ac 100644 --- a/src/test/ui/suggestions/issue-104086-suggest-let.stderr +++ b/src/test/ui/suggestions/issue-104086-suggest-let.stderr @@ -2,7 +2,12 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-104086-suggest-let.rs:2:5 | LL | x = x = x; - | ^ not found in this scope + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = x = x; + | +++ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-104086-suggest-let.rs:2:9 @@ -20,7 +25,12 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-104086-suggest-let.rs:7:5 | LL | x = y = y = y; - | ^ not found in this scope + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = y = y = y; + | +++ error[E0425]: cannot find value `y` in this scope --> $DIR/issue-104086-suggest-let.rs:7:9 @@ -44,7 +54,12 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-104086-suggest-let.rs:13:5 | LL | x = y = y; - | ^ not found in this scope + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = y = y; + | +++ error[E0425]: cannot find value `y` in this scope --> $DIR/issue-104086-suggest-let.rs:13:9 @@ -62,7 +77,12 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-104086-suggest-let.rs:18:5 | LL | x = x = y; - | ^ not found in this scope + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = x = y; + | +++ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-104086-suggest-let.rs:18:9 |
