From be0501f568c1cd68ac4e65507ecf458f8305ba23 Mon Sep 17 00:00:00 2001 From: Yoshiki Matsuda Date: Sun, 8 May 2022 18:11:56 +0900 Subject: [PATCH 1/5] suggest similarly named type when use of undeclared crate or module --- compiler/rustc_resolve/src/diagnostics.rs | 95 +++++++++++++++++-- .../builtin-prelude-no-accidents.stderr | 5 +- .../macros/macro_path_as_generic_bound.stderr | 5 +- .../resolve/suggest-type-to-lowercase-path.rs | 9 ++ .../suggest-type-to-lowercase-path.stderr | 12 +++ .../type-ascription-instead-of-path.stderr | 5 +- 6 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/resolve/suggest-type-to-lowercase-path.rs create mode 100644 src/test/ui/resolve/suggest-type-to-lowercase-path.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index a820f700869b2..559a10283d557 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -28,7 +28,7 @@ use rustc_span::{BytePos, Span}; use tracing::debug; use crate::imports::{Import, ImportKind, ImportResolver}; -use crate::late::{PatternSource, Rib}; +use crate::late::{PatternSource, Rib, RibKind}; use crate::path_names_to_string; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize}; use crate::{HasGenericParams, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot}; @@ -1825,6 +1825,75 @@ impl<'a> Resolver<'a> { } } + fn find_similarly_named_type( + &mut self, + ident: Symbol, + ribs: Option<&PerNS>>>, + ) -> Option { + fn is_type_candidate(res: Res) -> bool { + matches!( + res, + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Trait + | DefKind::TraitAlias + | DefKind::TyAlias + | DefKind::AssocTy + | DefKind::TyParam + | DefKind::OpaqueTy + | DefKind::ForeignTy, + _ + ) | Res::PrimTy(..) + | Res::SelfTy { .. } + ) + } + + let mut names = Vec::new(); + if let Some(ribs) = ribs { + // Search in lexical scope. + // Walk backwards up the ribs in scope and collect candidates. + for rib in ribs[TypeNS].iter().rev() { + for (ident, res) in &rib.bindings { + if is_type_candidate(*res) { + names.push(TypoSuggestion::typo_from_res(ident.name, *res)); + } + } + // Items in scope + if let RibKind::ModuleRibKind(module) = rib.kind { + // Items from this module + self.add_module_candidates(module, &mut names, &is_type_candidate); + + if let ModuleKind::Block(..) = module.kind { + // We can through blocks + } else { + // Items from the prelude + if !module.no_implicit_prelude { + if let Some(prelude) = self.prelude { + self.add_module_candidates(prelude, &mut names, &is_type_candidate); + } + } + break; + } + } + } + // Add primitive types + names.extend(PrimTy::ALL.iter().map(|prim_ty| { + TypoSuggestion::typo_from_res(prim_ty.name(), Res::PrimTy(*prim_ty)) + })) + } + + let mut names = names.iter().map(|sugg| sugg.candidate).collect::>(); + names.sort(); + names.dedup(); + + match find_best_match_for_name(&names, ident, None) { + Some(sugg) if sugg == ident => None, + sugg => sugg, + } + } + pub(crate) fn report_path_resolution_error( &mut self, path: &[Segment], @@ -2001,16 +2070,22 @@ impl<'a> Resolver<'a> { String::from("add `extern crate alloc` to use the `alloc` crate"), Applicability::MaybeIncorrect, )) + } else if let Some(sugg) = + self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module) + { + Some(( + vec![(ident.span, sugg.to_string())], + String::from("there is a crate or module with a similar name"), + Applicability::MaybeIncorrect, + )) } else { - self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map( - |sugg| { - ( - vec![(ident.span, sugg.to_string())], - String::from("there is a crate or module with a similar name"), - Applicability::MaybeIncorrect, - ) - }, - ) + self.find_similarly_named_type(ident.name, ribs).map(|sugg| { + ( + vec![(ident.span, sugg.to_string())], + String::from("there is a type with a similar name"), + Applicability::MaybeIncorrect, + ) + }) }; (format!("use of undeclared crate or module `{}`", ident), suggestion) } diff --git a/src/test/ui/macros/builtin-prelude-no-accidents.stderr b/src/test/ui/macros/builtin-prelude-no-accidents.stderr index 56af618d484b5..773ef53fcd322 100644 --- a/src/test/ui/macros/builtin-prelude-no-accidents.stderr +++ b/src/test/ui/macros/builtin-prelude-no-accidents.stderr @@ -14,7 +14,10 @@ error[E0433]: failed to resolve: use of undeclared crate or module `vec` --> $DIR/builtin-prelude-no-accidents.rs:7:14 | LL | type B = vec::Vec; - | ^^^ use of undeclared crate or module `vec` + | ^^^ + | | + | use of undeclared crate or module `vec` + | help: there is a type with a similar name (notice the capitalization): `Vec` error: aborting due to 3 previous errors diff --git a/src/test/ui/macros/macro_path_as_generic_bound.stderr b/src/test/ui/macros/macro_path_as_generic_bound.stderr index 00d954d24f380..03c568f474631 100644 --- a/src/test/ui/macros/macro_path_as_generic_bound.stderr +++ b/src/test/ui/macros/macro_path_as_generic_bound.stderr @@ -2,7 +2,10 @@ error[E0433]: failed to resolve: use of undeclared crate or module `m` --> $DIR/macro_path_as_generic_bound.rs:7:6 | LL | foo!(m::m2::A); - | ^ use of undeclared crate or module `m` + | ^ + | | + | use of undeclared crate or module `m` + | help: there is a type with a similar name: `T` error: aborting due to previous error diff --git a/src/test/ui/resolve/suggest-type-to-lowercase-path.rs b/src/test/ui/resolve/suggest-type-to-lowercase-path.rs new file mode 100644 index 0000000000000..1235a46367a4c --- /dev/null +++ b/src/test/ui/resolve/suggest-type-to-lowercase-path.rs @@ -0,0 +1,9 @@ +// Beginners often write an incorrect type name whose initial letter is +// a lowercase while the correct one is an uppercase. +// (e.g. `string` instead of `String`) +// This tests that we suggest the latter when we encounter the former. + +fn main() { + let _ = string::new(); + //~^ ERROR failed to resolve: use of undeclared crate or module `string` +} diff --git a/src/test/ui/resolve/suggest-type-to-lowercase-path.stderr b/src/test/ui/resolve/suggest-type-to-lowercase-path.stderr new file mode 100644 index 0000000000000..7b01b683aa88e --- /dev/null +++ b/src/test/ui/resolve/suggest-type-to-lowercase-path.stderr @@ -0,0 +1,12 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `string` + --> $DIR/suggest-type-to-lowercase-path.rs:7:13 + | +LL | let _ = string::new(); + | ^^^^^^ + | | + | use of undeclared crate or module `string` + | help: there is a type with a similar name (notice the capitalization): `String` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path.stderr index 518660cfa1686..66bb14ceac1f7 100644 --- a/src/test/ui/suggestions/type-ascription-instead-of-path.stderr +++ b/src/test/ui/suggestions/type-ascription-instead-of-path.stderr @@ -2,7 +2,10 @@ error[E0433]: failed to resolve: use of undeclared crate or module `io` --> $DIR/type-ascription-instead-of-path.rs:2:9 | LL | std:io::stdin(); - | ^^ use of undeclared crate or module `io` + | ^^ + | | + | use of undeclared crate or module `io` + | help: there is a type with a similar name: `i8` error[E0423]: expected value, found crate `std` --> $DIR/type-ascription-instead-of-path.rs:2:5 From 8788df515af91af50c8fd21dc4e66d9cd9bfaa77 Mon Sep 17 00:00:00 2001 From: Yoshiki Matsuda Date: Mon, 9 May 2022 00:27:25 +0900 Subject: [PATCH 2/5] suggest similarly named type when use of undeclared type --- compiler/rustc_resolve/src/diagnostics.rs | 8 +++++++- .../generic-associated-types/equality-bound.stderr | 5 ++++- src/test/ui/pattern/pattern-error-continue.stderr | 5 ++++- src/test/ui/resolve/suggest-similar-type-name.rs | 10 ++++++++++ src/test/ui/resolve/suggest-similar-type-name.stderr | 12 ++++++++++++ 5 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/resolve/suggest-similar-type-name.rs create mode 100644 src/test/ui/resolve/suggest-similar-type-name.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 559a10283d557..ecea620e8d5e6 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2059,7 +2059,13 @@ impl<'a> Resolver<'a> { Applicability::MaybeIncorrect, )) } else { - None + self.find_similarly_named_type(ident.name, ribs).map(|sugg| { + ( + vec![(ident.span, sugg.to_string())], + String::from("there is a type with a similar name"), + Applicability::MaybeIncorrect, + ) + }) }; (format!("use of undeclared type `{}`", ident), suggestion) diff --git a/src/test/ui/generic-associated-types/equality-bound.stderr b/src/test/ui/generic-associated-types/equality-bound.stderr index d78f7a7fbcee1..e432c30d59b7e 100644 --- a/src/test/ui/generic-associated-types/equality-bound.stderr +++ b/src/test/ui/generic-associated-types/equality-bound.stderr @@ -36,7 +36,10 @@ error[E0433]: failed to resolve: use of undeclared type `I` --> $DIR/equality-bound.rs:9:41 | LL | fn sum3(i: J) -> i32 where I::Item = i32 { - | ^ use of undeclared type `I` + | ^ + | | + | use of undeclared type `I` + | help: there is a type with a similar name: `J` error: aborting due to 4 previous errors diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr index 4c2eff63ab5e8..651d1eacb6859 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 `E` --> $DIR/pattern-error-continue.rs:33:9 | LL | E::V => {} - | ^ use of undeclared type `E` + | ^ + | | + | use of undeclared type `E` + | help: there is a type with a similar name: `Eq` 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-similar-type-name.rs b/src/test/ui/resolve/suggest-similar-type-name.rs new file mode 100644 index 0000000000000..18c1210c9b534 --- /dev/null +++ b/src/test/ui/resolve/suggest-similar-type-name.rs @@ -0,0 +1,10 @@ +struct FooType {} + +impl FooType { + fn bar() {} +} + +fn main() { + FooTyp::bar() + //~^ ERROR failed to resolve: use of undeclared type `FooTyp` +} diff --git a/src/test/ui/resolve/suggest-similar-type-name.stderr b/src/test/ui/resolve/suggest-similar-type-name.stderr new file mode 100644 index 0000000000000..c99c8c02c9fb9 --- /dev/null +++ b/src/test/ui/resolve/suggest-similar-type-name.stderr @@ -0,0 +1,12 @@ +error[E0433]: failed to resolve: use of undeclared type `FooTyp` + --> $DIR/suggest-similar-type-name.rs:8:5 + | +LL | FooTyp::bar() + | ^^^^^^ + | | + | use of undeclared type `FooTyp` + | help: there is a type with a similar name: `FooType` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. From 9e75730b5467c1233cb26d4331224355756cebda Mon Sep 17 00:00:00 2001 From: Yoshiki Matsuda Date: Tue, 10 May 2022 00:59:22 +0900 Subject: [PATCH 3/5] print the appropriate description for the suggestion --- compiler/rustc_hir/src/def.rs | 10 +++--- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 34 ++++++++++++++----- compiler/rustc_span/src/hygiene.rs | 2 +- .../equality-bound.stderr | 2 +- .../builtin-prelude-no-accidents.stderr | 2 +- .../macros/macro_path_as_generic_bound.stderr | 2 +- .../ui/pattern/pattern-error-continue.stderr | 2 +- .../resolve/suggest-similar-type-name.stderr | 2 +- .../suggest-type-to-lowercase-path.stderr | 2 +- .../type-ascription-instead-of-path.stderr | 2 +- 11 files changed, 39 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index d0893cd09d8db..23b4303da28e3 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -11,7 +11,7 @@ use std::array::IntoIter; use std::fmt::Debug; /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum CtorOf { /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct. @@ -21,7 +21,7 @@ pub enum CtorOf { } /// What kind of constructor something is. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum CtorKind { /// Constructor function automatically created by a tuple struct/variant. @@ -33,7 +33,7 @@ pub enum CtorKind { } /// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum NonMacroAttrKind { /// Single-segment attribute defined by the language (`#[inline]`) @@ -50,7 +50,7 @@ pub enum NonMacroAttrKind { } /// What kind of definition something is; e.g., `mod` vs `struct`. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum DefKind { // Type namespace @@ -297,7 +297,7 @@ impl DefKind { /// - the call to `str_to_string` will resolve to [`Res::Def`], with the [`DefId`] /// pointing to the definition of `str_to_string` in the current crate. // -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum Res { /// Definition having a unique ID (`DefId`), corresponds to something defined in user code. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 48a41c8bd245a..0e8bdfd32f8d9 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2400,7 +2400,7 @@ impl<'hir> Ty<'hir> { } /// Not represented directly in the AST; referred to by name through a `ty_path`. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum PrimTy { Int(IntTy), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index ecea620e8d5e6..adc4674d66d42 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -4,7 +4,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_ID}; use rustc_ast_pretty::pprust; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::struct_span_err; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_feature::BUILTIN_ATTRIBUTES; @@ -48,6 +48,7 @@ pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability); /// similarly named label and whether or not it is reachable. pub(crate) type LabelSuggestion = (Ident, bool); +#[derive(Clone, PartialEq, Eq)] pub(crate) enum SuggestionTarget { /// The target has a similar name as the name used by the programmer (probably a typo) SimilarlyNamed, @@ -55,6 +56,7 @@ pub(crate) enum SuggestionTarget { SingleItem, } +#[derive(Clone, PartialEq, Eq)] pub(crate) struct TypoSuggestion { pub candidate: Symbol, pub res: Res, @@ -1829,7 +1831,7 @@ impl<'a> Resolver<'a> { &mut self, ident: Symbol, ribs: Option<&PerNS>>>, - ) -> Option { + ) -> Option { fn is_type_candidate(res: Res) -> bool { matches!( res, @@ -1884,14 +1886,20 @@ impl<'a> Resolver<'a> { })) } - let mut names = names.iter().map(|sugg| sugg.candidate).collect::>(); - names.sort(); + // We sort names here to ensure that the suggestion is deterministic. + // (Notice that there may be a pair of TypoSuggestions whose Symbols + // are same but Res are different.) + names.sort_by_key(|name| (name.candidate, name.res)); names.dedup(); + let symbols = names.iter().map(|sugg| sugg.candidate).collect::>(); + let typo_suggestions: FxHashMap = + names.into_iter().map(|typo_sugg| (typo_sugg.candidate, typo_sugg)).collect(); - match find_best_match_for_name(&names, ident, None) { + match find_best_match_for_name(&symbols, ident, None) { Some(sugg) if sugg == ident => None, sugg => sugg, } + .map(|sugg| typo_suggestions.get(&sugg).unwrap().clone()) } pub(crate) fn report_path_resolution_error( @@ -2061,8 +2069,12 @@ impl<'a> Resolver<'a> { } else { self.find_similarly_named_type(ident.name, ribs).map(|sugg| { ( - vec![(ident.span, sugg.to_string())], - String::from("there is a type with a similar name"), + vec![(ident.span, sugg.candidate.to_string())], + format!( + "there is {} {} with a similar name", + sugg.res.article(), + sugg.res.descr(), + ), Applicability::MaybeIncorrect, ) }) @@ -2087,8 +2099,12 @@ impl<'a> Resolver<'a> { } else { self.find_similarly_named_type(ident.name, ribs).map(|sugg| { ( - vec![(ident.span, sugg.to_string())], - String::from("there is a type with a similar name"), + vec![(ident.span, sugg.candidate.to_string())], + format!( + "there is {} {} with a similar name", + sugg.res.article(), + sugg.res.descr() + ), Applicability::MaybeIncorrect, ) }) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index e169d3c7cfb7c..06730c3eb559d 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1073,7 +1073,7 @@ impl ExpnKind { } /// The kind of macro invocation or definition. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum MacroKind { /// A bang macro `foo!()`. diff --git a/src/test/ui/generic-associated-types/equality-bound.stderr b/src/test/ui/generic-associated-types/equality-bound.stderr index e432c30d59b7e..ba17f97044b7b 100644 --- a/src/test/ui/generic-associated-types/equality-bound.stderr +++ b/src/test/ui/generic-associated-types/equality-bound.stderr @@ -39,7 +39,7 @@ LL | fn sum3(i: J) -> i32 where I::Item = i32 { | ^ | | | use of undeclared type `I` - | help: there is a type with a similar name: `J` + | help: there is a type parameter with a similar name: `J` error: aborting due to 4 previous errors diff --git a/src/test/ui/macros/builtin-prelude-no-accidents.stderr b/src/test/ui/macros/builtin-prelude-no-accidents.stderr index 773ef53fcd322..858cf7c7649cf 100644 --- a/src/test/ui/macros/builtin-prelude-no-accidents.stderr +++ b/src/test/ui/macros/builtin-prelude-no-accidents.stderr @@ -17,7 +17,7 @@ LL | type B = vec::Vec; | ^^^ | | | use of undeclared crate or module `vec` - | help: there is a type with a similar name (notice the capitalization): `Vec` + | help: there is a struct with a similar name (notice the capitalization): `Vec` error: aborting due to 3 previous errors diff --git a/src/test/ui/macros/macro_path_as_generic_bound.stderr b/src/test/ui/macros/macro_path_as_generic_bound.stderr index 03c568f474631..280633518b72a 100644 --- a/src/test/ui/macros/macro_path_as_generic_bound.stderr +++ b/src/test/ui/macros/macro_path_as_generic_bound.stderr @@ -5,7 +5,7 @@ LL | foo!(m::m2::A); | ^ | | | use of undeclared crate or module `m` - | help: there is a type with a similar name: `T` + | help: there is a type parameter with a similar name: `T` 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 651d1eacb6859..56b4089f2549b 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 `E` - | help: there is a type with a similar name: `Eq` + | help: there is a trait with a similar name: `Eq` 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-similar-type-name.stderr b/src/test/ui/resolve/suggest-similar-type-name.stderr index c99c8c02c9fb9..e5f27a899383b 100644 --- a/src/test/ui/resolve/suggest-similar-type-name.stderr +++ b/src/test/ui/resolve/suggest-similar-type-name.stderr @@ -5,7 +5,7 @@ LL | FooTyp::bar() | ^^^^^^ | | | use of undeclared type `FooTyp` - | help: there is a type with a similar name: `FooType` + | help: there is a struct with a similar name: `FooType` error: aborting due to previous error diff --git a/src/test/ui/resolve/suggest-type-to-lowercase-path.stderr b/src/test/ui/resolve/suggest-type-to-lowercase-path.stderr index 7b01b683aa88e..e37fe3ab74b48 100644 --- a/src/test/ui/resolve/suggest-type-to-lowercase-path.stderr +++ b/src/test/ui/resolve/suggest-type-to-lowercase-path.stderr @@ -5,7 +5,7 @@ LL | let _ = string::new(); | ^^^^^^ | | | use of undeclared crate or module `string` - | help: there is a type with a similar name (notice the capitalization): `String` + | help: there is a struct with a similar name (notice the capitalization): `String` error: aborting due to previous error diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path.stderr index 66bb14ceac1f7..575f40168a6eb 100644 --- a/src/test/ui/suggestions/type-ascription-instead-of-path.stderr +++ b/src/test/ui/suggestions/type-ascription-instead-of-path.stderr @@ -5,7 +5,7 @@ LL | std:io::stdin(); | ^^ | | | use of undeclared crate or module `io` - | help: there is a type with a similar name: `i8` + | help: there is a builtin type with a similar name: `i8` error[E0423]: expected value, found crate `std` --> $DIR/type-ascription-instead-of-path.rs:2:5 From 63c4d1e60d05af4520eb0016955dba8adaa7a7ed Mon Sep 17 00:00:00 2001 From: Yoshiki Matsuda Date: Wed, 18 May 2022 20:53:57 +0900 Subject: [PATCH 4/5] remove PartialOrd and Ord impls, and sort by the candidate name str --- compiler/rustc_hir/src/def.rs | 10 +++++----- compiler/rustc_resolve/src/diagnostics.rs | 13 ++++--------- compiler/rustc_span/src/hygiene.rs | 2 +- src/test/ui/pattern/pattern-error-continue.stderr | 2 +- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 23b4303da28e3..d0893cd09d8db 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -11,7 +11,7 @@ use std::array::IntoIter; use std::fmt::Debug; /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum CtorOf { /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct. @@ -21,7 +21,7 @@ pub enum CtorOf { } /// What kind of constructor something is. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum CtorKind { /// Constructor function automatically created by a tuple struct/variant. @@ -33,7 +33,7 @@ pub enum CtorKind { } /// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum NonMacroAttrKind { /// Single-segment attribute defined by the language (`#[inline]`) @@ -50,7 +50,7 @@ pub enum NonMacroAttrKind { } /// What kind of definition something is; e.g., `mod` vs `struct`. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum DefKind { // Type namespace @@ -297,7 +297,7 @@ impl DefKind { /// - the call to `str_to_string` will resolve to [`Res::Def`], with the [`DefId`] /// pointing to the definition of `str_to_string` in the current crate. // -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum Res { /// Definition having a unique ID (`DefId`), corresponds to something defined in user code. diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index adc4674d66d42..7d923b12226a7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -4,7 +4,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_ID}; use rustc_ast_pretty::pprust; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_feature::BUILTIN_ATTRIBUTES; @@ -1886,20 +1886,15 @@ impl<'a> Resolver<'a> { })) } - // We sort names here to ensure that the suggestion is deterministic. - // (Notice that there may be a pair of TypoSuggestions whose Symbols - // are same but Res are different.) - names.sort_by_key(|name| (name.candidate, name.res)); - names.dedup(); + // Make sure the suggestion is deterministic. + names.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap()); let symbols = names.iter().map(|sugg| sugg.candidate).collect::>(); - let typo_suggestions: FxHashMap = - names.into_iter().map(|typo_sugg| (typo_sugg.candidate, typo_sugg)).collect(); match find_best_match_for_name(&symbols, ident, None) { Some(sugg) if sugg == ident => None, sugg => sugg, } - .map(|sugg| typo_suggestions.get(&sugg).unwrap().clone()) + .and_then(|sugg| names.into_iter().find(|name| name.candidate == sugg)) } pub(crate) fn report_path_resolution_error( diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 06730c3eb559d..e169d3c7cfb7c 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1073,7 +1073,7 @@ impl ExpnKind { } /// The kind of macro invocation or definition. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] #[derive(HashStable_Generic)] pub enum MacroKind { /// A bang macro `foo!()`. diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr index 56b4089f2549b..742a73bd8ca7e 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 `E` - | help: there is a trait with a similar name: `Eq` + | help: there is an enum with a similar name: `A` error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D` --> $DIR/pattern-error-continue.rs:18:9 From 85acc8ecbcfe006dadf312d22084d4006ca47589 Mon Sep 17 00:00:00 2001 From: Yoshiki Matsuda Date: Sun, 5 Jun 2022 01:43:41 +0900 Subject: [PATCH 5/5] remove unnecessary derives --- compiler/rustc_resolve/src/diagnostics.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7d923b12226a7..e6513525dcf0b 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -48,7 +48,6 @@ pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability); /// similarly named label and whether or not it is reachable. pub(crate) type LabelSuggestion = (Ident, bool); -#[derive(Clone, PartialEq, Eq)] pub(crate) enum SuggestionTarget { /// The target has a similar name as the name used by the programmer (probably a typo) SimilarlyNamed, @@ -56,7 +55,6 @@ pub(crate) enum SuggestionTarget { SingleItem, } -#[derive(Clone, PartialEq, Eq)] pub(crate) struct TypoSuggestion { pub candidate: Symbol, pub res: Res,