From 42e9f2daf3d5ea55080c40c48f2695dfee491f78 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sat, 21 May 2022 12:55:37 +0900 Subject: [PATCH 1/2] typo suggestion for a variable with a name similar to struct fields --- .../rustc_resolve/src/late/diagnostics.rs | 15 ++++---- ...iable-with-name-similar-to-struct-field.rs | 19 ++++++++++ ...e-with-name-similar-to-struct-field.stderr | 36 +++++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs create mode 100644 src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 4f07d0076f1..42063ac940a 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -443,6 +443,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ); } } + // Try Levenshtein algorithm. + let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected); if path.len() == 1 && self.self_type_is_available() { if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected) { let self_is_available = self.self_value_is_available(path[0].ident.span); @@ -452,18 +454,19 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_suggestion( span, "you might have meant to use the available field", - format!("self.{}", path_str), + format!("self.{path_str}"), Applicability::MachineApplicable, ); } else { err.span_label(span, "a field by this name exists in `Self`"); } + self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span); } AssocSuggestion::MethodWithSelf if self_is_available => { err.span_suggestion( span, "you might have meant to call the method", - format!("self.{}", path_str), + format!("self.{path_str}"), Applicability::MachineApplicable, ); } @@ -474,7 +477,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_suggestion( span, &format!("you might have meant to {}", candidate.action()), - format!("Self::{}", path_str), + format!("Self::{path_str}"), Applicability::MachineApplicable, ); } @@ -493,16 +496,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.span_suggestion( call_span, - &format!("try calling `{}` as a method", ident), - format!("self.{}({})", path_str, args_snippet), + &format!("try calling `{ident}` as a method"), + format!("self.{path_str}({args_snippet})"), Applicability::MachineApplicable, ); return (err, candidates); } } - // Try Levenshtein algorithm. - let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected); // Try context-dependent help if relaxed lookup didn't work. if let Some(res) = res { if self.smart_resolve_context_dependent_help( diff --git a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs new file mode 100644 index 00000000000..7db4dd2f49c --- /dev/null +++ b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs @@ -0,0 +1,19 @@ +struct Foo { + config: String, +} + +impl Foo { + fn new(cofig: String) -> Self { + Self { config } //~ Error cannot find value `config` in this scope + } + + fn do_something(cofig: String) { + println!("{config}"); //~ Error cannot find value `config` in this scope + } + + fn self_is_available(self, cofig: String) { + println!("{config}"); //~ Error cannot find value `config` in this scope + } +} + +fn main() {} diff --git a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr new file mode 100644 index 00000000000..6e9fe6d9c46 --- /dev/null +++ b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr @@ -0,0 +1,36 @@ +error[E0425]: cannot find value `config` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:7:16 + | +LL | Self { config } + | ^^^^^^ + | | + | a field by this name exists in `Self` + | help: a local variable with a similar name exists: `cofig` + +error[E0425]: cannot find value `config` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:11:20 + | +LL | println!("{config}"); + | ^^^^^^ + | | + | a field by this name exists in `Self` + | help: a local variable with a similar name exists: `cofig` + +error[E0425]: cannot find value `config` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:15:20 + | +LL | println!("{config}"); + | ^^^^^^ + | +help: you might have meant to use the available field + | +LL | println!("{self.config}"); + | ~~~~~~~~~~~ +help: a local variable with a similar name exists + | +LL | println!("{cofig}"); + | ~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. From 39caed08ae56304b281cfb538020430e48cf499d Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 23 May 2022 19:58:20 +0900 Subject: [PATCH 2/2] add typo suggestions for all `AssocSuggestion` variants --- .../rustc_resolve/src/late/diagnostics.rs | 2 +- ...iable-with-name-similar-to-struct-field.rs | 31 +++++++- ...e-with-name-similar-to-struct-field.stderr | 77 ++++++++++++++++++- 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 42063ac940a..9b5a69e4bb2 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -460,7 +460,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } else { err.span_label(span, "a field by this name exists in `Self`"); } - self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span); } AssocSuggestion::MethodWithSelf if self_is_available => { err.span_suggestion( @@ -482,6 +481,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ); } } + self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span); return (err, candidates); } diff --git a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs index 7db4dd2f49c..ecd3f588119 100644 --- a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs +++ b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs @@ -1,8 +1,8 @@ -struct Foo { +struct A { config: String, } -impl Foo { +impl A { fn new(cofig: String) -> Self { Self { config } //~ Error cannot find value `config` in this scope } @@ -16,4 +16,31 @@ impl Foo { } } +trait B { + const BAR: u32 = 3; + type Baz; + fn bar(&self); + fn baz(&self) {} + fn bah() {} +} + +impl B for Box { + type Baz = String; + fn bar(&self) { + // let baz = 3; + baz(); + //~^ ERROR cannot find function `baz` + bah; + //~^ ERROR cannot find value `bah` + BAR; + //~^ ERROR cannot find value `BAR` in this scope + let foo: Baz = "".to_string(); + //~^ ERROR cannot find type `Baz` in this scope + } +} + +fn ba() {} +const BARR: u32 = 3; +type Bar = String; + fn main() {} diff --git a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr index 6e9fe6d9c46..0b0a37f246c 100644 --- a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr +++ b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr @@ -31,6 +31,79 @@ help: a local variable with a similar name exists LL | println!("{cofig}"); | ~~~~~ -error: aborting due to 3 previous errors +error[E0425]: cannot find function `baz` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:31:9 + | +LL | baz(); + | ^^^ +... +LL | fn ba() {} + | ------- similarly named function `ba` defined here + | +help: you might have meant to call the method + | +LL | self.baz(); + | ~~~~~~~~ +help: a function with a similar name exists + | +LL | ba(); + | ~~ -For more information about this error, try `rustc --explain E0425`. +error[E0425]: cannot find value `bah` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:33:9 + | +LL | bah; + | ^^^ +... +LL | fn ba() {} + | ------- similarly named function `ba` defined here + | +help: you might have meant to call the associated function + | +LL | Self::bah; + | ~~~~~~~~~ +help: a function with a similar name exists + | +LL | ba; + | ~~ + +error[E0425]: cannot find value `BAR` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:35:9 + | +LL | BAR; + | ^^^ +... +LL | const BARR: u32 = 3; + | -------------------- similarly named constant `BARR` defined here + | +help: you might have meant to use the associated `const` + | +LL | Self::BAR; + | ~~~~~~~~~ +help: a constant with a similar name exists + | +LL | BARR; + | ~~~~ + +error[E0412]: cannot find type `Baz` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:37:18 + | +LL | let foo: Baz = "".to_string(); + | ^^^ +... +LL | type Bar = String; + | ------------------ similarly named type alias `Bar` defined here + | +help: you might have meant to use the associated type + | +LL | let foo: Self::Baz = "".to_string(); + | ~~~~~~~~~ +help: a type alias with a similar name exists + | +LL | let foo: Bar = "".to_string(); + | ~~~ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`.