From a3ec43fb761579135c42555b6485cfaea272acee Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 5 Feb 2020 07:09:08 +0100 Subject: [PATCH 1/6] Suggest similar type or module on resolve failure When failing to resolve types or modules, this change tries to provide a suggestion with similarly named candidates. --- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_resolve/lib.rs | 23 ++++++++++- .../ui/macros/macro-inner-attributes.stderr | 5 ++- .../ui/pattern/pattern-error-continue.stderr | 5 ++- src/test/ui/resolve/suggest-type.rs | 19 +++++++++ src/test/ui/resolve/suggest-type.stderr | 39 +++++++++++++++++++ 6 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/resolve/suggest-type.rs create mode 100644 src/test/ui/resolve/suggest-type.stderr diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 075dca8f01d7b..a8d26a382e5ce 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -491,7 +491,7 @@ impl<'a> Resolver<'a> { } /// Lookup typo candidate in scope for a macro or import. - fn early_lookup_typo_candidate( + crate fn early_lookup_typo_candidate( &mut self, scope_set: ScopeSet, parent_scope: &ParentScope<'a>, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2e63c3e170605..1d996c8739a02 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2195,7 +2195,28 @@ impl<'a> Resolver<'a> { return PathResult::NonModule(PartialRes::new(Res::Err)); } } else if i == 0 { - (format!("use of undeclared type or module `{}`", ident), None) + let parent_scope = &ParentScope::module(self.graph_root); + let typo_suggestion = self.early_lookup_typo_candidate( + ScopeSet::AbsolutePath(TypeNS), + parent_scope, + ident, + &|_| true, + ); + if let Some(typo_suggestion) = typo_suggestion { + ( + format!("use of undeclared type or module `{}`", ident), + Some(( + vec![( + ident.span, + format!("{}", typo_suggestion.candidate.as_str()), + )], + String::from("did you mean"), + Applicability::MaybeIncorrect, + )), + ) + } else { + (format!("use of undeclared type or module `{}`", ident), None) + } } else { (format!("could not find `{}` in `{}`", ident, path[i - 1].ident), None) }; diff --git a/src/test/ui/macros/macro-inner-attributes.stderr b/src/test/ui/macros/macro-inner-attributes.stderr index 5e20f106a955b..cdd2298d880f7 100644 --- a/src/test/ui/macros/macro-inner-attributes.stderr +++ b/src/test/ui/macros/macro-inner-attributes.stderr @@ -2,7 +2,10 @@ error[E0433]: failed to resolve: use of undeclared type or module `a` --> $DIR/macro-inner-attributes.rs:17:5 | LL | a::bar(); - | ^ use of undeclared type or module `a` + | ^ + | | + | use of undeclared type or module `a` + | help: did you mean: `b` error: aborting due to previous error diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr index 60f76796c0396..d8605d2dd7a1d 100644 --- a/src/test/ui/pattern/pattern-error-continue.stderr +++ b/src/test/ui/pattern/pattern-error-continue.stderr @@ -2,7 +2,10 @@ error[E0433]: failed to resolve: use of undeclared type or module `E` --> $DIR/pattern-error-continue.rs:33:9 | LL | E::V => {} - | ^ use of undeclared type or module `E` + | ^ + | | + | use of undeclared type or module `E` + | help: did you mean: `A` error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D` --> $DIR/pattern-error-continue.rs:18:9 diff --git a/src/test/ui/resolve/suggest-type.rs b/src/test/ui/resolve/suggest-type.rs new file mode 100644 index 0000000000000..50a6168d87491 --- /dev/null +++ b/src/test/ui/resolve/suggest-type.rs @@ -0,0 +1,19 @@ +use std::ffi::CString; + +mod foo { + fn bar() {} +} + +fn main() { + let _ = Cstring::new("hello").unwrap(); + //~^ ERROR failed to resolve: use of undeclared type or module `Cstring` + + let _ = CStRiNg::new("hello").unwrap(); + //~^ ERROR failed to resolve: use of undeclared type or module `CStRiNg` + + let _ = cStrIng::new("hello").unwrap(); + //~^ ERROR failed to resolve: use of undeclared type or module `cStrIng` + + let _ = foO::bar(); + //~^ ERROR failed to resolve: use of undeclared type or module `foO` +} diff --git a/src/test/ui/resolve/suggest-type.stderr b/src/test/ui/resolve/suggest-type.stderr new file mode 100644 index 0000000000000..cf5950421c738 --- /dev/null +++ b/src/test/ui/resolve/suggest-type.stderr @@ -0,0 +1,39 @@ +error[E0433]: failed to resolve: use of undeclared type or module `Cstring` + --> $DIR/suggest-type.rs:8:13 + | +LL | let _ = Cstring::new("hello").unwrap(); + | ^^^^^^^ + | | + | use of undeclared type or module `Cstring` + | help: did you mean (notice the capitalization): `CString` + +error[E0433]: failed to resolve: use of undeclared type or module `CStRiNg` + --> $DIR/suggest-type.rs:11:13 + | +LL | let _ = CStRiNg::new("hello").unwrap(); + | ^^^^^^^ + | | + | use of undeclared type or module `CStRiNg` + | help: did you mean: `CString` + +error[E0433]: failed to resolve: use of undeclared type or module `cStrIng` + --> $DIR/suggest-type.rs:14:13 + | +LL | let _ = cStrIng::new("hello").unwrap(); + | ^^^^^^^ + | | + | use of undeclared type or module `cStrIng` + | help: did you mean (notice the capitalization): `CString` + +error[E0433]: failed to resolve: use of undeclared type or module `foO` + --> $DIR/suggest-type.rs:17:13 + | +LL | let _ = foO::bar(); + | ^^^ + | | + | use of undeclared type or module `foO` + | help: did you mean (notice the capitalization): `foo` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0433`. From 242dab698df9abfc9d727a2f84225a554356cbb0 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 6 Feb 2020 07:45:05 +0100 Subject: [PATCH 2/6] Move suggestion building to librustc_resolve/diagnostics.rs --- src/librustc_resolve/diagnostics.rs | 27 ++++++++++++++++++++++++++- src/librustc_resolve/lib.rs | 23 +---------------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index a8d26a382e5ce..babef519f0d76 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -491,7 +491,7 @@ impl<'a> Resolver<'a> { } /// Lookup typo candidate in scope for a macro or import. - crate fn early_lookup_typo_candidate( + fn early_lookup_typo_candidate( &mut self, scope_set: ScopeSet, parent_scope: &ParentScope<'a>, @@ -999,6 +999,31 @@ impl<'a> Resolver<'a> { err.emit(); } + + crate fn make_undeclared_type_suggestion( + &mut self, + ident: Ident, + ) -> (String, Option) { + let parent_scope = &ParentScope::module(self.graph_root); + let typo_suggestion = self.early_lookup_typo_candidate( + ScopeSet::AbsolutePath(TypeNS), + parent_scope, + ident, + &|_| true, + ); + if let Some(typo_suggestion) = typo_suggestion { + ( + format!("use of undeclared type or module `{}`", ident), + Some(( + vec![(ident.span, format!("{}", typo_suggestion.candidate.as_str()))], + String::from("did you mean"), + Applicability::MaybeIncorrect, + )), + ) + } else { + (format!("use of undeclared type or module `{}`", ident), None) + } + } } impl<'a, 'b> ImportResolver<'a, 'b> { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 1d996c8739a02..36861d497bf87 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2195,28 +2195,7 @@ impl<'a> Resolver<'a> { return PathResult::NonModule(PartialRes::new(Res::Err)); } } else if i == 0 { - let parent_scope = &ParentScope::module(self.graph_root); - let typo_suggestion = self.early_lookup_typo_candidate( - ScopeSet::AbsolutePath(TypeNS), - parent_scope, - ident, - &|_| true, - ); - if let Some(typo_suggestion) = typo_suggestion { - ( - format!("use of undeclared type or module `{}`", ident), - Some(( - vec![( - ident.span, - format!("{}", typo_suggestion.candidate.as_str()), - )], - String::from("did you mean"), - Applicability::MaybeIncorrect, - )), - ) - } else { - (format!("use of undeclared type or module `{}`", ident), None) - } + self.make_undeclared_type_suggestion(ident) } else { (format!("could not find `{}` in `{}`", ident, path[i - 1].ident), None) }; From 8e0cf4048f9f123fc9fb3179bbeaad704b467e2e Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 15 Feb 2020 11:16:04 +0100 Subject: [PATCH 3/6] Remove tests testing Levenshtein distance --- src/test/ui/resolve/suggest-type.rs | 6 ------ src/test/ui/resolve/suggest-type.stderr | 22 ++-------------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/test/ui/resolve/suggest-type.rs b/src/test/ui/resolve/suggest-type.rs index 50a6168d87491..8a44e19c82ded 100644 --- a/src/test/ui/resolve/suggest-type.rs +++ b/src/test/ui/resolve/suggest-type.rs @@ -8,12 +8,6 @@ fn main() { let _ = Cstring::new("hello").unwrap(); //~^ ERROR failed to resolve: use of undeclared type or module `Cstring` - let _ = CStRiNg::new("hello").unwrap(); - //~^ ERROR failed to resolve: use of undeclared type or module `CStRiNg` - - let _ = cStrIng::new("hello").unwrap(); - //~^ ERROR failed to resolve: use of undeclared type or module `cStrIng` - let _ = foO::bar(); //~^ ERROR failed to resolve: use of undeclared type or module `foO` } diff --git a/src/test/ui/resolve/suggest-type.stderr b/src/test/ui/resolve/suggest-type.stderr index cf5950421c738..8847efde634dd 100644 --- a/src/test/ui/resolve/suggest-type.stderr +++ b/src/test/ui/resolve/suggest-type.stderr @@ -7,26 +7,8 @@ LL | let _ = Cstring::new("hello").unwrap(); | use of undeclared type or module `Cstring` | help: did you mean (notice the capitalization): `CString` -error[E0433]: failed to resolve: use of undeclared type or module `CStRiNg` - --> $DIR/suggest-type.rs:11:13 - | -LL | let _ = CStRiNg::new("hello").unwrap(); - | ^^^^^^^ - | | - | use of undeclared type or module `CStRiNg` - | help: did you mean: `CString` - -error[E0433]: failed to resolve: use of undeclared type or module `cStrIng` - --> $DIR/suggest-type.rs:14:13 - | -LL | let _ = cStrIng::new("hello").unwrap(); - | ^^^^^^^ - | | - | use of undeclared type or module `cStrIng` - | help: did you mean (notice the capitalization): `CString` - error[E0433]: failed to resolve: use of undeclared type or module `foO` - --> $DIR/suggest-type.rs:17:13 + --> $DIR/suggest-type.rs:11:13 | LL | let _ = foO::bar(); | ^^^ @@ -34,6 +16,6 @@ LL | let _ = foO::bar(); | use of undeclared type or module `foO` | help: did you mean (notice the capitalization): `foo` -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0433`. From 8a468d2f0e9a987dd33030d2299b3ace762c7b66 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 15 Feb 2020 11:31:00 +0100 Subject: [PATCH 4/6] Re-use typo suggestion wording --- src/librustc_resolve/diagnostics.rs | 17 ++++++++++------- .../ui/macros/macro-inner-attributes.stderr | 2 +- .../ui/pattern/pattern-error-continue.stderr | 2 +- src/test/ui/resolve/suggest-type.stderr | 4 ++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index babef519f0d76..9509e1d5695a9 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -797,6 +797,14 @@ impl<'a> Resolver<'a> { } } + fn typo_suggestion_text(&self, suggestion: &TypoSuggestion) -> String { + format!( + "{} {} with a similar name exists", + suggestion.res.article(), + suggestion.res.descr() + ) + } + crate fn add_typo_suggestion( &self, err: &mut DiagnosticBuilder<'_>, @@ -809,14 +817,9 @@ impl<'a> Resolver<'a> { return false; } - let msg = format!( - "{} {} with a similar name exists", - suggestion.res.article(), - suggestion.res.descr() - ); err.span_suggestion( span, - &msg, + &self.typo_suggestion_text(&suggestion), suggestion.candidate.to_string(), Applicability::MaybeIncorrect, ); @@ -1016,7 +1019,7 @@ impl<'a> Resolver<'a> { format!("use of undeclared type or module `{}`", ident), Some(( vec![(ident.span, format!("{}", typo_suggestion.candidate.as_str()))], - String::from("did you mean"), + self.typo_suggestion_text(&typo_suggestion), Applicability::MaybeIncorrect, )), ) diff --git a/src/test/ui/macros/macro-inner-attributes.stderr b/src/test/ui/macros/macro-inner-attributes.stderr index cdd2298d880f7..d13e4b178c37c 100644 --- a/src/test/ui/macros/macro-inner-attributes.stderr +++ b/src/test/ui/macros/macro-inner-attributes.stderr @@ -5,7 +5,7 @@ LL | a::bar(); | ^ | | | use of undeclared type or module `a` - | help: did you mean: `b` + | help: a module with a similar name exists: `b` error: aborting due to previous error diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr index d8605d2dd7a1d..3aaf644aefb00 100644 --- a/src/test/ui/pattern/pattern-error-continue.stderr +++ b/src/test/ui/pattern/pattern-error-continue.stderr @@ -5,7 +5,7 @@ LL | E::V => {} | ^ | | | use of undeclared type or module `E` - | help: did you mean: `A` + | help: an enum with a similar name exists: `A` error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D` --> $DIR/pattern-error-continue.rs:18:9 diff --git a/src/test/ui/resolve/suggest-type.stderr b/src/test/ui/resolve/suggest-type.stderr index 8847efde634dd..45301bf345977 100644 --- a/src/test/ui/resolve/suggest-type.stderr +++ b/src/test/ui/resolve/suggest-type.stderr @@ -5,7 +5,7 @@ LL | let _ = Cstring::new("hello").unwrap(); | ^^^^^^^ | | | use of undeclared type or module `Cstring` - | help: did you mean (notice the capitalization): `CString` + | help: a struct with a similar name exists (notice the capitalization): `CString` error[E0433]: failed to resolve: use of undeclared type or module `foO` --> $DIR/suggest-type.rs:11:13 @@ -14,7 +14,7 @@ LL | let _ = foO::bar(); | ^^^ | | | use of undeclared type or module `foO` - | help: did you mean (notice the capitalization): `foo` + | help: a module with a similar name exists (notice the capitalization): `foo` error: aborting due to 2 previous errors From 9863a9bb1b44a22d40bb8aa9b514356728c98b77 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 15 Feb 2020 14:29:34 +0100 Subject: [PATCH 5/6] Add error annotations for existing tests --- src/test/ui/resolve/suggest-type.rs | 4 ++++ src/test/ui/resolve/suggest-type.stderr | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/ui/resolve/suggest-type.rs b/src/test/ui/resolve/suggest-type.rs index 8a44e19c82ded..888ec6490dff6 100644 --- a/src/test/ui/resolve/suggest-type.rs +++ b/src/test/ui/resolve/suggest-type.rs @@ -7,7 +7,11 @@ mod foo { fn main() { let _ = Cstring::new("hello").unwrap(); //~^ ERROR failed to resolve: use of undeclared type or module `Cstring` + //~| HELP a struct with a similar name exists + //~| SUGGESTION CString let _ = foO::bar(); //~^ ERROR failed to resolve: use of undeclared type or module `foO` + //~| HELP a module with a similar name exists + //~| SUGGESTION foo } diff --git a/src/test/ui/resolve/suggest-type.stderr b/src/test/ui/resolve/suggest-type.stderr index 45301bf345977..8d3de9d0fc73a 100644 --- a/src/test/ui/resolve/suggest-type.stderr +++ b/src/test/ui/resolve/suggest-type.stderr @@ -8,7 +8,7 @@ LL | let _ = Cstring::new("hello").unwrap(); | help: a struct with a similar name exists (notice the capitalization): `CString` error[E0433]: failed to resolve: use of undeclared type or module `foO` - --> $DIR/suggest-type.rs:11:13 + --> $DIR/suggest-type.rs:13:13 | LL | let _ = foO::bar(); | ^^^ From 3c6a203baf1331b92741689aa63220e1f0982dd6 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 16 Feb 2020 10:10:52 +0100 Subject: [PATCH 6/6] Fix suggestion inside module --- src/librustc_resolve/diagnostics.rs | 5 +++-- src/librustc_resolve/lib.rs | 2 +- src/test/ui/resolve/suggest-type.rs | 9 ++++++++- src/test/ui/resolve/suggest-type.stderr | 15 ++++++++++++--- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 9509e1d5695a9..67d2c3743270a 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -1006,10 +1006,11 @@ impl<'a> Resolver<'a> { crate fn make_undeclared_type_suggestion( &mut self, ident: Ident, + parent_scope: &ParentScope<'a>, + ns: Namespace, ) -> (String, Option) { - let parent_scope = &ParentScope::module(self.graph_root); let typo_suggestion = self.early_lookup_typo_candidate( - ScopeSet::AbsolutePath(TypeNS), + ScopeSet::All(ns, false), parent_scope, ident, &|_| true, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 36861d497bf87..1a66ef3a7aeea 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2195,7 +2195,7 @@ impl<'a> Resolver<'a> { return PathResult::NonModule(PartialRes::new(Res::Err)); } } else if i == 0 { - self.make_undeclared_type_suggestion(ident) + self.make_undeclared_type_suggestion(ident, &parent_scope, ns) } else { (format!("could not find `{}` in `{}`", ident, path[i - 1].ident), None) }; diff --git a/src/test/ui/resolve/suggest-type.rs b/src/test/ui/resolve/suggest-type.rs index 888ec6490dff6..2a6bf7c9fd19f 100644 --- a/src/test/ui/resolve/suggest-type.rs +++ b/src/test/ui/resolve/suggest-type.rs @@ -1,7 +1,14 @@ use std::ffi::CString; mod foo { - fn bar() {} + use std::collections::HashMap; + + fn bar() { + let _ = HashNap::new(); + //~^ ERROR failed to resolve: use of undeclared type or module `HashNap` + //~| HELP a struct with a similar name exists + //~| SUGGESTION HashMap + } } fn main() { diff --git a/src/test/ui/resolve/suggest-type.stderr b/src/test/ui/resolve/suggest-type.stderr index 8d3de9d0fc73a..201334b301e32 100644 --- a/src/test/ui/resolve/suggest-type.stderr +++ b/src/test/ui/resolve/suggest-type.stderr @@ -1,5 +1,14 @@ +error[E0433]: failed to resolve: use of undeclared type or module `HashNap` + --> $DIR/suggest-type.rs:7:17 + | +LL | let _ = HashNap::new(); + | ^^^^^^^ + | | + | use of undeclared type or module `HashNap` + | help: a struct with a similar name exists: `HashMap` + error[E0433]: failed to resolve: use of undeclared type or module `Cstring` - --> $DIR/suggest-type.rs:8:13 + --> $DIR/suggest-type.rs:15:13 | LL | let _ = Cstring::new("hello").unwrap(); | ^^^^^^^ @@ -8,7 +17,7 @@ LL | let _ = Cstring::new("hello").unwrap(); | help: a struct with a similar name exists (notice the capitalization): `CString` error[E0433]: failed to resolve: use of undeclared type or module `foO` - --> $DIR/suggest-type.rs:13:13 + --> $DIR/suggest-type.rs:20:13 | LL | let _ = foO::bar(); | ^^^ @@ -16,6 +25,6 @@ LL | let _ = foO::bar(); | use of undeclared type or module `foO` | help: a module with a similar name exists (notice the capitalization): `foo` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0433`.