From 74d12e85983f2e9883c4b577a1f6de6db9e26278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 11 Oct 2025 13:54:57 +0200 Subject: [PATCH 1/3] Move more early buffered lints to dyn lint diagnostics (5/N) --- compiler/rustc_lint/messages.ftl | 8 ---- compiler/rustc_lint/src/early/diagnostics.rs | 18 --------- compiler/rustc_lint/src/lints.rs | 38 ------------------ compiler/rustc_lint_defs/src/lib.rs | 10 +---- compiler/rustc_resolve/messages.ftl | 9 +++++ compiler/rustc_resolve/src/check_unused.rs | 6 ++- compiler/rustc_resolve/src/errors.rs | 41 +++++++++++++++++++- compiler/rustc_resolve/src/lib.rs | 3 +- compiler/rustc_resolve/src/macros.rs | 10 ++--- 9 files changed, 59 insertions(+), 84 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index df04d135600ac..82b7b1fd125e9 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -257,9 +257,6 @@ lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message .rationale = {$rationale} -lint_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition - .suggestion = convert it to a `use` - lint_for_loops_over_fallibles = for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement .suggestion = consider using `if let` to clear intent @@ -467,9 +464,6 @@ lint_lintpass_by_hand = implementing `LintPass` by hand lint_macro_expr_fragment_specifier_2024_migration = the `expr` fragment specifier will accept more expressions in the 2024 edition .suggestion = to keep the existing behavior, use the `expr_2021` fragment specifier -lint_macro_is_private = macro `{$ident}` is private - -lint_macro_rule_never_used = rule #{$n} of macro `{$name}` is never used lint_malformed_attribute = malformed lint attribute input @@ -962,8 +956,6 @@ lint_unused_imports = {$num_snippets -> lint_unused_lifetime = lifetime parameter `{$ident}` never used .suggestion = elide the unused lifetime -lint_unused_macro_definition = unused macro definition: `{$name}` - lint_unused_op = unused {$op} that must be used .label = the {$op} produces a value .suggestion = use `let _ = ...` to ignore the resulting value diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 9029ee0447110..16f50933eb0de 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -251,12 +251,6 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag); } - BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => { - let suggestion_span = vis_span.between(ident_span); - let code = if vis_span.is_empty() { "use " } else { " use " }; - - lints::ExternCrateNotIdiomatic { span: suggestion_span, code }.decorate_lint(diag); - } BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => { lints::AmbiguousGlobImports { ambiguity }.decorate_lint(diag); } @@ -332,18 +326,6 @@ pub fn decorate_builtin_lint( lints::PrivateExternCrateReexport { ident, sugg: extern_crate_span.shrink_to_lo() } .decorate_lint(diag); } - BuiltinLintDiag::MacroIsPrivate(ident) => { - lints::MacroIsPrivate { ident }.decorate_lint(diag); - } - BuiltinLintDiag::UnusedMacroDefinition(name) => { - lints::UnusedMacroDefinition { name }.decorate_lint(diag); - } - BuiltinLintDiag::MacroRuleNeverUsed(n, name) => { - lints::MacroRuleNeverUsed { n: n + 1, name }.decorate_lint(diag); - } - BuiltinLintDiag::UnstableFeature(msg) => { - lints::UnstableFeature { msg }.decorate_lint(diag); - } BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 096299c16e0fe..c346e50033a43 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2583,35 +2583,6 @@ pub(crate) struct PrivateExternCrateReexport { pub sugg: Span, } -#[derive(LintDiagnostic)] -#[diag(lint_macro_is_private)] -pub(crate) struct MacroIsPrivate { - pub ident: Ident, -} - -#[derive(LintDiagnostic)] -#[diag(lint_unused_macro_definition)] -pub(crate) struct UnusedMacroDefinition { - pub name: Symbol, -} - -#[derive(LintDiagnostic)] -#[diag(lint_macro_rule_never_used)] -pub(crate) struct MacroRuleNeverUsed { - pub n: usize, - pub name: Symbol, -} - -pub(crate) struct UnstableFeature { - pub msg: DiagMessage, -} - -impl<'a> LintDiagnostic<'a, ()> for UnstableFeature { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(self.msg); - } -} - #[derive(LintDiagnostic)] #[diag(lint_unused_crate_dependency)] #[help] @@ -2893,15 +2864,6 @@ pub(crate) struct NamedArgumentUsedPositionally { pub named_arg_name: String, } -#[derive(LintDiagnostic)] -#[diag(lint_extern_crate_not_idiomatic)] -pub(crate) struct ExternCrateNotIdiomatic { - #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] - pub span: Span, - - pub code: &'static str, -} - // FIXME: make this translatable pub(crate) struct AmbiguousGlobImports { pub ambiguity: AmbiguityErrorDiag, diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index ec26c35ffdc9f..657c2671db41d 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; -use rustc_error_messages::{DiagArgValue, DiagMessage, IntoDiagArg, MultiSpan}; +use rustc_error_messages::{DiagArgValue, IntoDiagArg, MultiSpan}; use rustc_hir_id::{HashStableContext, HirId, ItemLocalId}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::DefPathHash; @@ -678,10 +678,6 @@ pub enum BuiltinLintDiag { /// Indicates if the named argument is used as a width/precision for formatting is_formatting_arg: bool, }, - ExternCrateNotIdiomatic { - vis_span: Span, - ident_span: Span, - }, AmbiguousGlobImports { diag: AmbiguityErrorDiag, }, @@ -731,10 +727,6 @@ pub enum BuiltinLintDiag { source: Ident, extern_crate_span: Span, }, - MacroIsPrivate(Ident), - UnusedMacroDefinition(Symbol), - MacroRuleNeverUsed(usize, Symbol), - UnstableFeature(DiagMessage), UnusedCrateDependency { extern_crate: Symbol, local_crate: Symbol, diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 1569c175948e1..eb49ca33aa748 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -146,6 +146,9 @@ resolve_explicit_unsafe_traits = resolve_extern_crate_loading_macro_not_at_crate_root = an `extern crate` loading macros must be at the crate root +resolve_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition + .suggestion = convert it to a `use` + resolve_extern_crate_self_requires_renaming = `extern crate self;` requires renaming .suggestion = rename the `self` crate to be able to import it @@ -280,6 +283,10 @@ resolve_macro_extern_deprecated = `#[macro_escape]` is a deprecated synonym for `#[macro_use]` .help = try an outer attribute: `#[macro_use]` +resolve_macro_is_private = macro `{$ident}` is private + +resolve_macro_rule_never_used = rule #{$n} of macro `{$name}` is never used + resolve_macro_use_deprecated = applying the `#[macro_use]` attribute to an `extern crate` item is deprecated .help = remove it and import macros at use sites with a `use` item instead @@ -493,6 +500,8 @@ resolve_unused_extern_crate = unused extern crate resolve_unused_label = unused label +resolve_unused_macro_definition = unused macro definition: `{$name}` + resolve_unused_macro_use = unused `#[macro_use]` import resolve_variable_bound_with_different_mode = diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 3f793bb013899..0aaea96348b5e 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -228,11 +228,15 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { .span .find_ancestor_inside(extern_crate.span) .unwrap_or(extern_crate.ident.span); + self.r.lint_buffer.buffer_lint( UNUSED_EXTERN_CRATES, extern_crate.id, extern_crate.span, - BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span }, + crate::errors::ExternCrateNotIdiomatic { + span: vis_span.between(ident_span), + code: if vis_span.is_empty() { "use " } else { " use " }, + }, ); } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index eace729473e21..99f88357d93ba 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,7 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ElidedLifetimeInPathSubdiag, EmissionGuarantee, IntoDiagArg, MultiSpan, - Subdiagnostic, + Applicability, Diag, DiagMessage, ElidedLifetimeInPathSubdiag, EmissionGuarantee, IntoDiagArg, + LintDiagnostic, MultiSpan, Subdiagnostic, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; @@ -1359,3 +1359,40 @@ pub(crate) struct UnusedMacroUse; #[diag(resolve_macro_use_deprecated)] #[help] pub(crate) struct MacroUseDeprecated; + +#[derive(LintDiagnostic)] +#[diag(resolve_macro_is_private)] +pub(crate) struct MacroIsPrivate { + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(resolve_unused_macro_definition)] +pub(crate) struct UnusedMacroDefinition { + pub name: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(resolve_macro_rule_never_used)] +pub(crate) struct MacroRuleNeverUsed { + pub n: usize, + pub name: Symbol, +} + +pub(crate) struct UnstableFeature { + pub msg: DiagMessage, +} + +impl<'a> LintDiagnostic<'a, ()> for UnstableFeature { + fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { + diag.primary_message(self.msg); + } +} + +#[derive(LintDiagnostic)] +#[diag(resolve_extern_crate_not_idiomatic)] +pub(crate) struct ExternCrateNotIdiomatic { + #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + pub span: Span, + pub code: &'static str, +} diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 16eeb9229c977..ed47f3124f939 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -73,7 +73,6 @@ use rustc_middle::ty::{ ResolverGlobalCtxt, TyCtxt, TyCtxtFeed, Visibility, }; use rustc_query_system::ich::StableHashingContext; -use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; use rustc_span::{DUMMY_SP, Ident, Macros20NormalizedIdent, Span, Symbol, kw, sym}; @@ -2067,7 +2066,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { PRIVATE_MACRO_USE, import.root_id, ident.span, - BuiltinLintDiag::MacroIsPrivate(ident), + errors::MacroIsPrivate { ident }, ); } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 1222b40d8b367..8ec551c3cab79 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -340,7 +340,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { UNUSED_MACROS, node_id, ident.span, - BuiltinLintDiag::UnusedMacroDefinition(ident.name), + errors::UnusedMacroDefinition { name: ident.name }, ); // Do not report unused individual rules if the entire macro is unused self.unused_macro_rules.swap_remove(&node_id); @@ -361,7 +361,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { UNUSED_MACRO_RULES, node_id, rule_span, - BuiltinLintDiag::MacroRuleNeverUsed(arm_i, ident.name), + errors::MacroRuleNeverUsed { n: arm_i + 1, name: ident.name }, ); } } @@ -1031,10 +1031,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lint, node_id, span, - BuiltinLintDiag::UnstableFeature( - // FIXME make this translatable - msg.into(), - ), + // FIXME make this translatable + errors::UnstableFeature { msg: msg.into() }, ) }; stability::report_unstable( From 3ad6359f543ca608e720f172d4b07caaed898a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 11 Oct 2025 15:52:36 +0200 Subject: [PATCH 2/3] Move more early buffered lints to dyn lint diagnostics (6/N) --- compiler/rustc_lint/messages.ftl | 14 ------ compiler/rustc_lint/src/early/diagnostics.rs | 18 ------- compiler/rustc_lint/src/lints.rs | 50 -------------------- compiler/rustc_lint_defs/src/lib.rs | 18 ------- compiler/rustc_resolve/messages.ftl | 14 ++++++ compiler/rustc_resolve/src/errors.rs | 49 +++++++++++++++++++ compiler/rustc_resolve/src/imports.rs | 12 +++-- compiler/rustc_resolve/src/macros.rs | 23 ++++----- 8 files changed, 82 insertions(+), 116 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 82b7b1fd125e9..bf721154d73be 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -642,10 +642,6 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass lint_opaque_hidden_inferred_bound_sugg = add this bound -lint_out_of_scope_macro_calls = cannot find macro `{$path}` in the current scope when looking from {$location} - .label = not found from {$location} - .help = import `macro_rules` with `use` to make it callable above its definition - lint_overflowing_bin_hex = literal out of range for `{$ty}` .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}` @@ -681,9 +677,6 @@ lint_pattern_in_bodiless = patterns aren't allowed in functions without bodies lint_pattern_in_foreign = patterns aren't allowed in foreign function declarations .label = pattern not allowed in foreign function -lint_private_extern_crate_reexport = extern crate `{$ident}` is private and cannot be re-exported - .suggestion = consider making the `extern crate` item publicly accessible - lint_query_instability = using `{$query}` can result in unstable query results .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale @@ -709,10 +702,6 @@ lint_redundant_import = the item `{$ident}` is imported redundantly .label_imported_prelude = the item `{$ident}` is already imported by the extern prelude .label_defined_prelude = the item `{$ident}` is already defined by the extern prelude -lint_redundant_import_visibility = glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough - .note = the most public imported item is `{$max_vis}` - .help = reduce the glob import's visibility or increase visibility of imported items - lint_redundant_semicolons = unnecessary trailing {$multiple -> [true] semicolons @@ -872,9 +861,6 @@ lint_unicode_text_flow = unicode codepoint changing visible direction of text pr lint_unit_bindings = binding has unit type `()` .label = this pattern is inferred to be the unit type `()` -lint_unknown_diagnostic_attribute = unknown diagnostic attribute -lint_unknown_diagnostic_attribute_typo_sugg = an attribute with a similar name exists - lint_unknown_gated_lint = unknown lint: `{$name}` .note = the `{$name}` lint is unstable diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 16f50933eb0de..34bb3989008ea 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -311,21 +311,6 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag); } - BuiltinLintDiag::RedundantImportVisibility { max_vis, span: vis_span, import_vis } => { - lints::RedundantImportVisibility { span: vis_span, help: (), max_vis, import_vis } - .decorate_lint(diag); - } - BuiltinLintDiag::UnknownDiagnosticAttribute { span: typo_span, typo_name } => { - let typo = typo_name.map(|typo_name| lints::UnknownDiagnosticAttributeTypoSugg { - span: typo_span, - typo_name, - }); - lints::UnknownDiagnosticAttribute { typo }.decorate_lint(diag); - } - BuiltinLintDiag::PrivateExternCrateReexport { source: ident, extern_crate_span } => { - lints::PrivateExternCrateReexport { ident, sugg: extern_crate_span.shrink_to_lo() } - .decorate_lint(diag); - } BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) } @@ -340,8 +325,5 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag) } - BuiltinLintDiag::OutOfScopeMacroCalls { span, path, location } => { - lints::OutOfScopeMacroCalls { span, path, location }.decorate_lint(diag) - } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c346e50033a43..43786db8bdce0 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2575,14 +2575,6 @@ pub(crate) mod unexpected_cfg_value { } } -#[derive(LintDiagnostic)] -#[diag(lint_private_extern_crate_reexport, code = E0365)] -pub(crate) struct PrivateExternCrateReexport { - pub ident: Ident, - #[suggestion(code = "pub ", style = "verbose", applicability = "maybe-incorrect")] - pub sugg: Span, -} - #[derive(LintDiagnostic)] #[diag(lint_unused_crate_dependency)] #[help] @@ -2602,26 +2594,6 @@ pub(crate) struct IllFormedAttributeInput { pub docs: &'static str, } -#[derive(LintDiagnostic)] -#[diag(lint_unknown_diagnostic_attribute)] -pub(crate) struct UnknownDiagnosticAttribute { - #[subdiagnostic] - pub typo: Option, -} - -#[derive(Subdiagnostic)] -#[suggestion( - lint_unknown_diagnostic_attribute_typo_sugg, - style = "verbose", - code = "{typo_name}", - applicability = "machine-applicable" -)] -pub(crate) struct UnknownDiagnosticAttributeTypoSugg { - #[primary_span] - pub span: Span, - pub typo_name: Symbol, -} - #[derive(LintDiagnostic)] #[diag(lint_unicode_text_flow)] #[note] @@ -2921,18 +2893,6 @@ pub(crate) struct AssociatedConstElidedLifetime { pub lifetimes_in_scope: MultiSpan, } -#[derive(LintDiagnostic)] -#[diag(lint_redundant_import_visibility)] -pub(crate) struct RedundantImportVisibility { - #[note] - pub span: Span, - #[help] - pub help: (), - - pub import_vis: String, - pub max_vis: String, -} - #[derive(LintDiagnostic)] #[diag(lint_unsafe_attr_outside_unsafe)] pub(crate) struct UnsafeAttrOutsideUnsafe { @@ -2954,16 +2914,6 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { pub right: Span, } -#[derive(LintDiagnostic)] -#[diag(lint_out_of_scope_macro_calls)] -#[help] -pub(crate) struct OutOfScopeMacroCalls { - #[label] - pub span: Span, - pub path: String, - pub location: String, -} - #[derive(LintDiagnostic)] #[diag(lint_static_mut_refs_lint)] pub(crate) struct RefOfMutStatic<'a> { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 657c2671db41d..8acb5eb319912 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -714,19 +714,6 @@ pub enum BuiltinLintDiag { span: Span, lifetimes_in_scope: MultiSpan, }, - RedundantImportVisibility { - span: Span, - max_vis: String, - import_vis: String, - }, - UnknownDiagnosticAttribute { - span: Span, - typo_name: Option, - }, - PrivateExternCrateReexport { - source: Ident, - extern_crate_span: Span, - }, UnusedCrateDependency { extern_crate: Symbol, local_crate: Symbol, @@ -735,11 +722,6 @@ pub enum BuiltinLintDiag { suggestions: Vec, docs: Option<&'static str>, }, - OutOfScopeMacroCalls { - span: Span, - path: String, - location: String, - }, } pub type RegisteredTools = FxIndexSet; diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index eb49ca33aa748..4a980b2bd747d 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -342,6 +342,10 @@ resolve_note_and_refers_to_the_item_defined_here = } } +resolve_out_of_scope_macro_calls = cannot find macro `{$path}` in the current scope when looking from {$location} + .label = not found from {$location} + .help = import `macro_rules` with `use` to make it callable above its definition + resolve_outer_ident_is_not_publicly_reexported = {$outer_ident_descr} `{$outer_ident}` is not publicly re-exported @@ -362,12 +366,19 @@ resolve_param_in_ty_of_const_param = resolve_pattern_doesnt_bind_name = pattern doesn't bind `{$name}` +resolve_private_extern_crate_reexport = extern crate `{$ident}` is private and cannot be re-exported + .suggestion = consider making the `extern crate` item publicly accessible + resolve_proc_macro_derive_resolution_fallback = cannot find {$ns_descr} `{$ident}` in this scope .label = names from parent modules are not accessible without an explicit import 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` +resolve_redundant_import_visibility = glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough + .note = the most public imported item is `{$max_vis}` + .help = reduce the glob import's visibility or increase visibility of imported items + resolve_reexport_of_crate_public = re-export of crate public `{$ident}` @@ -473,6 +484,9 @@ resolve_unexpected_res_change_ty_to_const_param_sugg = 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_unknown_diagnostic_attribute = unknown diagnostic attribute +resolve_unknown_diagnostic_attribute_typo_sugg = an attribute with a similar name exists + resolve_unnamed_crate_root_import = crate root imports need to be explicitly named: `use crate as name;` diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 99f88357d93ba..fe1f0d253a127 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -812,6 +812,14 @@ pub(crate) struct CannotBeReexportedCratePublicNS { pub(crate) ident: Ident, } +#[derive(LintDiagnostic)] +#[diag(resolve_private_extern_crate_reexport, code = E0365)] +pub(crate) struct PrivateExternCrateReexport { + pub ident: Ident, + #[suggestion(code = "pub ", style = "verbose", applicability = "maybe-incorrect")] + pub sugg: Span, +} + #[derive(Subdiagnostic)] #[help(resolve_consider_adding_macro_export)] pub(crate) struct ConsiderAddingMacroExport { @@ -1396,3 +1404,44 @@ pub(crate) struct ExternCrateNotIdiomatic { pub span: Span, pub code: &'static str, } + +#[derive(LintDiagnostic)] +#[diag(resolve_out_of_scope_macro_calls)] +#[help] +pub(crate) struct OutOfScopeMacroCalls { + #[label] + pub span: Span, + pub path: String, + pub location: String, +} + +#[derive(LintDiagnostic)] +#[diag(resolve_redundant_import_visibility)] +pub(crate) struct RedundantImportVisibility { + #[note] + pub span: Span, + #[help] + pub help: (), + pub import_vis: String, + pub max_vis: String, +} + +#[derive(LintDiagnostic)] +#[diag(resolve_unknown_diagnostic_attribute)] +pub(crate) struct UnknownDiagnosticAttribute { + #[subdiagnostic] + pub typo: Option, +} + +#[derive(Subdiagnostic)] +#[suggestion( + resolve_unknown_diagnostic_attribute_typo_sugg, + style = "verbose", + code = "{typo_name}", + applicability = "machine-applicable" +)] +pub(crate) struct UnknownDiagnosticAttributeTypoSugg { + #[primary_span] + pub span: Span, + pub typo_name: Symbol, +} diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index f98aaecea18ce..f844e7b9cc12f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1095,10 +1095,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { UNUSED_IMPORTS, id, import.span, - BuiltinLintDiag::RedundantImportVisibility { + crate::errors::RedundantImportVisibility { + span: import.span, + help: (), max_vis: max_vis.to_string(def_id, self.tcx), import_vis: import.vis.to_string(def_id, self.tcx), - span: import.span, }, ); } @@ -1330,13 +1331,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if !any_successful_reexport { let (ns, binding) = reexport_error.unwrap(); if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import, binding) { + let extern_crate_sp = self.tcx.source_span(self.local_def_id(extern_crate_id)); self.lint_buffer.buffer_lint( PUB_USE_OF_PRIVATE_EXTERN_CRATE, import_id, import.span, - BuiltinLintDiag::PrivateExternCrateReexport { - source: ident, - extern_crate_span: self.tcx.source_span(self.local_def_id(extern_crate_id)), + crate::errors::PrivateExternCrateReexport { + ident, + sugg: extern_crate_sp.shrink_to_lo(), }, ); } else if ns == TypeNS { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 8ec551c3cab79..10a0078547ad9 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -21,7 +21,6 @@ use rustc_hir::def::{self, DefKind, MacroKinds, Namespace, NonMacroAttrKind}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::{RegisteredTools, TyCtxt}; -use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNKNOWN_DIAGNOSTIC_ATTRIBUTES, UNUSED_MACRO_RULES, UNUSED_MACROS, @@ -687,23 +686,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit(); } + const DIAG_ATTRS: &[Symbol] = + &[sym::on_unimplemented, sym::do_not_recommend, sym::on_const]; + if res == Res::NonMacroAttr(NonMacroAttrKind::Tool) && let [namespace, attribute, ..] = &*path.segments && namespace.ident.name == sym::diagnostic - && ![sym::on_unimplemented, sym::do_not_recommend, sym::on_const] - .contains(&attribute.ident.name) + && !DIAG_ATTRS.contains(&attribute.ident.name) { - let typo_name = find_best_match_for_name( - &[sym::on_unimplemented, sym::do_not_recommend, sym::on_const], - attribute.ident.name, - Some(5), - ); + let span = attribute.span(); + + let typo = find_best_match_for_name(DIAG_ATTRS, attribute.ident.name, Some(5)) + .map(|typo_name| errors::UnknownDiagnosticAttributeTypoSugg { span, typo_name }); self.tcx.sess.psess.buffer_lint( UNKNOWN_DIAGNOSTIC_ATTRIBUTES, - attribute.span(), + span, node_id, - BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name }, + errors::UnknownDiagnosticAttribute { typo }, ); } @@ -1130,9 +1130,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { OUT_OF_SCOPE_MACRO_CALLS, path.span, node_id, - BuiltinLintDiag::OutOfScopeMacroCalls { + errors::OutOfScopeMacroCalls { span: path.span, path: pprust::path_to_string(path), + // FIXME: Make this translatable. location, }, ); From 109e5e5999041b85dcf5212f6cad559d3ed1111e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 11 Oct 2025 18:25:10 +0200 Subject: [PATCH 3/3] Move early buffered lint ambigous-glob-imports to a dyn lint diagnostic --- compiler/rustc_errors/src/lib.rs | 16 ------- compiler/rustc_lint/src/early/diagnostics.rs | 3 -- compiler/rustc_lint/src/lints.rs | 13 ------ compiler/rustc_lint_defs/src/lib.rs | 18 -------- compiler/rustc_resolve/src/diagnostics.rs | 43 ++++++++----------- compiler/rustc_resolve/src/errors.rs | 45 +++++++++++++++++++- 6 files changed, 61 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b8dda9ed57431..876a5340d93ed 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -2049,22 +2049,6 @@ pub fn elided_lifetime_in_path_suggestion( ElidedLifetimeInPathSubdiag { expected, indicate } } -pub fn report_ambiguity_error<'a, G: EmissionGuarantee>( - diag: &mut Diag<'a, G>, - ambiguity: rustc_lint_defs::AmbiguityErrorDiag, -) { - diag.span_label(ambiguity.label_span, ambiguity.label_msg); - diag.note(ambiguity.note_msg); - diag.span_note(ambiguity.b1_span, ambiguity.b1_note_msg); - for help_msg in ambiguity.b1_help_msgs { - diag.help(help_msg); - } - diag.span_note(ambiguity.b2_span, ambiguity.b2_note_msg); - for help_msg in ambiguity.b2_help_msgs { - diag.help(help_msg); - } -} - /// Grammatical tool for displaying messages to end users in a nice form. /// /// Returns "an" if the given string starts with a vowel, and "a" otherwise. diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 34bb3989008ea..e376d7d2ab883 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -251,9 +251,6 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag); } - BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => { - lints::AmbiguousGlobImports { ambiguity }.decorate_lint(diag); - } BuiltinLintDiag::AmbiguousGlobReexports { name, namespace, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 43786db8bdce0..0687490645d3f 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -15,7 +15,6 @@ use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::inhabitedness::InhabitedPredicate; use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt}; use rustc_session::Session; -use rustc_session::lint::AmbiguityErrorDiag; use rustc_span::edition::Edition; use rustc_span::{Ident, Span, Symbol, sym}; @@ -2836,18 +2835,6 @@ pub(crate) struct NamedArgumentUsedPositionally { pub named_arg_name: String, } -// FIXME: make this translatable -pub(crate) struct AmbiguousGlobImports { - pub ambiguity: AmbiguityErrorDiag, -} - -impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { - diag.primary_message(self.ambiguity.msg.clone()); - rustc_errors::report_ambiguity_error(diag, self.ambiguity); - } -} - #[derive(LintDiagnostic)] #[diag(lint_ambiguous_glob_reexport)] pub(crate) struct AmbiguousGlobReexports { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 8acb5eb319912..326fdaf9cec92 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -593,21 +593,6 @@ impl StableCompare for LintId { } } -#[derive(Debug)] -pub struct AmbiguityErrorDiag { - pub msg: String, - pub span: Span, - pub label_span: Span, - pub label_msg: String, - pub note_msg: String, - pub b1_span: Span, - pub b1_note_msg: String, - pub b1_help_msgs: Vec, - pub b2_span: Span, - pub b2_note_msg: String, - pub b2_help_msgs: Vec, -} - #[derive(Debug, Clone)] pub enum DeprecatedSinceKind { InEffect, @@ -678,9 +663,6 @@ pub enum BuiltinLintDiag { /// Indicates if the named argument is used as a width/precision for formatting is_formatting_arg: bool, }, - AmbiguousGlobImports { - diag: AmbiguityErrorDiag, - }, AmbiguousGlobReexports { /// The name for which collision(s) have occurred. name: String, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index fe299a6cebca7..f6219808945e4 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -11,7 +11,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, MultiSpan, SuggestionStyle, - report_ambiguity_error, struct_span_code_err, + struct_span_code_err, }; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem}; @@ -22,16 +22,16 @@ use rustc_hir::{PrimTy, Stability, StabilityLevel, find_attr}; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::Session; +use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, }; -use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiag}; use rustc_session::utils::was_invoked_from_cargo; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; -use rustc_span::source_map::SourceMap; +use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::{BytePos, Ident, Macros20NormalizedIdent, Span, Symbol, SyntaxContext, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use tracing::{debug, instrument}; @@ -145,7 +145,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } for ambiguity_error in &self.ambiguity_errors { - let diag = self.ambiguity_diagnostics(ambiguity_error); + let diag = self.ambiguity_diagnostic(ambiguity_error); + if ambiguity_error.warning { let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else { unreachable!() @@ -153,13 +154,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.lint_buffer.buffer_lint( AMBIGUOUS_GLOB_IMPORTS, import.root_id, - ambiguity_error.ident.span, - BuiltinLintDiag::AmbiguousGlobImports { diag }, + diag.ident.span, + diag, ); } else { - let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", diag.msg); - report_ambiguity_error(&mut err, diag); - err.emit(); + self.dcx().emit_err(diag); } } @@ -1995,7 +1994,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - fn ambiguity_diagnostics(&self, ambiguity_error: &AmbiguityError<'ra>) -> AmbiguityErrorDiag { + fn ambiguity_diagnostic(&self, ambiguity_error: &AmbiguityError<'ra>) -> errors::Ambiguity { let AmbiguityError { kind, ident, b1, b2, misc1, misc2, .. } = *ambiguity_error; let extern_prelude_ambiguity = || { self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)).is_some_and(|entry| { @@ -2038,8 +2037,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } ( - b.span, - note_msg, + Spanned { node: note_msg, span: b.span }, help_msgs .iter() .enumerate() @@ -2050,20 +2048,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .collect::>(), ) }; - let (b1_span, b1_note_msg, b1_help_msgs) = could_refer_to(b1, misc1, ""); - let (b2_span, b2_note_msg, b2_help_msgs) = could_refer_to(b2, misc2, " also"); - - AmbiguityErrorDiag { - msg: format!("`{ident}` is ambiguous"), - span: ident.span, - label_span: ident.span, - label_msg: "ambiguous name".to_string(), - note_msg: format!("ambiguous because of {}", kind.descr()), - b1_span, - b1_note_msg, + let (b1_note, b1_help_msgs) = could_refer_to(b1, misc1, ""); + let (b2_note, b2_help_msgs) = could_refer_to(b2, misc2, " also"); + + errors::Ambiguity { + ident, + kind: kind.descr(), + b1_note, b1_help_msgs, - b2_span, - b2_note_msg, + b2_note, b2_help_msgs, } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index fe1f0d253a127..af58d88ec35f2 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,9 +1,10 @@ use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagMessage, ElidedLifetimeInPathSubdiag, EmissionGuarantee, IntoDiagArg, - LintDiagnostic, MultiSpan, Subdiagnostic, + Applicability, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, ElidedLifetimeInPathSubdiag, + EmissionGuarantee, IntoDiagArg, Level, LintDiagnostic, MultiSpan, Subdiagnostic, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; +use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span, Symbol}; use crate::late::PatternSource; @@ -1445,3 +1446,43 @@ pub(crate) struct UnknownDiagnosticAttributeTypoSugg { pub span: Span, pub typo_name: Symbol, } + +// FIXME: Make this properly translatable. +pub(crate) struct Ambiguity { + pub ident: Ident, + pub kind: &'static str, + pub b1_note: Spanned, + pub b1_help_msgs: Vec, + pub b2_note: Spanned, + pub b2_help_msgs: Vec, +} + +impl Ambiguity { + fn decorate<'a>(self, diag: &mut Diag<'a, impl EmissionGuarantee>) { + diag.primary_message(format!("`{}` is ambiguous", self.ident)); + diag.span_label(self.ident.span, "ambiguous name"); + diag.note(format!("ambiguous because of {}", self.kind)); + diag.span_note(self.b1_note.span, self.b1_note.node); + for help_msg in self.b1_help_msgs { + diag.help(help_msg); + } + diag.span_note(self.b2_note.span, self.b2_note.node); + for help_msg in self.b2_help_msgs { + diag.help(help_msg); + } + } +} + +impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for Ambiguity { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + let mut diag = Diag::new(dcx, level, "").with_span(self.ident.span).with_code(E0659); + self.decorate(&mut diag); + diag + } +} + +impl<'a> LintDiagnostic<'a, ()> for Ambiguity { + fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { + self.decorate(diag); + } +}