From e4f4e58dc3c20617f4a245a38237ed5fe0224911 Mon Sep 17 00:00:00 2001 From: JeanCASPAR <55629512+JeanCASPAR@users.noreply.github.com> Date: Sun, 24 Mar 2024 12:43:53 +0000 Subject: [PATCH 1/4] Port build_reduce_graph --- compiler/rustc_resolve/messages.ftl | 60 ++++++- .../rustc_resolve/src/build_reduced_graph.rs | 63 ++----- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/errors.rs | 161 +++++++++++++++++- 4 files changed, 235 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index a03bb6acd41a7..b26cf9aa3363d 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -11,6 +11,8 @@ resolve_added_macro_use = resolve_ancestor_only = visibilities can only be restricted to ancestor modules +resolve_arguments_macro_use_not_allowed = arguments to `macro_use` are not allowed here + resolve_associated_const_with_similar_name_exists = there is an associated constant with a similar name @@ -20,6 +22,10 @@ resolve_associated_fn_with_similar_name_exists = resolve_associated_type_with_similar_name_exists = there is an associated type with a similar name +resolve_attempt_to_define_builtin_macro_twice = + attempted to define built-in macro more than once + .note = previously defined here + resolve_attempt_to_use_non_constant_value_in_constant = attempt to use a non-constant value in a constant @@ -32,6 +38,8 @@ resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion = resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = this would need to be a `{$suggestion}` +resolve_bad_macro_import = bad macro import + resolve_binding_in_never_pattern = never patterns cannot contain variable bindings .suggestion = use a wildcard `_` instead @@ -100,13 +108,31 @@ resolve_const_param_in_non_trivial_anon_const = resolve_const_param_in_ty_of_const_param = const parameters may not be used in the type of const parameters -resolve_expected_found = +resolve_elided_anonymous_lifetime_report_error = + `&` without an explicit lifetime name cannot be used here + .label = explicit lifetime name needed here + +resolve_elided_anonymous_lifetime_report_error_suggestion = + consider introducing a higher-ranked lifetime here + +resolve_expected_module_found = expected module, found {$res} `{$path_str}` .label = not a module +resolve_explicit_anonymous_lifetime_report_error = + `'_` cannot be used here + .label = `'_` is a reserved lifetime name + resolve_explicit_unsafe_traits = unsafe traits like `{$ident}` should be implemented explicitly +resolve_extern_crate_loading_macro_not_at_crate_root = + an `extern crate` loading macros must be at the crate root + +resolve_extern_crate_self_requires_renaming = + `extern crate self;` requires renaming + .suggestion = rename the `self` crate to be able to import it + resolve_forward_declared_generic_param = generic parameters with a default cannot use forward declared identifiers .label = defaulted generic parameters cannot be forward declared @@ -135,17 +161,20 @@ resolve_generic_params_from_outer_item_static = a `static` is a separate item fr resolve_generic_params_from_outer_item_ty_param = type parameter from outer item - resolve_ident_bound_more_than_once_in_parameter_list = identifier `{$identifier}` is bound more than once in this parameter list .label = used as parameter more than once +resolve_implicit_elided_lifetimes_not_allowed_here = implicit elided lifetime not allowed here + resolve_ident_bound_more_than_once_in_same_pattern = identifier `{$identifier}` is bound more than once in the same pattern .label = used in a pattern more than once resolve_imported_crate = `$crate` may not be imported +resolve_imported_macro_not_found = imported macro not found + resolve_imports_cannot_refer_to = imports cannot refer to {$what} @@ -183,11 +212,22 @@ resolve_lowercase_self = resolve_macro_defined_later = a macro with the same name exists, but it appears later at here +resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments = + macro-expanded `extern crate` items cannot shadow names passed with `--extern` + resolve_macro_expected_found = expected {$expected}, found {$found} `{$macro_path}` +resolve_macro_extern_deprecated = + `#[macro_escape]` is a deprecated synonym for `#[macro_use]` + .help = try an outer attribute: `#[macro_use]` + resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self` +resolve_macro_use_name_already_in_use = + `{$name}` is already in scope + .note = macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560) + resolve_method_not_member_of_trait = method `{$method}` is not a member of trait `{$trait_}` .label = not a member of trait `{$trait_}` @@ -217,6 +257,8 @@ resolve_param_in_ty_of_const_param = the type of const parameters must not depend on other generic parameters .label = the type must not depend on the parameter `{$name}` +resolve_pattern_doesnt_bind_name = pattern doesn't bind `{$name}` + resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it .help = you can define integration tests in a directory named `tests` @@ -254,6 +296,9 @@ resolve_self_in_generic_param_default = generic parameters cannot use `Self` in their defaults .label = `Self` in generic parameter default +resolve_static_lifetime_is_reserved = invalid lifetime parameter name: `{$ident}` + .label = 'static is a reserved lifetime name + resolve_tool_module_imported = cannot use a tool module through an import .note = the tool module imported here @@ -284,12 +329,18 @@ resolve_undeclared_label = use of undeclared label `{$name}` .label = undeclared label `{$name}` +resolve_underscore_lifetime_is_reserved = `'_` cannot be used here + .label = `'_` is a reserved lifetime name + resolve_unexpected_res_change_ty_to_const_param_sugg = you might have meant to write a const parameter here resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg = if you meant to collect the rest of the slice in `{$ident}`, use the at operator +resolve_unnamed_crate_root_import = + crate root imports need to be explicitly named: `use crate as name;` + resolve_unreachable_label = use of unreachable label `{$name}` .label = unreachable label `{$name}` @@ -312,3 +363,8 @@ resolve_variable_bound_with_different_mode = variable `{$variable_name}` is bound inconsistently across alternatives separated by `|` .label = bound in different ways .first_binding_span = first binding + +resolve_variable_is_not_bound_in_all_patterns = + variable `{$name}` is not bound in all patterns + +resolve_variable_not_in_all_patterns = variable not in all patterns diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 375f20dd809f2..1b6387acf71e2 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -19,7 +19,6 @@ use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind}; use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId}; use rustc_attr as attr; use rustc_data_structures::sync::Lrc; -use rustc_errors::{codes::*, struct_span_code_err, Applicability}; use rustc_expand::expand::AstFragment; use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; @@ -529,11 +528,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } if ident.name == kw::Crate { - self.r.dcx().span_err( - ident.span, - "crate root imports need to be explicitly named: \ - `use crate as name;`", - ); + self.r.dcx().emit_err(errors::UnnamedCrateRootImport { span: ident.span }); } let kind = ImportKind::Single { @@ -848,16 +843,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let expansion = parent_scope.expansion; let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower { - self.r - .dcx() - .struct_span_err(item.span, "`extern crate self;` requires renaming") - .with_span_suggestion( - item.span, - "rename the `self` crate to be able to import it", - "extern crate self as name;", - Applicability::HasPlaceholders, - ) - .emit(); + self.r.dcx().emit_err(errors::ExternCrateSelfRequiresRenaming { span: sp }); return; } else if orig_name == Some(kw::SelfLower) { Some(self.r.graph_root) @@ -897,9 +883,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { if parent == self.r.graph_root { if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() { - let msg = "macro-expanded `extern crate` items cannot \ - shadow names passed with `--extern`"; - self.r.dcx().span_err(item.span, msg); + self.r.dcx().emit_err( + errors::MacroExpandedExternCrateCannotShadowExternArguments { + span: item.span, + }, + ); // `return` is intended to discard this binding because it's an // unregistered ambiguity error which would result in a panic // caused by inconsistency `path_res` @@ -1030,10 +1018,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { allow_shadowing: bool, ) { if self.r.macro_use_prelude.insert(name, binding).is_some() && !allow_shadowing { - let msg = format!("`{name}` is already in scope"); - let note = - "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)"; - self.r.dcx().struct_span_err(span, msg).with_note(note).emit(); + self.r.dcx().emit_err(errors::MacroUseNameAlreadyInUse { span, name }); } } @@ -1044,13 +1029,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { for attr in &item.attrs { if attr.has_name(sym::macro_use) { if self.parent_scope.module.parent.is_some() { - struct_span_code_err!( - self.r.dcx(), - item.span, - E0468, - "an `extern crate` loading macros must be at the crate root" - ) - .emit(); + self.r.dcx().emit_err(errors::ExternCrateLoadingMacroNotAtCrateRoot { + span: item.span, + }); } if let ItemKind::ExternCrate(Some(orig_name)) = item.kind { if orig_name == kw::SelfLower { @@ -1058,7 +1039,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } let ill_formed = |span| { - struct_span_code_err!(self.r.dcx(), span, E0466, "bad macro import").emit(); + self.r.dcx().emit_err(errors::BadMacroImport { span }); }; match attr.meta() { Some(meta) => match meta.kind { @@ -1143,13 +1124,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { allow_shadowing, ); } else { - struct_span_code_err!( - self.r.dcx(), - ident.span, - E0469, - "imported macro not found" - ) - .emit(); + self.r.dcx().emit_err(errors::ImportedMacroNotFound { span: ident.span }); } } } @@ -1160,18 +1135,16 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool { for attr in attrs { if attr.has_name(sym::macro_escape) { - let msg = "`#[macro_escape]` is a deprecated synonym for `#[macro_use]`"; - let mut err = self.r.dcx().struct_span_warn(attr.span, msg); - if let ast::AttrStyle::Inner = attr.style { - err.help("try an outer attribute: `#[macro_use]`"); - } - err.emit(); + let inner_attribute = matches!(attr.style, ast::AttrStyle::Inner).then_some(()); + self.r + .dcx() + .emit_warn(errors::MacroExternDeprecated { span: attr.span, inner_attribute }); } else if !attr.has_name(sym::macro_use) { continue; } if !attr.is_word() { - self.r.dcx().span_err(attr.span, "arguments to `macro_use` are not allowed here"); + self.r.dcx().emit_err(errors::ArgumentsMacroUseNotAllowed { span: attr.span }); } return true; } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 4057bc9ffbd07..1a14558468dd2 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1005,7 +1005,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ResolutionError::FailedToResolve { segment: None, label, suggestion, module: None }, ), VisResolutionError::ExpectedFound(span, path_str, res) => { - self.dcx().create_err(errs::ExpectedFound { span, res, path_str }) + self.dcx().create_err(errs::ExpectedModuleFound { span, res, path_str }) } VisResolutionError::Indeterminate(span) => { self.dcx().create_err(errs::Indeterminate(span)) diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 5eee6a51fd2da..665abc2b06729 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,4 +1,5 @@ -use rustc_errors::{codes::*, Applicability}; +#![allow(dead_code)] // TODO : non +use rustc_errors::{codes::*, Applicability, MultiSpan}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{ symbol::{Ident, Symbol}, @@ -495,8 +496,8 @@ pub(crate) struct Relative2018 { pub(crate) struct AncestorOnly(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_expected_found, code = E0577)] -pub(crate) struct ExpectedFound { +#[diag(resolve_expected_module_found, code = E0577)] +pub(crate) struct ExpectedModuleFound { #[primary_span] #[label] pub(crate) span: Span, @@ -801,3 +802,157 @@ pub(crate) struct UnexpectedResUseAtOpInSlicePatWithRangeSugg { pub ident: Ident, pub snippet: String, } + +#[derive(Diagnostic)] +#[diag(resolve_extern_crate_loading_macro_not_at_crate_root, code = E0468)] +pub(crate) struct ExternCrateLoadingMacroNotAtCrateRoot { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_bad_macro_import, code = E0466)] +pub(crate) struct BadMacroImport { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_extern_crate_self_requires_renaming)] +pub(crate) struct ExternCrateSelfRequiresRenaming { + #[primary_span] + #[suggestion(code = "extern crate self as name;", applicability = "has-placeholders")] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_macro_use_name_already_in_use)] +#[note] +pub(crate) struct MacroUseNameAlreadyInUse { + #[primary_span] + pub(crate) span: Span, + pub(crate) name: Symbol, +} + +#[derive(Diagnostic)] +#[diag(resolve_imported_macro_not_found, code = E0469)] +pub(crate) struct ImportedMacroNotFound { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_macro_extern_deprecated)] +pub(crate) struct MacroExternDeprecated { + #[primary_span] + pub(crate) span: Span, + #[help] + pub inner_attribute: Option<()>, +} + +#[derive(Diagnostic)] +#[diag(resolve_arguments_macro_use_not_allowed)] +pub(crate) struct ArgumentsMacroUseNotAllowed { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_unnamed_crate_root_import)] +pub(crate) struct UnnamedCrateRootImport { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments)] +pub(crate) struct MacroExpandedExternCrateCannotShadowExternArguments { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_elided_anonymous_lifetime_report_error, code = E0637)] +pub(crate) struct ElidedAnonymousLivetimeReportError { + #[primary_span] + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) suggestion: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + resolve_elided_anonymous_lifetime_report_error_suggestion, + applicability = "machine-applicable" +)] +pub(crate) struct ElidedAnonymousLivetimeReportErrorSuggestion { + #[suggestion_part(code = "for<'a> ")] + pub(crate) lo: Span, + #[suggestion_part(code = "'a ")] + pub(crate) hi: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_explicit_anonymous_lifetime_report_error, code = E0637)] +pub(crate) struct ExplicitAnonymousLivetimeReportError { + #[primary_span] + #[label] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_implicit_elided_lifetimes_not_allowed_here, code = E0726)] +pub(crate) struct ImplicitElidedLifetimeNotAllowedHere { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_underscore_lifetime_is_reserved, code = E0637)] +pub(crate) struct UnderscoreLifetimeIsReserved { + #[primary_span] + #[label] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_static_lifetime_is_reserved, code = E0262)] +pub(crate) struct StaticLifetimeIsReserved { + #[primary_span] + #[label] + pub(crate) span: Span, + pub(crate) lifetime: Ident, +} + +#[derive(Diagnostic)] +#[diag(resolve_attempt_to_define_builtin_macro_twice, code = E0773)] +pub(crate) struct AttemptToDefineBuiltinMacroTwice { + #[primary_span] + pub(crate) span: Span, + #[note] + pub(crate) note_span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_variable_is_not_bound_in_all_patterns, code = E0408)] +pub(crate) struct VariableIsNotBoundInAllPatterns { + #[primary_span] + pub(crate) multispan: MultiSpan, + pub(crate) name: Symbol, +} + +#[derive(Subdiagnostic, Debug, Clone)] +#[label(resolve_pattern_doesnt_bind_name)] +pub(crate) struct PatternDoesntBindName { + #[primary_span] + pub(crate) span: Span, + pub(crate) name: Symbol, +} + +#[derive(Subdiagnostic, Debug, Clone)] +#[label(resolve_variable_not_in_all_patterns)] +pub(crate) struct VariableNotInAllPatterns { + #[primary_span] + pub(crate) span: Span, +} \ No newline at end of file From 4226dc2045717ba8570e56c446557ce808b10916 Mon Sep 17 00:00:00 2001 From: Jean CASPAR Date: Sun, 24 Mar 2024 15:11:27 +0000 Subject: [PATCH 2/4] Migrate some diagnostics --- compiler/rustc_resolve/messages.ftl | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 22 ++++--- compiler/rustc_resolve/src/errors.rs | 3 +- compiler/rustc_resolve/src/late.rs | 77 +++++++++-------------- compiler/rustc_resolve/src/macros.rs | 14 ++--- 5 files changed, 48 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index b26cf9aa3363d..c737ad86e466b 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -296,7 +296,7 @@ resolve_self_in_generic_param_default = generic parameters cannot use `Self` in their defaults .label = `Self` in generic parameter default -resolve_static_lifetime_is_reserved = invalid lifetime parameter name: `{$ident}` +resolve_static_lifetime_is_reserved = invalid lifetime parameter name: `{$lifetime}` .label = 'static is a reserved lifetime name resolve_tool_module_imported = diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 1a14558468dd2..a367a5f21db2d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -29,8 +29,8 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Span, SyntaxContext}; use thin_vec::{thin_vec, ThinVec}; -use crate::errors::{AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion}; -use crate::errors::{ +use crate::errors::{self, + AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive, ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition, MaybeMissingMacroRulesName, }; @@ -677,18 +677,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let origin_sp = origin.iter().copied().collect::>(); let msp = MultiSpan::from_spans(target_sp.clone()); - let mut err = struct_span_code_err!( - self.dcx(), - msp, - E0408, - "variable `{}` is not bound in all patterns", + let mut err = self.dcx().create_err(errors::VariableIsNotBoundInAllPatterns { + multispan: msp, name, - ); + }); for sp in target_sp { - err.span_label(sp, format!("pattern doesn't bind `{name}`")); + err.subdiagnostic(self.dcx(), errors::PatternDoesntBindName { + span: sp, + name, + }); } for sp in origin_sp { - err.span_label(sp, "variable not in all patterns"); + err.subdiagnostic(self.dcx(), errors::VariableNotInAllPatterns { + span: sp, + }); } if could_be_path { let import_suggestions = self.lookup_import_candidates( diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 665abc2b06729..9a140f98c7fb8 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] // TODO : non use rustc_errors::{codes::*, Applicability, MultiSpan}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{ @@ -955,4 +954,4 @@ pub(crate) struct PatternDoesntBindName { pub(crate) struct VariableNotInAllPatterns { #[primary_span] pub(crate) span: Span, -} \ No newline at end of file +} diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 49b4a6efd3c3e..ec11bfd96daa7 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -6,8 +6,7 @@ //! If you wonder why there's no `early.rs`, that's because it's split into three files - //! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`. -use crate::errors::ImportsCannotReferTo; -use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding}; +use crate::{errors, path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding}; use crate::{BindingKey, Used}; use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; @@ -17,7 +16,7 @@ use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor} use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{ - codes::*, struct_span_code_err, Applicability, DiagArgValue, IntoDiagArg, StashKey, + codes::*, Applicability, DiagArgValue, IntoDiagArg, StashKey, }; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; @@ -1666,18 +1665,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); } LifetimeRibKind::AnonymousReportError => { - let (msg, note) = if elided { - ( - "`&` without an explicit lifetime name cannot be used here", - "explicit lifetime name needed here", - ) - } else { - ("`'_` cannot be used here", "`'_` is a reserved lifetime name") - }; - let mut diag = - struct_span_code_err!(self.r.dcx(), lifetime.ident.span, E0637, "{}", msg,); - diag.span_label(lifetime.ident.span, note); if elided { + let mut suggestion = None; for rib in self.lifetime_ribs[i..].iter().rev() { if let LifetimeRibKind::Generics { span, @@ -1685,19 +1674,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { .. } = &rib.kind { - diag.multipart_suggestion( - "consider introducing a higher-ranked lifetime here", - vec![ - (span.shrink_to_lo(), "for<'a> ".into()), - (lifetime.ident.span.shrink_to_hi(), "'a ".into()), - ], - Applicability::MachineApplicable, - ); + suggestion = + Some(errors::ElidedAnonymousLivetimeReportErrorSuggestion { + lo: span.shrink_to_lo(), + hi: lifetime.ident.span.shrink_to_hi(), + }); break; } } - } - diag.emit(); + self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError { + span: lifetime.ident.span, + suggestion, + }); + } else { + self.r.dcx().emit_err(errors::ExplicitAnonymousLivetimeReportError { + span: lifetime.ident.span, + }); + }; self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); return; } @@ -1863,13 +1856,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // async fn foo(_: std::cell::Ref) { ... } LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } | LifetimeRibKind::AnonymousWarn(_) => { + let mut err = + self.r.dcx().create_err(errors::ImplicitElidedLifetimeNotAllowedHere { + span: path_span, + }); let sess = self.r.tcx.sess; - let mut err = struct_span_code_err!( - sess.dcx(), - path_span, - E0726, - "implicit elided lifetime not allowed here" - ); rustc_errors::add_elided_lifetime_in_path_suggestion( sess.source_map(), &mut err, @@ -2313,7 +2304,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let report_error = |this: &Self, ns| { if this.should_report_errs() { let what = if ns == TypeNS { "type parameters" } else { "local variables" }; - this.r.dcx().emit_err(ImportsCannotReferTo { span: ident.span, what }); + this.r.dcx().emit_err(errors::ImportsCannotReferTo { span: ident.span, what }); } }; @@ -2633,29 +2624,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } if param.ident.name == kw::UnderscoreLifetime { - struct_span_code_err!( - self.r.dcx(), - param.ident.span, - E0637, - "`'_` cannot be used here" - ) - .with_span_label(param.ident.span, "`'_` is a reserved lifetime name") - .emit(); + self.r + .dcx() + .emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span }); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); continue; } if param.ident.name == kw::StaticLifetime { - struct_span_code_err!( - self.r.dcx(), - param.ident.span, - E0262, - "invalid lifetime parameter name: `{}`", - param.ident, - ) - .with_span_label(param.ident.span, "'static is a reserved lifetime name") - .emit(); + self.r.dcx().emit_err(errors::StaticLifetimeIsReserved { + span: param.ident.span, + lifetime: param.ident, + }); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); continue; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index dbca2f9895d20..bedf79400e36b 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -14,7 +14,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; -use rustc_errors::{codes::*, struct_span_code_err, Applicability, StashKey}; +use rustc_errors::{Applicability, StashKey}; use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; @@ -916,14 +916,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { rule_spans = Vec::new(); } BuiltinMacroState::AlreadySeen(span) => { - struct_span_code_err!( - self.dcx(), - item.span, - E0773, - "attempted to define built-in macro more than once" - ) - .with_span_note(span, "previously defined here") - .emit(); + self.dcx().emit_err(errors::AttemptToDefineBuiltinMacroTwice { + span: item.span, + note_span: span, + }); } } } else { From cec9f7f71659360e66933d4fb782d37938d00f09 Mon Sep 17 00:00:00 2001 From: Jean CASPAR Date: Sun, 24 Mar 2024 21:53:18 +0000 Subject: [PATCH 3/4] Migrate more diagnostics --- compiler/rustc_resolve/messages.ftl | 106 +++++++++ compiler/rustc_resolve/src/diagnostics.rs | 273 +++++++++++----------- compiler/rustc_resolve/src/errors.rs | 267 +++++++++++++++++++++ compiler/rustc_resolve/src/late.rs | 4 +- compiler/rustc_resolve/src/macros.rs | 61 +++-- 5 files changed, 537 insertions(+), 174 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index c737ad86e466b..95592b1c1dd6f 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -38,6 +38,9 @@ resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion = resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = this would need to be a `{$suggestion}` +resolve_attributes_starting_with_rustc_are_reserved = + attributes starting with `rustc` are reserved for use by the `rustc` compiler + resolve_bad_macro_import = bad macro import resolve_binding_in_never_pattern = @@ -70,12 +73,19 @@ resolve_cannot_determine_macro_resolution = cannot determine resolution for the {$kind} `{$path}` .note = import resolution is stuck, try simplifying macro imports +resolve_cannot_find_builtin_macro_with_name = + cannot find a built-in macro with name `{$ident}` + resolve_cannot_find_ident_in_this_scope = cannot find {$expected} `{$ident}` in this scope resolve_cannot_glob_import_possible_crates = cannot glob-import all possible crates +resolve_cannot_use_through_an_import = + cannot use {$article} {$descr} through an import + .note = the {$descr} imported here + resolve_change_import_binding = you can use `as` to change the binding name of the import @@ -88,6 +98,12 @@ resolve_consider_adding_macro_export = resolve_consider_declaring_with_pub = consider declaring type or module `{$ident}` with `pub` +resolve_consider_making_the_field_public = + { $number_of_fields -> + [one] consider making the field publicly accessible + *[other] consider making the fields publicly accessible + } + resolve_consider_marking_as_pub = consider marking `{$ident}` as `pub` in the imported module @@ -108,6 +124,9 @@ resolve_const_param_in_non_trivial_anon_const = resolve_const_param_in_ty_of_const_param = const parameters may not be used in the type of const parameters +resolve_constructor_private_if_any_field_private = + a constructor is private if any of the fields is private + resolve_elided_anonymous_lifetime_report_error = `&` without an explicit lifetime name cannot be used here .label = explicit lifetime name needed here @@ -133,10 +152,20 @@ resolve_extern_crate_self_requires_renaming = `extern crate self;` requires renaming .suggestion = rename the `self` crate to be able to import it +resolve_failed_resolve_unresolve_import = failed to resolve: unresolved import + +resolve_failed_resolve_unresolve_import_label = unresolved import + resolve_forward_declared_generic_param = generic parameters with a default cannot use forward declared identifiers .label = defaulted generic parameters cannot be forward declared +resolve_found_an_item_configured_out = + found an item that was configured out + +resolve_generic_arguments_in_macro_path = + generic arguments in macro path + resolve_generic_params_from_outer_item = can't use {$is_self -> [true] `Self` @@ -171,6 +200,12 @@ resolve_ident_bound_more_than_once_in_same_pattern = identifier `{$identifier}` is bound more than once in the same pattern .label = used in a pattern more than once +resolve_ident_imported_here_but_it_is_desc = + `{$imported_ident}` is imported here, but it is {$imported_ident_desc} + +resolve_ident_in_scope_but_it_is_desc = + `{$imported_ident}` is in scope, but it is {$imported_ident_desc} + resolve_imported_crate = `$crate` may not be imported resolve_imported_macro_not_found = imported macro not found @@ -190,6 +225,13 @@ resolve_is_not_directly_importable = `{$target}` is not directly importable .label = cannot be imported directly +resolve_is_private = + {$ident_descr} `{$ident}` is private + .label = private {$ident_descr} + +resolve_item_was_behind_feature = + the item is gated behind the `{$feature}` feature + resolve_items_in_traits_are_not_importable = items in traits are not importable @@ -217,6 +259,7 @@ resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments = resolve_macro_expected_found = expected {$expected}, found {$found} `{$macro_path}` + .label = not {$article} {$expected} resolve_macro_extern_deprecated = `#[macro_escape]` is a deprecated synonym for `#[macro_use]` @@ -237,11 +280,45 @@ resolve_missing_macro_rules_name = maybe you have forgotten to define a name for resolve_module_only = visibility must resolve to a module +resolve_name_defined_multiple_time = + the name `{$name}` is defined multiple times + .note = `{$name}` must be defined only once in the {$descr} namespace of this {$container} + +resolve_name_defined_multiple_time_old_binding_definition = + previous definition of the {$old_kind} `{$name}` here + +resolve_name_defined_multiple_time_old_binding_import = + previous import of the {$old_kind} `{$name}` here + +resolve_name_defined_multiple_time_redefined = + `{$name}` redefined here + +resolve_name_defined_multiple_time_reimported = + `{$name}` reimported here + resolve_name_is_already_used_as_generic_parameter = the name `{$name}` is already used for a generic parameter in this item's generic parameters .label = already used .first_use_of_name = first use of `{$name}` +resolve_name_reserved_in_attribute_namespace = + name `{$ident}` is reserved in attribute namespace + +resolve_note_and_refers_to_the_item_defined_here = + {$first -> + [true] {$dots -> + [true] the {$binding_descr} `{$binding_name}` is defined here... + *[false] the {$binding_descr} `{$binding_name}` is defined here + } + *[false] {$dots -> + [true] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here... + *[false] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here + } + } + +resolve_outer_ident_is_not_publicly_reexported = + {$outer_ident_descr} `{$outer_ident}` is not publicly re-exported + resolve_param_in_enum_discriminant = generic parameters may not be used in enum discriminant values .label = cannot perform const operation using `{$name}` @@ -275,6 +352,8 @@ resolve_relative_2018 = resolve_remove_surrounding_derive = remove from the surrounding `derive()` +resolve_remove_unnecessary_import = remove unnecessary import + resolve_self_import_can_only_appear_once_in_the_list = `self` import can only appear once in an import list .label = can only appear once in an import list @@ -296,13 +375,33 @@ resolve_self_in_generic_param_default = generic parameters cannot use `Self` in their defaults .label = `Self` in generic parameter default +resolve_similarly_named_defined_here = + similarly named {$candidate_descr} `{$candidate}` defined here + +resolve_single_item_defined_here = + {$candidate_descr} `{$candidate}` defined here + resolve_static_lifetime_is_reserved = invalid lifetime parameter name: `{$lifetime}` .label = 'static is a reserved lifetime name +resolve_suggestion_import_ident_directly = + import `{$ident}` directly + +resolve_suggestion_import_ident_through_reexport = + import `{$ident}` through the re-export + resolve_tool_module_imported = cannot use a tool module through an import .note = the tool module imported here +resolve_tool_only_accepts_identifiers = + `{$tool}` only accepts identifiers + .label = not an identifier + +resolve_tool_was_already_registered = + tool `{$tool}` was already registered + .label = already registered here + resolve_trait_impl_duplicate = duplicate definitions with name `{$name}`: .label = duplicate definition @@ -368,3 +467,10 @@ resolve_variable_is_not_bound_in_all_patterns = variable `{$name}` is not bound in all patterns resolve_variable_not_in_all_patterns = variable not in all patterns + +resolve_you_could_import_this_desc = you could import this {$desc} + +resolve_trait_impl_mismatch = + item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}` + .label = does not match trait + .trait_impl_mismatch_label_item = item in trait \ No newline at end of file diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index a367a5f21db2d..12484462f82f4 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -6,8 +6,8 @@ use rustc_ast::{MetaItemKind, NestedMetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - codes::*, pluralize, report_ambiguity_error, struct_span_code_err, Applicability, Diag, - DiagCtxt, ErrorGuaranteed, MultiSpan, SuggestionStyle, + codes::*, report_ambiguity_error, struct_span_code_err, Applicability, Diag, DiagCtxt, + ErrorGuaranteed, MultiSpan, SuggestionStyle, }; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; @@ -29,10 +29,9 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Span, SyntaxContext}; use thin_vec::{thin_vec, ThinVec}; -use crate::errors::{self, - AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, - ConsiderAddingADerive, ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition, - MaybeMissingMacroRulesName, +use crate::errors::{ + self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive, + ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition, MaybeMissingMacroRulesName, }; use crate::imports::{Import, ImportKind}; use crate::late::{PatternSource, Rib}; @@ -226,16 +225,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ModuleKind::Block => "block", }; - let old_noun = match old_binding.is_import_user_facing() { - true => "import", - false => "definition", - }; - - let new_participle = match new_binding.is_import_user_facing() { - true => "imported", - false => "defined", - }; - let (name, span) = (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span)); @@ -254,35 +243,51 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (TypeNS, _) => "type", }; - let msg = format!("the name `{name}` is defined multiple times"); - - let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) { - (true, true) => struct_span_code_err!(self.dcx(), span, E0259, "{}", msg), + let code = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) { + (true, true) => E0259, (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() { - true => struct_span_code_err!(self.dcx(), span, E0254, "{}", msg), - false => struct_span_code_err!(self.dcx(), span, E0260, "{}", msg), + true => E0254, + false => E0260, }, _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) { - (false, false) => struct_span_code_err!(self.dcx(), span, E0428, "{}", msg), - (true, true) => struct_span_code_err!(self.dcx(), span, E0252, "{}", msg), - _ => struct_span_code_err!(self.dcx(), span, E0255, "{}", msg), + (false, false) => E0428, + (true, true) => E0252, + _ => E0255, }, }; - err.note(format!( - "`{}` must be defined only once in the {} namespace of this {}", - name, - ns.descr(), - container - )); - - err.span_label(span, format!("`{name}` re{new_participle} here")); - if !old_binding.span.is_dummy() && old_binding.span != span { - err.span_label( - self.tcx.sess.source_map().guess_head_span(old_binding.span), - format!("previous {old_noun} of the {old_kind} `{name}` here"), - ); - } + let label = match new_binding.is_import_user_facing() { + true => errors::NameDefinedMultipleTimeLabel::Reimported { span, name }, + false => errors::NameDefinedMultipleTimeLabel::Redefined { span, name }, + }; + + let old_binding_label = + (!old_binding.span.is_dummy() && old_binding.span != span).then(|| { + let span = self.tcx.sess.source_map().guess_head_span(old_binding.span); + match old_binding.is_import_user_facing() { + true => errors::NameDefinedMultipleTimeOldBindingLabel::Import { + span, + name, + old_kind, + }, + false => errors::NameDefinedMultipleTimeOldBindingLabel::Definition { + span, + name, + old_kind, + }, + } + }); + + let mut err = self + .dcx() + .create_err(errors::NameDefinedMultipleTime { + span, + descr: ns.descr(), + container, + label, + old_binding_label, + }) + .with_code(code); // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; @@ -330,20 +335,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match import { Some((import, span, true)) if should_remove_import && import.is_nested() => { - self.add_suggestion_for_duplicate_nested_use(&mut err, import, span) + self.add_suggestion_for_duplicate_nested_use(&mut err, import, span); } Some((import, _, true)) if should_remove_import && !import.is_glob() => { // Simple case - remove the entire import. Due to the above match arm, this can // only be a single use so just remove it entirely. - err.tool_only_span_suggestion( - import.use_span_with_attributes, - "remove unnecessary import", - "", - Applicability::MaybeIncorrect, + err.subdiagnostic( + self.tcx.dcx(), + errors::ToolOnlyRemoveUnnecessaryImport { + span: import.use_span_with_attributes, + }, ); } Some((import, span, _)) => { - self.add_suggestion_for_rename_of_use(&mut err, name, import, span) + self.add_suggestion_for_rename_of_use(&mut err, name, import, span); } _ => {} } @@ -444,7 +449,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { binding_span: Span, ) { assert!(import.is_nested()); - let message = "remove unnecessary import"; // Two examples will be used to illustrate the span manipulations we're doing: // @@ -460,22 +464,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // previous imports. if found_closing_brace { if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) { - err.tool_only_span_suggestion(span, message, "", Applicability::MaybeIncorrect); + err.subdiagnostic(self.dcx(), errors::ToolOnlyRemoveUnnecessaryImport { span }); } else { // Remove the entire line if we cannot extend the span back, this indicates an // `issue_52891::{self}` case. - err.span_suggestion( - import.use_span_with_attributes, - message, - "", - Applicability::MaybeIncorrect, + err.subdiagnostic( + self.dcx(), + errors::RemoveUnnecessaryImport { span: import.use_span_with_attributes }, ); } return; } - err.span_suggestion(span, message, "", Applicability::MachineApplicable); + err.subdiagnostic(self.dcx(), errors::RemoveUnnecessaryImport { span }); } pub(crate) fn lint_if_path_starts_with_module( @@ -571,14 +573,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolution_error: ResolutionError<'a>, ) -> Diag<'_> { match resolution_error { - ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => { + ResolutionError::GenericParamsFromOuterItem( + outer_res, + has_generic_params, + def_kind, + ) => { use errs::GenericParamsFromOuterItemLabel as Label; let static_or_const = match def_kind { - DefKind::Static{ .. } => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), + DefKind::Static { .. } => { + Some(errs::GenericParamsFromOuterItemStaticOrConst::Static) + } DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const), _ => None, }; - let is_self = matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }); + let is_self = + matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }); let mut err = errs::GenericParamsFromOuterItem { span, label: None, @@ -677,20 +686,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let origin_sp = origin.iter().copied().collect::>(); let msp = MultiSpan::from_spans(target_sp.clone()); - let mut err = self.dcx().create_err(errors::VariableIsNotBoundInAllPatterns { - multispan: msp, - name, - }); + let mut err = self + .dcx() + .create_err(errors::VariableIsNotBoundInAllPatterns { multispan: msp, name }); for sp in target_sp { - err.subdiagnostic(self.dcx(), errors::PatternDoesntBindName { - span: sp, - name, - }); + err.subdiagnostic(self.dcx(), errors::PatternDoesntBindName { span: sp, name }); } for sp in origin_sp { - err.subdiagnostic(self.dcx(), errors::VariableNotInAllPatterns { - span: sp, - }); + err.subdiagnostic(self.dcx(), errors::VariableNotInAllPatterns { span: sp }); } if could_be_path { let import_suggestions = self.lookup_import_candidates( @@ -963,17 +966,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { code, trait_item_span, trait_path, - } => { - self.dcx().struct_span_err( + } => self + .dcx() + .create_err(errors::TraitImplMismatch { span, - format!( - "item `{name}` is an associated {kind}, which doesn't match its trait `{trait_path}`", - ), - ) - .with_code(code) - .with_span_label(span, "does not match trait") - .with_span_label(trait_item_span, "item in trait") - } + name, + kind, + trait_path, + trait_item_span, + }) + .with_code(code), ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self .dcx() .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }), @@ -1534,17 +1536,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; if let crate::NameBindingKind::Import { import, .. } = binding.kind { if !import.span.is_dummy() { - err.span_note( - import.span, - format!("`{ident}` is imported here, but it is {desc}"), - ); + let note = errors::IdentImporterHereButItIsDesc { + span: import.span, + imported_ident: ident, + imported_ident_desc: &desc, + }; + err.subdiagnostic(self.tcx.dcx(), note); // Silence the 'unused import' warning we might get, // since this diagnostic already covers that import. self.record_use(ident, binding, Used::Other); return; } } - err.note(format!("`{ident}` is in scope, but it is {desc}")); + let note = errors::IdentInScopeButItIsDesc { + imported_ident: ident, + imported_ident_desc: &desc, + }; + err.subdiagnostic(self.tcx.dcx(), note); return; } } @@ -1584,20 +1592,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // | ^ return false; } - let prefix = match suggestion.target { - SuggestionTarget::SimilarlyNamed => "similarly named ", - SuggestionTarget::SingleItem => "", + let span = self.tcx.sess.source_map().guess_head_span(def_span); + let candidate_descr = suggestion.res.descr(); + let candidate = suggestion.candidate; + let label = match suggestion.target { + SuggestionTarget::SimilarlyNamed => { + errors::DefinedHere::SimilarlyNamed { span, candidate_descr, candidate } + } + SuggestionTarget::SingleItem => { + errors::DefinedHere::SingleItem { span, candidate_descr, candidate } + } }; - - err.span_label( - self.tcx.sess.source_map().guess_head_span(def_span), - format!( - "{}{} `{}` defined here", - prefix, - suggestion.res.descr(), - suggestion.candidate, - ), - ); + err.subdiagnostic(self.tcx.dcx(), label); } let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target @@ -1751,16 +1757,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { |b: NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; // Print the primary message. - let descr = get_descr(binding); - let mut err = struct_span_code_err!( - self.dcx(), - ident.span, - E0603, - "{} `{}` is private", - descr, - ident - ); - err.span_label(ident.span, format!("private {descr}")); + let ident_descr = get_descr(binding); + let mut err = + self.dcx().create_err(errors::IsPrivate { span: ident.span, ident_descr, ident }); let mut not_publicly_reexported = false; if let Some((this_res, outer_ident)) = outermost_res { @@ -1784,10 +1783,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If we suggest importing a public re-export, don't point at the definition. if point_to_def && ident.span != outer_ident.span { not_publicly_reexported = true; - err.span_label( - outer_ident.span, - format!("{} `{outer_ident}` is not publicly re-exported", this_res.descr()), - ); + let label = errors::OuterIdentIsNotPubliclyReexported { + span: outer_ident.span, + outer_ident_descr: this_res.descr(), + outer_ident, + }; + err.subdiagnostic(self.tcx.dcx(), label); } } @@ -1801,18 +1802,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { { non_exhaustive = Some(attr.span); } else if let Some(span) = ctor_fields_span { - err.span_label(span, "a constructor is private if any of the fields is private"); + let label = errors::ConstructorPrivateIfAnyFieldPrivate { span }; + err.subdiagnostic(self.tcx.dcx(), label); if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) { - err.multipart_suggestion_verbose( - format!( - "consider making the field{} publicly accessible", - pluralize!(fields.len()) - ), - fields.iter().map(|span| (*span, "pub ".to_string())).collect(), - Applicability::MaybeIncorrect, - ); + let spans = fields.iter().map(|span| *span).collect(); + let sugg = + errors::ConsiderMakingTheFieldPublic { spans, number_of_fields: fields.len() }; + err.subdiagnostic(self.tcx.dcx(), sugg); } } @@ -1895,13 +1893,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { NameBindingKind::Res(_) | NameBindingKind::Module(_) => {} } let first = binding == first_binding; - let msg = format!( - "{and_refers_to}the {item} `{name}`{which} is defined here{dots}", - and_refers_to = if first { "" } else { "...and refers to " }, - item = get_descr(binding), - which = if first { "" } else { " which" }, - dots = if next_binding.is_some() { "..." } else { "" }, - ); let def_span = self.tcx.sess.source_map().guess_head_span(binding.span); let mut note_span = MultiSpan::from_span(def_span); if !first && binding.vis.is_public() { @@ -1921,7 +1912,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { "cannot be constructed because it is `#[non_exhaustive]`", ); } - err.span_note(note_span, msg); + let note = errors::NoteAndRefersToTheItemDefinedHere { + span: note_span, + binding_descr: get_descr(binding), + binding_name: name, + first, + dots: next_binding.is_some(), + }; + err.subdiagnostic(self.tcx.dcx(), note); } // We prioritize shorter paths, non-core imports and direct imports over the alternatives. sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0] == "core", *reexport)); @@ -1935,15 +1933,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { continue; } let path = sugg.join("::"); - err.span_suggestion_verbose( - dedup_span, - format!( - "import `{ident}` {}", - if reexport { "through the re-export" } else { "directly" } - ), - path, - Applicability::MachineApplicable, - ); + let sugg = if reexport { + errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path } + } else { + errors::ImportIdent::Directly { span: dedup_span, ident, path } + }; + err.subdiagnostic(self.tcx.dcx(), sugg); break; } @@ -2523,13 +2518,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { continue; } - err.span_note(name.span, "found an item that was configured out"); + let note = errors::FoundItemConfigureOut { span: name.span }; + err.subdiagnostic(self.tcx.dcx(), note); if let MetaItemKind::List(nested) = &cfg.kind && let NestedMetaItem::MetaItem(meta_item) = &nested[0] && let MetaItemKind::NameValue(feature_name) = &meta_item.kind { - err.note(format!("the item is gated behind the `{}` feature", feature_name.symbol)); + let note = errors::ItemWasBehindFeature { feature: feature_name.symbol }; + err.subdiagnostic(self.tcx.dcx(), note); } } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 9a140f98c7fb8..e1ab5b57c3cca 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use rustc_errors::{codes::*, Applicability, MultiSpan}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{ @@ -525,8 +526,10 @@ pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span); #[diag(resolve_macro_expected_found)] pub(crate) struct MacroExpectedFound<'a> { #[primary_span] + #[label] pub(crate) span: Span, pub(crate) found: &'a str, + pub(crate) article: &'static str, pub(crate) expected: &'a str, pub(crate) macro_path: &'a str, #[subdiagnostic] @@ -955,3 +958,267 @@ pub(crate) struct VariableNotInAllPatterns { #[primary_span] pub(crate) span: Span, } + +#[derive(Diagnostic)] +#[diag(resolve_name_defined_multiple_time)] +#[note] +pub(crate) struct NameDefinedMultipleTime { + #[primary_span] + pub(crate) span: Span, + pub(crate) descr: &'static str, + pub(crate) container: &'static str, + #[subdiagnostic] + pub(crate) label: NameDefinedMultipleTimeLabel, + #[subdiagnostic] + pub(crate) old_binding_label: Option, +} + +#[derive(Subdiagnostic)] +pub(crate) enum NameDefinedMultipleTimeLabel { + #[label(resolve_name_defined_multiple_time_reimported)] + Reimported { + #[primary_span] + span: Span, + name: Symbol, + }, + #[label(resolve_name_defined_multiple_time_redefined)] + Redefined { + #[primary_span] + span: Span, + name: Symbol, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum NameDefinedMultipleTimeOldBindingLabel { + #[label(resolve_name_defined_multiple_time_old_binding_import)] + Import { + #[primary_span] + span: Span, + name: Symbol, + old_kind: &'static str, + }, + #[label(resolve_name_defined_multiple_time_old_binding_definition)] + Definition { + #[primary_span] + span: Span, + name: Symbol, + old_kind: &'static str, + }, +} + +#[derive(Diagnostic)] +#[diag(resolve_is_private, code = E0603)] +pub(crate) struct IsPrivate<'a> { + #[primary_span] + #[label] + pub(crate) span: Span, + pub(crate) ident_descr: &'a str, + pub(crate) ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(resolve_generic_arguments_in_macro_path)] +pub(crate) struct GenericArgumentsInMacroPath { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_attributes_starting_with_rustc_are_reserved)] +pub(crate) struct AttributesStartingWithRustcAreReserved { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_cannot_use_through_an_import)] +pub(crate) struct CannotUseThroughAnImport { + #[primary_span] + pub(crate) span: Span, + pub(crate) article: &'static str, + pub(crate) descr: &'static str, + #[note] + pub(crate) binding_span: Option, +} + +#[derive(Diagnostic)] +#[diag(resolve_name_reserved_in_attribute_namespace)] +pub(crate) struct NameReservedInAttributeNamespace { + #[primary_span] + pub(crate) span: Span, + pub(crate) ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(resolve_cannot_find_builtin_macro_with_name)] +pub(crate) struct CannotFindBuiltinMacroWithName { + #[primary_span] + pub(crate) span: Span, + pub(crate) ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(resolve_tool_was_already_registered)] +pub(crate) struct ToolWasAlreadyRegistered { + #[primary_span] + pub(crate) span: Span, + pub(crate) tool: Ident, + #[label] + pub(crate) old_ident_span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_tool_only_accepts_identifiers)] +pub(crate) struct ToolOnlyAcceptsIdentifiers { + #[label] + #[primary_span] + pub(crate) span: Span, + pub(crate) tool: Symbol, +} + +#[derive(Subdiagnostic)] +pub(crate) enum DefinedHere { + #[label(resolve_similarly_named_defined_here)] + SimilarlyNamed { + #[primary_span] + span: Span, + candidate_descr: &'static str, + candidate: Symbol, + }, + #[label(resolve_single_item_defined_here)] + SingleItem { + #[primary_span] + span: Span, + candidate_descr: &'static str, + candidate: Symbol, + }, +} + +#[derive(Subdiagnostic)] +#[label(resolve_outer_ident_is_not_publicly_reexported)] +pub(crate) struct OuterIdentIsNotPubliclyReexported { + #[primary_span] + pub(crate) span: Span, + pub(crate) outer_ident_descr: &'static str, + pub(crate) outer_ident: Ident, +} + +#[derive(Subdiagnostic)] +#[label(resolve_constructor_private_if_any_field_private)] +pub(crate) struct ConstructorPrivateIfAnyFieldPrivate { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + resolve_consider_making_the_field_public, + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct ConsiderMakingTheFieldPublic { + #[suggestion_part(code = "pub ")] + pub(crate) spans: Vec, + pub(crate) number_of_fields: usize, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ImportIdent { + #[suggestion( + resolve_suggestion_import_ident_through_reexport, + code = "{path}", + applicability = "machine-applicable", + style = "verbose" + )] + ThroughReExport { + #[primary_span] + span: Span, + ident: Ident, + path: String, + }, + #[suggestion( + resolve_suggestion_import_ident_directly, + code = "{path}", + applicability = "machine-applicable", + style = "verbose" + )] + Directly { + #[primary_span] + span: Span, + ident: Ident, + path: String, + }, +} + +#[derive(Subdiagnostic)] +#[note(resolve_note_and_refers_to_the_item_defined_here)] +pub(crate) struct NoteAndRefersToTheItemDefinedHere<'a> { + #[primary_span] + pub(crate) span: MultiSpan, + pub(crate) binding_descr: &'a str, + pub(crate) binding_name: Ident, + pub(crate) first: bool, + pub(crate) dots: bool, +} + +#[derive(Subdiagnostic)] +#[suggestion(resolve_remove_unnecessary_import, code = "", applicability = "maybe-incorrect")] +pub(crate) struct RemoveUnnecessaryImport { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion( + resolve_remove_unnecessary_import, + code = "", + applicability = "maybe-incorrect", + style = "tool-only" +)] +pub(crate) struct ToolOnlyRemoveUnnecessaryImport { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Subdiagnostic)] +#[note(resolve_ident_imported_here_but_it_is_desc)] +pub(crate) struct IdentImporterHereButItIsDesc<'a> { + #[primary_span] + pub(crate) span: Span, + pub(crate) imported_ident: Ident, + pub(crate) imported_ident_desc: &'a str, +} + +#[derive(Subdiagnostic)] +#[note(resolve_ident_in_scope_but_it_is_desc)] +pub(crate) struct IdentInScopeButItIsDesc<'a> { + pub(crate) imported_ident: Ident, + pub(crate) imported_ident_desc: &'a str, +} + +#[derive(Subdiagnostic)] +#[note(resolve_found_an_item_configured_out)] +pub(crate) struct FoundItemConfigureOut { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Subdiagnostic)] +#[note(resolve_item_was_behind_feature)] +pub(crate) struct ItemWasBehindFeature { + pub(crate) feature: Symbol, +} + +#[derive(Diagnostic)] +#[diag(resolve_trait_impl_mismatch)] +pub(crate) struct TraitImplMismatch { + #[primary_span] + #[label] + pub(crate) span: Span, + pub(crate) name: Symbol, + pub(crate) kind: &'static str, + pub(crate) trait_path: String, + #[label(resolve_trait_impl_mismatch_label_item)] + pub(crate) trait_item_span: Span, +} diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ec11bfd96daa7..33c9c7fcc6208 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -15,9 +15,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::{ - codes::*, Applicability, DiagArgValue, IntoDiagArg, StashKey, -}; +use rustc_errors::{codes::*, Applicability, DiagArgValue, IntoDiagArg, StashKey}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index bedf79400e36b..2a23ed71753fa 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -123,20 +123,18 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { match nested_meta.ident() { Some(ident) => { if let Some(old_ident) = registered_tools.replace(ident) { - let msg = format!("{} `{}` was already registered", "tool", ident); - tcx.dcx() - .struct_span_err(ident.span, msg) - .with_span_label(old_ident.span, "already registered here") - .emit(); + tcx.dcx().emit_err(errors::ToolWasAlreadyRegistered { + span: ident.span, + tool: ident, + old_ident_span: old_ident.span, + }); } } None => { - let msg = format!("`{}` only accepts identifiers", sym::register_tool); - let span = nested_meta.span(); - tcx.dcx() - .struct_span_err(span, msg) - .with_span_label(span, "not an identifier") - .emit(); + tcx.dcx().emit_err(errors::ToolOnlyAcceptsIdentifiers { + span: nested_meta.span(), + tool: sym::register_tool, + }); } } } @@ -485,13 +483,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Report errors for the resolved macro. for segment in &path.segments { if let Some(args) = &segment.args { - self.dcx().span_err(args.span(), "generic arguments in macro path"); + self.dcx().emit_err(errors::GenericArgumentsInMacroPath { span: args.span() }); } if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") { - self.dcx().span_err( - segment.ident.span, - "attributes starting with `rustc` are reserved for use by the `rustc` compiler", - ); + self.dcx().emit_err(errors::AttributesStartingWithRustcAreReserved { + span: segment.ident.span, + }); } } @@ -535,6 +532,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut err = MacroExpectedFound { span: path.span, expected, + article, found: res.descr(), macro_path: &path_str, remove_surrounding_derive: None, @@ -550,10 +548,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str }); } - self.dcx() - .create_err(err) - .with_span_label(path.span, format!("not {article} {expected}")) - .emit(); + self.dcx().emit_err(err); return Ok((self.dummy_ext(kind), Res::Err)); } @@ -872,13 +867,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) { if let Some(Res::NonMacroAttr(kind)) = res { if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) { - let msg = - format!("cannot use {} {} through an import", kind.article(), kind.descr()); - let mut err = self.dcx().struct_span_err(span, msg); - if let Some(binding) = binding { - err.span_note(binding.span, format!("the {} imported here", kind.descr())); - } - err.emit(); + let binding_span = binding.map(|binding| binding.span); + self.dcx().emit_err(errors::CannotUseThroughAnImport { + span, + article: kind.article(), + descr: kind.descr(), + binding_span, + }); } } } @@ -889,10 +884,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if ident.name == sym::cfg || ident.name == sym::cfg_attr { let macro_kind = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kind()); if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) { - self.dcx().span_err( - ident.span, - format!("name `{ident}` is reserved in attribute namespace"), - ); + self.dcx() + .emit_err(errors::NameReservedInAttributeNamespace { span: ident.span, ident }); } } } @@ -923,8 +916,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } else { - let msg = format!("cannot find a built-in macro with name `{}`", item.ident); - self.dcx().span_err(item.span, msg); + self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { + span: item.span, + ident: item.ident, + }); } } From 992c5050217d93e3e07002fa978c152447d71910 Mon Sep 17 00:00:00 2001 From: Jean CASPAR Date: Sat, 13 Apr 2024 14:02:10 +0100 Subject: [PATCH 4/4] Reorder error messages --- compiler/rustc_resolve/messages.ftl | 19 ++++++------------- compiler/rustc_resolve/src/errors.rs | 1 - 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 95592b1c1dd6f..f824e4faf5d06 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -152,10 +152,6 @@ resolve_extern_crate_self_requires_renaming = `extern crate self;` requires renaming .suggestion = rename the `self` crate to be able to import it -resolve_failed_resolve_unresolve_import = failed to resolve: unresolved import - -resolve_failed_resolve_unresolve_import_label = unresolved import - resolve_forward_declared_generic_param = generic parameters with a default cannot use forward declared identifiers .label = defaulted generic parameters cannot be forward declared @@ -194,8 +190,6 @@ resolve_ident_bound_more_than_once_in_parameter_list = identifier `{$identifier}` is bound more than once in this parameter list .label = used as parameter more than once -resolve_implicit_elided_lifetimes_not_allowed_here = implicit elided lifetime not allowed here - resolve_ident_bound_more_than_once_in_same_pattern = identifier `{$identifier}` is bound more than once in the same pattern .label = used in a pattern more than once @@ -206,6 +200,8 @@ resolve_ident_imported_here_but_it_is_desc = resolve_ident_in_scope_but_it_is_desc = `{$imported_ident}` is in scope, but it is {$imported_ident_desc} +resolve_implicit_elided_lifetimes_not_allowed_here = implicit elided lifetime not allowed here + resolve_imported_crate = `$crate` may not be imported resolve_imported_macro_not_found = imported macro not found @@ -408,6 +404,10 @@ resolve_trait_impl_duplicate = .old_span_label = previous definition here .trait_item_span = item in trait +resolve_trait_impl_mismatch = + item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}` + .label = does not match trait + .trait_impl_mismatch_label_item = item in trait resolve_try_using_similarly_named_label = try using similarly named label @@ -467,10 +467,3 @@ resolve_variable_is_not_bound_in_all_patterns = variable `{$name}` is not bound in all patterns resolve_variable_not_in_all_patterns = variable not in all patterns - -resolve_you_could_import_this_desc = you could import this {$desc} - -resolve_trait_impl_mismatch = - item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}` - .label = does not match trait - .trait_impl_mismatch_label_item = item in trait \ No newline at end of file diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index e1ab5b57c3cca..b0329702d1143 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use rustc_errors::{codes::*, Applicability, MultiSpan}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{