diff options
Diffstat (limited to 'compiler/rustc_resolve/src/diagnostics.rs')
-rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 649 |
1 files changed, 249 insertions, 400 deletions
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5d868ebec..e392df6c5 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -25,7 +25,9 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Span, SyntaxContext}; +use thin_vec::ThinVec; +use crate::errors as errs; use crate::imports::{Import, ImportKind, ImportResolver}; use crate::late::{PatternSource, Rib}; use crate::path_names_to_string; @@ -58,16 +60,32 @@ pub(crate) enum SuggestionTarget { #[derive(Debug)] pub(crate) struct TypoSuggestion { pub candidate: Symbol, + /// The source location where the name is defined; None if the name is not defined + /// in source e.g. primitives + pub span: Option<Span>, pub res: Res, pub target: SuggestionTarget, } impl TypoSuggestion { - pub(crate) fn typo_from_res(candidate: Symbol, res: Res) -> TypoSuggestion { - Self { candidate, res, target: SuggestionTarget::SimilarlyNamed } + pub(crate) fn typo_from_ident(ident: Ident, res: Res) -> TypoSuggestion { + Self { + candidate: ident.name, + span: Some(ident.span), + res, + target: SuggestionTarget::SimilarlyNamed, + } + } + pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion { + Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed } } - pub(crate) fn single_item_from_res(candidate: Symbol, res: Res) -> TypoSuggestion { - Self { candidate, res, target: SuggestionTarget::SingleItem } + pub(crate) fn single_item_from_ident(ident: Ident, res: Res) -> TypoSuggestion { + Self { + candidate: ident.name, + span: Some(ident.span), + res, + target: SuggestionTarget::SingleItem, + } } } @@ -174,12 +192,12 @@ impl<'a> Resolver<'a> { ModuleKind::Block => "block", }; - let old_noun = match old_binding.is_import() { + let old_noun = match old_binding.is_import_user_facing() { true => "import", false => "definition", }; - let new_participle = match new_binding.is_import() { + let new_participle = match new_binding.is_import_user_facing() { true => "imported", false => "defined", }; @@ -210,7 +228,7 @@ impl<'a> Resolver<'a> { true => struct_span_err!(self.session, span, E0254, "{}", msg), false => struct_span_err!(self.session, span, E0260, "{}", msg), }, - _ => match (old_binding.is_import(), new_binding.is_import()) { + _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) { (false, false) => struct_span_err!(self.session, span, E0428, "{}", msg), (true, true) => struct_span_err!(self.session, span, E0252, "{}", msg), _ => struct_span_err!(self.session, span, E0255, "{}", msg), @@ -225,21 +243,27 @@ impl<'a> Resolver<'a> { )); err.span_label(span, format!("`{}` re{} here", name, new_participle)); - err.span_label( - self.session.source_map().guess_head_span(old_binding.span), - format!("previous {} of the {} `{}` here", old_noun, old_kind, name), - ); + if !old_binding.span.is_dummy() && old_binding.span != span { + err.span_label( + self.session.source_map().guess_head_span(old_binding.span), + format!("previous {} of the {} `{}` here", old_noun, old_kind, name), + ); + } // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; + let can_suggest = |binding: &NameBinding<'_>, import: &self::Import<'_>| { + !binding.span.is_dummy() + && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport) + }; let import = match (&new_binding.kind, &old_binding.kind) { // If there are two imports where one or both have attributes then prefer removing the // import without attributes. (Import { import: new, .. }, Import { import: old, .. }) if { - !new_binding.span.is_dummy() - && !old_binding.span.is_dummy() - && (new.has_attributes || old.has_attributes) + (new.has_attributes || old.has_attributes) + && can_suggest(old_binding, old) + && can_suggest(new_binding, new) } => { if old.has_attributes { @@ -249,10 +273,10 @@ impl<'a> Resolver<'a> { } } // Otherwise prioritize the new binding. - (Import { import, .. }, other) if !new_binding.span.is_dummy() => { + (Import { import, .. }, other) if can_suggest(new_binding, import) => { Some((import, new_binding.span, other.is_import())) } - (other, Import { import, .. }) if !old_binding.span.is_dummy() => { + (other, Import { import, .. }) if can_suggest(old_binding, import) => { Some((import, old_binding.span, other.is_import())) } _ => None, @@ -337,7 +361,7 @@ impl<'a> Resolver<'a> { } } } - ImportKind::ExternCrate { source, target } => { + ImportKind::ExternCrate { source, target, .. } => { suggestion = Some(format!( "extern crate {} as {};", source.unwrap_or(target.name), @@ -490,7 +514,7 @@ impl<'a> Resolver<'a> { if let Some(binding) = resolution.borrow().binding { let res = binding.res(); if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) { - names.push(TypoSuggestion::typo_from_res(key.ident.name, res)); + names.push(TypoSuggestion::typo_from_ident(key.ident, res)); } } } @@ -575,78 +599,41 @@ impl<'a> Resolver<'a> { err } - ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => { - let mut err = struct_span_err!( - self.session, - span, - E0403, - "the name `{}` is already used for a generic \ - parameter in this item's generic parameters", - name, - ); - err.span_label(span, "already used"); - err.span_label(first_use_span, format!("first use of `{}`", name)); - err - } + ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self + .session + .create_err(errs::NameAlreadyUsedInParameterList { span, first_use_span, name }), ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => { - let mut err = struct_span_err!( - self.session, + self.session.create_err(errs::MethodNotMemberOfTrait { span, - E0407, - "method `{}` is not a member of trait `{}`", method, - trait_ - ); - err.span_label(span, format!("not a member of trait `{}`", trait_)); - if let Some(candidate) = candidate { - err.span_suggestion( - method.span, - "there is an associated function with a similar name", - candidate.to_ident_string(), - Applicability::MaybeIncorrect, - ); - } - err + trait_, + sub: candidate.map(|c| errs::AssociatedFnWithSimilarNameExists { + span: method.span, + candidate: c, + }), + }) } ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => { - let mut err = struct_span_err!( - self.session, + self.session.create_err(errs::TypeNotMemberOfTrait { span, - E0437, - "type `{}` is not a member of trait `{}`", type_, - trait_ - ); - err.span_label(span, format!("not a member of trait `{}`", trait_)); - if let Some(candidate) = candidate { - err.span_suggestion( - type_.span, - "there is an associated type with a similar name", - candidate.to_ident_string(), - Applicability::MaybeIncorrect, - ); - } - err + trait_, + sub: candidate.map(|c| errs::AssociatedTypeWithSimilarNameExists { + span: type_.span, + candidate: c, + }), + }) } ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => { - let mut err = struct_span_err!( - self.session, + self.session.create_err(errs::ConstNotMemberOfTrait { span, - E0438, - "const `{}` is not a member of trait `{}`", const_, - trait_ - ); - err.span_label(span, format!("not a member of trait `{}`", trait_)); - if let Some(candidate) = candidate { - err.span_suggestion( - const_.span, - "there is an associated constant with a similar name", - candidate.to_ident_string(), - Applicability::MaybeIncorrect, - ); - } - err + trait_, + sub: candidate.map(|c| errs::AssociatedConstWithSimilarNameExists { + span: const_.span, + candidate: c, + }), + }) } ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => { let BindingError { name, target, origin, could_be_path } = binding_error; @@ -708,128 +695,78 @@ impl<'a> Resolver<'a> { err } ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => { - let mut err = struct_span_err!( - self.session, - span, - E0409, - "variable `{}` is bound inconsistently across alternatives separated by `|`", - variable_name - ); - err.span_label(span, "bound in different ways"); - err.span_label(first_binding_span, "first binding"); - err - } - ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { - let mut err = struct_span_err!( - self.session, - span, - E0415, - "identifier `{}` is bound more than once in this parameter list", - identifier - ); - err.span_label(span, "used as parameter more than once"); - err - } - ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => { - let mut err = struct_span_err!( - self.session, + self.session.create_err(errs::VariableBoundWithDifferentMode { span, - E0416, - "identifier `{}` is bound more than once in the same pattern", - identifier - ); - err.span_label(span, "used in a pattern more than once"); - err - } + first_binding_span, + variable_name, + }) + } + ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => self + .session + .create_err(errs::IdentifierBoundMoreThanOnceInParameterList { span, identifier }), + ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => self + .session + .create_err(errs::IdentifierBoundMoreThanOnceInSamePattern { span, identifier }), ResolutionError::UndeclaredLabel { name, suggestion } => { - let mut err = struct_span_err!( - self.session, - span, - E0426, - "use of undeclared label `{}`", - name - ); - - err.span_label(span, format!("undeclared label `{}`", name)); - - match suggestion { + let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion + { // A reachable label with a similar name exists. - Some((ident, true)) => { - err.span_label(ident.span, "a label with a similar name is reachable"); - err.span_suggestion( - span, - "try using similarly named label", - ident.name, - Applicability::MaybeIncorrect, - ); - } + Some((ident, true)) => ( + ( + Some(errs::LabelWithSimilarNameReachable(ident.span)), + Some(errs::TryUsingSimilarlyNamedLabel { + span, + ident_name: ident.name, + }), + ), + None, + ), // An unreachable label with a similar name exists. - Some((ident, false)) => { - err.span_label( - ident.span, - "a label with a similar name exists but is unreachable", - ); - } + Some((ident, false)) => ( + (None, None), + Some(errs::UnreachableLabelWithSimilarNameExists { + ident_span: ident.span, + }), + ), // No similarly-named labels exist. - None => (), - } - - err + None => ((None, None), None), + }; + self.session.create_err(errs::UndeclaredLabel { + span, + name, + sub_reachable, + sub_reachable_suggestion, + sub_unreachable, + }) } ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => { - let mut err = struct_span_err!( - self.session, - span, - E0429, - "{}", - "`self` imports are only allowed within a { } list" - ); - // None of the suggestions below would help with a case like `use self`. - if !root { + let (suggestion, mpart_suggestion) = if root { + (None, None) + } else { // use foo::bar::self -> foo::bar // use foo::bar::self as abc -> foo::bar as abc - err.span_suggestion( - span, - "consider importing the module directly", - "", - Applicability::MachineApplicable, - ); + let suggestion = errs::SelfImportsOnlyAllowedWithinSuggestion { span }; // use foo::bar::self -> foo::bar::{self} // use foo::bar::self as abc -> foo::bar::{self as abc} - let braces = vec![ - (span_with_rename.shrink_to_lo(), "{".to_string()), - (span_with_rename.shrink_to_hi(), "}".to_string()), - ]; - err.multipart_suggestion( - "alternatively, use the multi-path `use` syntax to import `self`", - braces, - Applicability::MachineApplicable, - ); - } - err + let mpart_suggestion = errs::SelfImportsOnlyAllowedWithinMultipartSuggestion { + multipart_start: span_with_rename.shrink_to_lo(), + multipart_end: span_with_rename.shrink_to_hi(), + }; + (Some(suggestion), Some(mpart_suggestion)) + }; + self.session.create_err(errs::SelfImportsOnlyAllowedWithin { + span, + suggestion, + mpart_suggestion, + }) } ResolutionError::SelfImportCanOnlyAppearOnceInTheList => { - let mut err = struct_span_err!( - self.session, - span, - E0430, - "`self` import can only appear once in an import list" - ); - err.span_label(span, "can only appear once in an import list"); - err + self.session.create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span }) } ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { - let mut err = struct_span_err!( - self.session, - span, - E0431, - "`self` import can only appear in an import list with \ - a non-empty prefix" - ); - err.span_label(span, "can only appear in an import list with a non-empty prefix"); - err + self.session.create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span }) } ResolutionError::FailedToResolve { label, suggestion } => { let mut err = @@ -847,23 +784,9 @@ impl<'a> Resolver<'a> { err } ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { - let mut err = struct_span_err!( - self.session, - span, - E0434, - "{}", - "can't capture dynamic environment in a fn item" - ); - err.help("use the `|| { ... }` closure form instead"); - err + self.session.create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span }) } - ResolutionError::AttemptToUseNonConstantValueInConstant(ident, sugg, current) => { - let mut err = struct_span_err!( - self.session, - span, - E0435, - "attempt to use a non-constant value in a constant" - ); + ResolutionError::AttemptToUseNonConstantValueInConstant(ident, suggestion, current) => { // let foo =... // ^^^ given this Span // ------- get this Span to have an applicable suggestion @@ -877,23 +800,34 @@ impl<'a> Resolver<'a> { .source_map() .span_extend_to_prev_str(ident.span, current, true, false); - match sp { + let ((with, with_label), without) = match sp { Some(sp) if !self.session.source_map().is_multiline(sp) => { let sp = sp.with_lo(BytePos(sp.lo().0 - (current.len() as u32))); - err.span_suggestion( - sp, - &format!("consider using `{}` instead of `{}`", sugg, current), - format!("{} {}", sugg, ident), - Applicability::MaybeIncorrect, - ); - err.span_label(span, "non-constant value"); - } - _ => { - err.span_label(ident.span, &format!("this would need to be a `{}`", sugg)); + ( + (Some(errs::AttemptToUseNonConstantValueInConstantWithSuggestion { + span: sp, + ident, + suggestion, + current, + }), Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion {span})), + None, + ) } - } + _ => ( + (None, None), + Some(errs::AttemptToUseNonConstantValueInConstantWithoutSuggestion { + ident_span: ident.span, + suggestion, + }), + ), + }; - err + self.session.create_err(errs::AttemptToUseNonConstantValueInConstant { + span, + with, + with_label, + without, + }) } ResolutionError::BindingShadowsSomethingUnacceptable { shadowing_binding, @@ -902,135 +836,80 @@ impl<'a> Resolver<'a> { article, shadowed_binding, shadowed_binding_span, - } => { - let shadowed_binding_descr = shadowed_binding.descr(); - let mut err = struct_span_err!( - self.session, - span, - E0530, - "{}s cannot shadow {}s", - shadowing_binding.descr(), - shadowed_binding_descr, - ); - err.span_label( - span, - format!("cannot be named the same as {} {}", article, shadowed_binding_descr), - ); - match (shadowing_binding, shadowed_binding) { + } => self.session.create_err(errs::BindingShadowsSomethingUnacceptable { + span, + shadowing_binding, + shadowed_binding, + article, + sub_suggestion: match (shadowing_binding, shadowed_binding) { ( PatternSource::Match, Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _), - ) => { - err.span_suggestion( - span, - "try specify the pattern arguments", - format!("{}(..)", name), - Applicability::Unspecified, - ); - } - _ => (), - } - let msg = - format!("the {} `{}` is {} here", shadowed_binding_descr, name, participle); - err.span_label(shadowed_binding_span, msg); - err - } + ) => Some(errs::BindingShadowsSomethingUnacceptableSuggestion { span, name }), + _ => None, + }, + shadowed_binding_span, + participle, + name, + }), ResolutionError::ForwardDeclaredGenericParam => { - let mut err = struct_span_err!( - self.session, - span, - E0128, - "generic parameters with a default cannot use \ - forward declared identifiers" - ); - err.span_label(span, "defaulted generic parameters cannot be forward declared"); - err + self.session.create_err(errs::ForwardDeclaredGenericParam { span }) } ResolutionError::ParamInTyOfConstParam(name) => { - let mut err = struct_span_err!( - self.session, - span, - E0770, - "the type of const parameters must not depend on other generic parameters" - ); - err.span_label( - span, - format!("the type must not depend on the parameter `{}`", name), - ); - err + self.session.create_err(errs::ParamInTyOfConstParam { span, name }) } ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => { - let mut err = self.session.struct_span_err( + self.session.create_err(errs::ParamInNonTrivialAnonConst { span, - "generic parameters may not be used in const operations", - ); - err.span_label(span, &format!("cannot perform const operation using `{}`", name)); - - if is_type { - err.note("type parameters may not be used in const expressions"); - } else { - err.help(&format!( - "const parameters may only be used as standalone arguments, i.e. `{}`", - name - )); - } - - if self.session.is_nightly_build() { - err.help( - "use `#![feature(generic_const_exprs)]` to allow generic const expressions", - ); - } - - err + name, + sub_is_type: if is_type { + errs::ParamInNonTrivialAnonConstIsType::AType + } else { + errs::ParamInNonTrivialAnonConstIsType::NotAType { name } + }, + help: self + .session + .is_nightly_build() + .then_some(errs::ParamInNonTrivialAnonConstHelp), + }) } ResolutionError::SelfInGenericParamDefault => { - let mut err = struct_span_err!( - self.session, - span, - E0735, - "generic parameters cannot use `Self` in their defaults" - ); - err.span_label(span, "`Self` in generic parameter default"); - err + self.session.create_err(errs::SelfInGenericParamDefault { span }) } ResolutionError::UnreachableLabel { name, definition_span, suggestion } => { - let mut err = struct_span_err!( - self.session, + let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) = + match suggestion { + // A reachable label with a similar name exists. + Some((ident, true)) => ( + ( + Some(errs::UnreachableLabelSubLabel { ident_span: ident.span }), + Some(errs::UnreachableLabelSubSuggestion { + span, + // intentionally taking 'ident.name' instead of 'ident' itself, as this + // could be used in suggestion context + ident_name: ident.name, + }), + ), + None, + ), + // An unreachable label with a similar name exists. + Some((ident, false)) => ( + (None, None), + Some(errs::UnreachableLabelSubLabelUnreachable { + ident_span: ident.span, + }), + ), + // No similarly-named labels exist. + None => ((None, None), None), + }; + self.session.create_err(errs::UnreachableLabel { span, - E0767, - "use of unreachable label `{}`", name, - ); - - err.span_label(definition_span, "unreachable label defined here"); - err.span_label(span, format!("unreachable label `{}`", name)); - err.note( - "labels are unreachable through functions, closures, async blocks and modules", - ); - - match suggestion { - // A reachable label with a similar name exists. - Some((ident, true)) => { - err.span_label(ident.span, "a label with a similar name is reachable"); - err.span_suggestion( - span, - "try using similarly named label", - ident.name, - Applicability::MaybeIncorrect, - ); - } - // An unreachable label with a similar name exists. - Some((ident, false)) => { - err.span_label( - ident.span, - "a label with a similar name exists but is also unreachable", - ); - } - // No similarly-named labels exist. - None => (), - } - - err + definition_span, + sub_suggestion, + sub_suggestion_label, + sub_unreachable_label, + }) } ResolutionError::TraitImplMismatch { name, @@ -1051,25 +930,10 @@ impl<'a> Resolver<'a> { err.span_label(trait_item_span, "item in trait"); err } - ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => { - let mut err = struct_span_err!( - self.session, - span, - E0201, - "duplicate definitions with name `{}`:", - name, - ); - err.span_label(old_span, "previous definition here"); - err.span_label(trait_item_span, "item in trait"); - err.span_label(span, "duplicate definition"); - err - } - ResolutionError::InvalidAsmSym => { - let mut err = self.session.struct_span_err(span, "invalid `sym` operand"); - err.span_label(span, "is a local variable"); - err.help("`sym` operands must refer to either a function or a static"); - err - } + ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self + .session + .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }), + ResolutionError::InvalidAsmSym => self.session.create_err(errs::InvalidAsmSym { span }), } } @@ -1079,48 +943,27 @@ impl<'a> Resolver<'a> { ) -> ErrorGuaranteed { match vis_resolution_error { VisResolutionError::Relative2018(span, path) => { - let mut err = self.session.struct_span_err( + self.session.create_err(errs::Relative2018 { span, - "relative paths are not supported in visibilities in 2018 edition or later", - ); - err.span_suggestion( - path.span, - "try", - format!("crate::{}", pprust::path_to_string(&path)), - Applicability::MaybeIncorrect, - ); - err + path_span: path.span, + // intentionally converting to String, as the text would also be used as + // in suggestion context + path_str: pprust::path_to_string(&path), + }) + } + VisResolutionError::AncestorOnly(span) => { + self.session.create_err(errs::AncestorOnly(span)) } - VisResolutionError::AncestorOnly(span) => struct_span_err!( - self.session, - span, - E0742, - "visibilities can only be restricted to ancestor modules" - ), VisResolutionError::FailedToResolve(span, label, suggestion) => { self.into_struct_error(span, ResolutionError::FailedToResolve { label, suggestion }) } VisResolutionError::ExpectedFound(span, path_str, res) => { - let mut err = struct_span_err!( - self.session, - span, - E0577, - "expected module, found {} `{}`", - res.descr(), - path_str - ); - err.span_label(span, "not a module"); - err + self.session.create_err(errs::ExpectedFound { span, res, path_str }) } - VisResolutionError::Indeterminate(span) => struct_span_err!( - self.session, - span, - E0578, - "cannot determine resolution for the visibility" - ), - VisResolutionError::ModuleOnly(span) => { - self.session.struct_span_err(span, "visibility must resolve to a module") + VisResolutionError::Indeterminate(span) => { + self.session.create_err(errs::Indeterminate(span)) } + VisResolutionError::ModuleOnly(span) => self.session.create_err(errs::ModuleOnly(span)), } .emit() } @@ -1145,7 +988,7 @@ impl<'a> Resolver<'a> { .get(&expn_id) .into_iter() .flatten() - .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)), + .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)), ); } } @@ -1164,7 +1007,7 @@ impl<'a> Resolver<'a> { suggestions.extend( ext.helper_attrs .iter() - .map(|name| TypoSuggestion::typo_from_res(*name, res)), + .map(|name| TypoSuggestion::typo_from_name(*name, res)), ); } } @@ -1174,8 +1017,8 @@ impl<'a> Resolver<'a> { if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() { let res = macro_rules_binding.binding.res(); if filter_fn(res) { - suggestions.push(TypoSuggestion::typo_from_res( - macro_rules_binding.ident.name, + suggestions.push(TypoSuggestion::typo_from_ident( + macro_rules_binding.ident, res, )) } @@ -1193,7 +1036,7 @@ impl<'a> Resolver<'a> { suggestions.extend(this.macro_use_prelude.iter().filter_map( |(name, binding)| { let res = binding.res(); - filter_fn(res).then_some(TypoSuggestion::typo_from_res(*name, res)) + filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res)) }, )); } @@ -1203,14 +1046,14 @@ impl<'a> Resolver<'a> { suggestions.extend( BUILTIN_ATTRIBUTES .iter() - .map(|attr| TypoSuggestion::typo_from_res(attr.name, res)), + .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)), ); } } Scope::ExternPrelude => { suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| { let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()); - filter_fn(res).then_some(TypoSuggestion::typo_from_res(ident.name, res)) + filter_fn(res).then_some(TypoSuggestion::typo_from_ident(*ident, res)) })); } Scope::ToolPrelude => { @@ -1218,7 +1061,7 @@ impl<'a> Resolver<'a> { suggestions.extend( this.registered_tools .iter() - .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)), + .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)), ); } Scope::StdLibPrelude => { @@ -1235,7 +1078,8 @@ impl<'a> Resolver<'a> { Scope::BuiltinTypes => { suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| { let res = Res::PrimTy(*prim_ty); - filter_fn(res).then_some(TypoSuggestion::typo_from_res(prim_ty.name(), res)) + filter_fn(res) + .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res)) })) } } @@ -1272,7 +1116,7 @@ impl<'a> Resolver<'a> { { let mut candidates = Vec::new(); let mut seen_modules = FxHashSet::default(); - let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), true)]; + let mut worklist = vec![(start_module, ThinVec::<ast::PathSegment>::new(), true)]; let mut worklist_via_import = vec![]; while let Some((in_module, path_segments, accessible)) = match worklist.pop() { @@ -1666,7 +1510,7 @@ impl<'a> Resolver<'a> { let a = if built_in.is_empty() { res.article() } else { "a" }; format!("{a}{built_in} {thing}{from}", thing = res.descr()) } else { - let introduced = if b.is_import() { "imported" } else { "defined" }; + let introduced = if b.is_import_user_facing() { "imported" } else { "defined" }; format!("the {thing} {introduced} here", thing = res.descr()) } } @@ -1725,10 +1569,10 @@ impl<'a> Resolver<'a> { /// If the binding refers to a tuple struct constructor with fields, /// returns the span of its fields. fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> { - if let NameBindingKind::Res( - Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id), - _, - ) = binding.kind + if let NameBindingKind::Res(Res::Def( + DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), + ctor_def_id, + )) = binding.kind { let def_id = self.parent(ctor_def_id); let fields = self.field_names.get(&def_id)?; @@ -1772,7 +1616,9 @@ impl<'a> Resolver<'a> { next_ident = source; Some(binding) } - ImportKind::Glob { .. } | ImportKind::MacroUse => Some(binding), + ImportKind::Glob { .. } | ImportKind::MacroUse | ImportKind::MacroExport => { + Some(binding) + } ImportKind::ExternCrate { .. } => None, }, _ => None, @@ -1994,13 +1840,16 @@ impl<'a> Resolver<'a> { (format!("use of undeclared type `{}`", ident), suggestion) } else { - let suggestion = if ident.name == sym::alloc { - Some(( + let mut suggestion = None; + if ident.name == sym::alloc { + suggestion = Some(( vec![], String::from("add `extern crate alloc` to use the `alloc` crate"), Applicability::MaybeIncorrect, )) - } else { + } + + suggestion = suggestion.or_else(|| { self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map( |sugg| { ( @@ -2010,7 +1859,7 @@ impl<'a> Resolver<'a> { ) }, ) - }; + }); (format!("use of undeclared crate or module `{}`", ident), suggestion) } } |