From 006fae361aa1c0cf4b998fbe91bebe5fbf6fcb5c Mon Sep 17 00:00:00 2001 From: Edvin Bryntesson Date: Tue, 27 Oct 2026 18:07:07 +0100 Subject: [PATCH 1/4] don't parse lint attrs in pre-expansion --- compiler/rustc_errors/src/decorate_diag.rs | 18 +- compiler/rustc_errors/src/diagnostic.rs | 13 + compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_expand/src/base.rs | 6 +- compiler/rustc_expand/src/expand.rs | 3 +- compiler/rustc_interface/src/passes.rs | 22 +- compiler/rustc_lint/src/builtin.rs | 14 +- compiler/rustc_lint/src/context.rs | 22 +- compiler/rustc_lint/src/early.rs | 235 +++++++++++++++--- compiler/rustc_lint/src/levels.rs | 2 +- compiler/rustc_lint/src/lib.rs | 7 +- compiler/rustc_lint/src/passes.rs | 21 +- compiler/rustc_resolve/src/macros.rs | 6 +- .../src/attrs/deprecated_cfg_attr.rs | 10 +- .../clippy/clippy_lints/src/attrs/mod.rs | 10 +- .../clippy_lints/src/attrs/non_minimal_cfg.rs | 6 +- .../src/attrs/unnecessary_clippy_cfg.rs | 4 +- .../src/nonstandard_macro_braces.rs | 14 +- src/tools/clippy/clippy_utils/src/lib.rs | 7 +- src/tools/clippy/clippy_utils/src/source.rs | 4 +- 20 files changed, 317 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_errors/src/decorate_diag.rs b/compiler/rustc_errors/src/decorate_diag.rs index 382a3b2758407..3b307922bea0e 100644 --- a/compiler/rustc_errors/src/decorate_diag.rs +++ b/compiler/rustc_errors/src/decorate_diag.rs @@ -1,13 +1,14 @@ use std::any::Any; /// This module provides types and traits for buffering lints until later in compilation. +use rustc_ast::AttrId; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_error_messages::MultiSpan; use rustc_lint_defs::{Lint, LintId}; -use crate::{Diag, DiagCtxtHandle, Diagnostic, Level}; +use crate::{Diag, DiagCtxtHandle, DiagInner, Diagnostic, Level}; pub struct DecorateDiagCompat( /// The third argument of the closure is a `Session`. However, due to the dependency tree, @@ -51,19 +52,28 @@ pub struct BufferedEarlyLint { pub diagnostic: DecorateDiagCompat, } +#[derive(Debug)] +pub struct PreExpansionLint { + pub lint: &'static Lint, + pub span: Option, + pub diag: DiagInner, + pub attrs: Vec, +} + #[derive(Default, Debug)] pub struct LintBuffer { - pub map: FxIndexMap>, + pub early: FxIndexMap>, + pub pre_expansion: Vec, } impl LintBuffer { pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) { - self.map.entry(early_lint.node_id).or_default().push(early_lint); + self.early.entry(early_lint.node_id).or_default().push(early_lint); } pub fn take(&mut self, id: NodeId) -> Vec { // FIXME(#120456) - is `swap_remove` correct? - self.map.swap_remove(&id).unwrap_or_default() + self.early.swap_remove(&id).unwrap_or_default() } pub fn buffer_lint( diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 65dc8042fd409..aedb22174e431 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -453,6 +453,19 @@ impl<'a> Diag<'a> { Self { dcx, diag: Some(Box::new(diag)) } } + pub fn from_inner_with_level( + dcx: DiagCtxtHandle<'a>, + mut diag: DiagInner, + level: Level, + ) -> Self { + diag.level = level; + Self::new_diagnostic(dcx, diag) + } + + pub fn into_inner(mut self) -> DiagInner { + self.take_diag() + } + /// Delay emission of this diagnostic as a bug. /// /// This can be useful in contexts where an error indicates a bug but diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a1ccefefbcb2a..04876244af8ff 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -30,7 +30,7 @@ pub use anstyle::{ Ansi256Color, AnsiColor, Color, EffectIter, Effects, Reset, RgbColor, Style as Anstyle, }; pub use codes::*; -pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer}; +pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer, PreExpansionLint}; pub use diagnostic::{ Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic, StringPart, Subdiag, Subdiagnostic, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 501bb21c1eea9..e60be076c1eb6 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -11,7 +11,7 @@ use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind use rustc_attr_ir::{self as attrs, CfgEntry, Deprecation, Stability, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::sync; -use rustc_errors::{BufferedEarlyLint, DiagCtxtHandle, ErrorGuaranteed}; +use rustc_errors::{BufferedEarlyLint, DiagCtxtHandle, ErrorGuaranteed, PreExpansionLint}; use rustc_feature::Features; use rustc_hir::def::MacroKinds; use rustc_lint_defs::RegisteredTools; @@ -1132,6 +1132,8 @@ pub trait ResolverExpand { /// Mark the scope as having a compile error so that error for lookup in this scope /// should be suppressed fn mark_scope_with_compile_error(&mut self, parent_node: NodeId); + + fn buffer_pre_expansion_lints(&mut self, lints: Vec); } pub trait LintStoreExpand { @@ -1144,7 +1146,7 @@ pub trait LintStoreExpand { attrs: &[Attribute], items: &[Box], name: Symbol, - ); + ) -> Vec; } type LintStoreExpandDyn<'a> = Option<&'a (dyn LintStoreExpand + 'a)>; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 1909712888828..f8f6bc04a98c0 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1410,7 +1410,7 @@ impl InvocationCollectorNode for Box { ); if let Some(lint_store) = ecx.lint_store { - lint_store.pre_expansion_lint( + let lints = lint_store.pre_expansion_lint( ecx.sess, ecx.ecfg.features, ecx.resolver.registered_lint_tools(), @@ -1419,6 +1419,7 @@ impl InvocationCollectorNode for Box { &items, ident.name, ); + ecx.resolver.buffer_pre_expansion_lints(lints); } *mod_kind = ModKind::Loaded(items, Inline::No { had_parse_error }, spans); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 73bebb22bc508..aeac0c67d0244 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -18,7 +18,7 @@ use rustc_data_structures::sync::{ }; use rustc_data_structures::thousands; use rustc_errors::timings::TimingSection; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, PreExpansionLint}; use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_feature::Features; use rustc_fs_util::try_canonicalize; @@ -93,20 +93,18 @@ fn pre_expansion_lint<'a>( registered_lint_tools: &RegisteredTools, check_node: EarlyCheckNode<'a>, node_name: Symbol, -) { +) -> Vec { sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run( || { - rustc_lint::check_ast_node( + rustc_lint::check_ast_node_pre_expansion( sess, features, - true, lint_store, registered_lint_tools, - None, check_node, - ); + ) }, - ); + ) } // Cannot implement directly for `LintStore` due to trait coherence. @@ -122,9 +120,9 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { attrs: &[ast::Attribute], items: &[Box], name: Symbol, - ) { + ) -> Vec { let check_node = EarlyCheckNode::LoadedMod(node_id, attrs, items); - pre_expansion_lint(sess, features, self.0, registered_lint_tools, check_node, name); + pre_expansion_lint(sess, features, self.0, registered_lint_tools, check_node, name) } } @@ -143,7 +141,7 @@ fn configure_and_expand( let features = tcx.features(); let lint_store = unerased_lint_store(sess); let crate_name = tcx.crate_name(LOCAL_CRATE); - pre_expansion_lint( + let lints = pre_expansion_lint( sess, features, lint_store, @@ -151,6 +149,7 @@ fn configure_and_expand( EarlyCheckNode::CrateRoot(&krate, pre_configured_attrs), crate_name, ); + resolver.lint_buffer().pre_expansion.extend(lints); rustc_builtin_macros::register_builtin_macros(resolver); let num_standard_library_imports = sess.time("crate_injection", || { @@ -490,10 +489,9 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { rustc_lint::check_ast_node( sess, tcx.features(), - false, lint_store, tcx.registered_lint_tools(()), - Some(lint_buffer), + lint_buffer, EarlyCheckNode::CrateRoot(&*krate, &*krate.attrs), ) } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d19d6a0da98ac..fafb91ef8c692 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -59,7 +59,7 @@ use crate::diagnostics::{ BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, BuiltinWhileTrue, EqInternalMethodImplemented, InvalidAsmLabel, }; -use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; +use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, PreExpansion}; declare_lint! { /// The `while_true` lint detects `while true { }`. @@ -1744,7 +1744,7 @@ declare_lint_pass!( struct UnderMacro(bool); impl KeywordIdents { - fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: &TokenStream) { + fn check_tokens(&mut self, cx: &EarlyContext<'_, PreExpansion>, tokens: &TokenStream) { // Check if the preceding token is `$`, because we want to allow `$async`, etc. let mut prev_dollar = false; for tt in tokens.iter() { @@ -1775,7 +1775,7 @@ impl KeywordIdents { fn check_ident_token( &mut self, - cx: &EarlyContext<'_>, + cx: &EarlyContext<'_, PreExpansion>, UnderMacro(under_macro): UnderMacro, ident: Ident, prefix: &'static str, @@ -1817,14 +1817,14 @@ impl KeywordIdents { } } -impl EarlyLintPass for KeywordIdents { - fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef) { +impl EarlyLintPass for KeywordIdents { + fn check_mac_def(&mut self, cx: &EarlyContext<'_, PreExpansion>, mac_def: &ast::MacroDef) { self.check_tokens(cx, &mac_def.body.tokens); } - fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) { + fn check_mac(&mut self, cx: &EarlyContext<'_, PreExpansion>, mac: &ast::MacCall) { self.check_tokens(cx, &mac.args.tokens); } - fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: &Ident) { + fn check_ident(&mut self, cx: &EarlyContext<'_, PreExpansion>, ident: &Ident) { if ident.name.as_str().starts_with('\'') { self.check_ident_token(cx, UnderMacro(false), ident.without_first_quote(), "'"); } else { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 9678ed65d2891..fc1c2379d3962 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -35,11 +35,12 @@ use rustc_span::{Ident, Span, Symbol, bug, sym}; use tracing::debug; use self::TargetLint::*; +use crate::early::{EarlyLintMode, PostExpansion, PreExpansion}; use crate::levels::LintLevelsBuilder; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; -pub(crate) type EarlyLintPassFactory = - Box EarlyLintPassObject + sync::DynSend + sync::DynSync>; +pub(crate) type EarlyLintPassFactory = + Box EarlyLintPassObject + sync::DynSend + sync::DynSync>; type LateLintPassFactory = Box Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync>; @@ -59,7 +60,7 @@ pub struct LintStore { /// /// * See [rust#69838](https://github.com/rust-lang/rust/pull/69838) /// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518) - pub(crate) pre_expansion_lint_passes: Vec, + pub(crate) pre_expansion_lint_passes: Vec>, /// These lint passes run on AST nodes. pub(crate) early_lint_passes: Vec, @@ -183,7 +184,7 @@ impl LintStore { } /// See the comment on `LintStore::pre_expansion_lint_passes`. - pub fn register_pre_expansion_lint_pass(&mut self, pass: EarlyLintPassFactory) { + pub fn register_pre_expansion_lint_pass(&mut self, pass: EarlyLintPassFactory) { self.pre_expansion_lint_passes.push(pass); } @@ -501,9 +502,10 @@ pub struct LateContext<'tcx> { } /// Context for lint checking of the AST, after expansion, before lowering to HIR. -pub struct EarlyContext<'a> { +pub struct EarlyContext<'a, M = PostExpansion> { pub builder: LintLevelsBuilder<'a, crate::levels::TopDown>, pub buffered: LintBuffer, + pub(crate) mode: M, } pub trait LintContext { @@ -551,7 +553,7 @@ pub trait LintContext { } } -impl<'a> EarlyContext<'a> { +impl<'a, M: EarlyLintMode> EarlyContext<'a, M> { pub(crate) fn new( sess: &'a Session, features: &'a Features, @@ -559,7 +561,8 @@ impl<'a> EarlyContext<'a> { lint_store: &'a LintStore, registered_lint_tools: &'a RegisteredTools, buffered: LintBuffer, - ) -> EarlyContext<'a> { + mode: M, + ) -> EarlyContext<'a, M> { EarlyContext { builder: LintLevelsBuilder::new( sess, @@ -569,6 +572,7 @@ impl<'a> EarlyContext<'a> { registered_lint_tools, ), buffered, + mode, } } } @@ -600,7 +604,7 @@ impl<'tcx> LintContext for LateContext<'tcx> { } } -impl LintContext for EarlyContext<'_> { +impl LintContext for EarlyContext<'_, M> { type LintExpectationId = UnstableLintExpectationId; /// Gets the overall compiler `Session` object. @@ -614,7 +618,7 @@ impl LintContext for EarlyContext<'_> { span: Option, decorator: impl for<'a> Diagnostic<'a>, ) { - self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorator) + M::opt_span_lint(self, lint, span.map(|s| s.into()), decorator) } fn get_lint_level_spec(&self, lint: &'static Lint) -> UnstableLevelSpec { diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index d55ea5553d2df..e9e06d0622d91 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -4,11 +4,17 @@ //! resolution, just before AST lowering. These lints are for purely //! syntactical lints. +use std::cell::Cell; + use rustc_ast::visit::{self as ast_visit, Visitor, walk_list}; -use rustc_ast::{self as ast, AttrVec, HasAttrs}; -use rustc_errors::{BufferedEarlyLint, LintBuffer}; +use rustc_ast::{self as ast, AttrId, AttrVec, HasAttrs}; +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::{ + BufferedEarlyLint, Diag, DiagCtxtHandle, DiagInner, Diagnostic, Level, LintBuffer, MultiSpan, + PreExpansionLint, +}; use rustc_feature::Features; -use rustc_lint_defs::LintPass; +use rustc_lint_defs::{Lint, LintPass}; use rustc_middle::ty::RegisteredTools; use rustc_session::Session; use rustc_span::{Ident, Span}; @@ -16,22 +22,152 @@ use tracing::debug; use crate::DiagAndSess; use crate::context::{EarlyContext, EarlyLintPassFactory, LintContext, LintStore}; +use crate::levels::BuilderPush; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; pub(super) mod diagnostics; +pub trait EarlyLintMode: Sized + 'static { + type Scope; + + fn enter( + cx: &mut EarlyContext<'_, Self>, + attrs: &[ast::Attribute], + is_crate_node: bool, + ) -> Self::Scope; + + fn exit( + cx: &mut EarlyContext<'_, Self>, + attrs: &[ast::Attribute], + is_crate_node: bool, + scope: Self::Scope, + ); + + fn opt_span_lint( + cx: &EarlyContext<'_, Self>, + lint: &'static Lint, + span: Option, + decorator: impl for<'a> Diagnostic<'a>, + ); +} + +#[derive(Default)] +pub struct PreExpansion { + attrs: Vec, + lints: Cell>, +} + +impl EarlyLintMode for PreExpansion { + type Scope = usize; + + fn enter(cx: &mut EarlyContext<'_, Self>, attrs: &[ast::Attribute], _: bool) -> usize { + let len = cx.mode.attrs.len(); + cx.mode.attrs.extend(attrs.iter().map(|attr| attr.id)); + len + } + + fn exit(cx: &mut EarlyContext<'_, Self>, _: &[ast::Attribute], _: bool, len: usize) { + cx.mode.attrs.truncate(len); + } + + fn opt_span_lint( + cx: &EarlyContext<'_, Self>, + lint: &'static Lint, + span: Option, + decorator: impl for<'a> Diagnostic<'a>, + ) { + let diag = decorator.into_diag(cx.sess().dcx(), Level::Warning(None)).into_inner(); + let mut lints = cx.mode.lints.take(); + lints.push(PreExpansionLint { lint, span, diag, attrs: cx.mode.attrs.clone() }); + cx.mode.lints.set(lints); + } +} + +#[derive(Default)] +pub struct PostExpansion { + lints: Vec>, + by_attr: FxHashMap>, +} + +impl PostExpansion { + fn new(lints: Vec) -> Self { + let mut by_attr: FxHashMap> = Default::default(); + for (i, lint) in lints.iter().enumerate() { + for &attr in &lint.attrs { + by_attr.entry(attr).or_default().push(i); + } + } + PostExpansion { lints: lints.into_iter().map(Some).collect(), by_attr } + } +} + +impl EarlyLintMode for PostExpansion { + type Scope = BuilderPush; + + fn enter( + cx: &mut EarlyContext<'_, Self>, + attrs: &[ast::Attribute], + is_crate_node: bool, + ) -> BuilderPush { + cx.builder.push(attrs, is_crate_node) + } + + fn exit( + cx: &mut EarlyContext<'_, Self>, + attrs: &[ast::Attribute], + is_crate_node: bool, + push: BuilderPush, + ) { + let PostExpansion { lints, by_attr } = &mut cx.mode; + if !by_attr.is_empty() || (is_crate_node && !lints.is_empty()) { + let mut to_emit = Vec::new(); + if is_crate_node { + to_emit.extend(lints.drain(..).flatten()); + by_attr.clear(); + } else { + for attr in attrs { + if let Some(idxs) = by_attr.remove(&attr.id) { + to_emit.extend(idxs.into_iter().filter_map(|i| lints[i].take())); + } + } + } + for PreExpansionLint { lint, span, diag, attrs: _ } in to_emit { + cx.builder.opt_span_lint(lint, span, PreExpansionDiag(diag)); + } + } + cx.builder.pop(push); + } + + fn opt_span_lint( + cx: &EarlyContext<'_, Self>, + lint: &'static Lint, + span: Option, + decorator: impl for<'a> Diagnostic<'a>, + ) { + cx.builder.opt_span_lint(lint, span, decorator) + } +} + +struct PreExpansionDiag(DiagInner); + +impl<'a> Diagnostic<'a> for PreExpansionDiag { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { + Diag::from_inner_with_level(dcx, self.0, level) + } +} + macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } /// Implements the AST traversal for early lint passes. `T` provides the /// `check_*` methods. -struct EarlyContextAndPass<'ecx, T: EarlyLintPass> { - context: EarlyContext<'ecx>, +struct EarlyContextAndPass<'ecx, T: EarlyLintPass, M: EarlyLintMode> { + context: EarlyContext<'ecx, M>, pass: T, } -impl<'ecx, T: EarlyLintPass> EarlyContextAndPass<'ecx, T> { +impl<'ecx, T: EarlyLintPass, M: EarlyLintMode> EarlyContextAndPass<'ecx, T, M> { fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; @@ -52,18 +188,20 @@ impl<'ecx, T: EarlyLintPass> EarlyContextAndPass<'ecx, T> { { let is_crate_node = id == ast::CRATE_NODE_ID; debug!(?id); - let push = self.context.builder.push(attrs, is_crate_node); + let scope = M::enter(&mut self.context, attrs, is_crate_node); debug!("early context: enter_attrs({:?})", attrs); lint_callback!(self, check_attributes, attrs); f(self); debug!("early context: exit_attrs({:?})", attrs); lint_callback!(self, check_attributes_post, attrs); - self.context.builder.pop(push); + M::exit(&mut self.context, attrs, is_crate_node, scope); } } -impl<'ast, 'ecx, T: EarlyLintPass> ast_visit::Visitor<'ast> for EarlyContextAndPass<'ecx, T> { +impl<'ast, 'ecx, T: EarlyLintPass, M: EarlyLintMode> ast_visit::Visitor<'ast> + for EarlyContextAndPass<'ecx, T, M> +{ fn visit_id(&mut self, id: rustc_ast::NodeId) { self.check_id(id); } @@ -245,12 +383,12 @@ impl<'ast, 'ecx, T: EarlyLintPass> ast_visit::Visitor<'ast> for EarlyContextAndP // `check_foo` method in `$methods` within this pass simply calls `check_foo` // once per `$pass`. Compare with `declare_combined_early_lint_pass`, which is // similar, but combines lint passes at compile time. -struct RuntimeCombinedEarlyLintPass { - passes: Vec, +struct RuntimeCombinedEarlyLintPass { + passes: Vec>, } #[allow(rustc::lint_pass_impl_without_macro)] -impl LintPass for RuntimeCombinedEarlyLintPass { +impl LintPass for RuntimeCombinedEarlyLintPass { fn name(&self) -> &'static str { panic!() } @@ -261,8 +399,8 @@ impl LintPass for RuntimeCombinedEarlyLintPass { macro_rules! impl_early_lint_pass { ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => ( - impl EarlyLintPass for RuntimeCombinedEarlyLintPass { - $(fn $f(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) { + impl EarlyLintPass for RuntimeCombinedEarlyLintPass { + $(fn $f(&mut self, context: &EarlyContext<'_, M>, $($param: $arg),*) { for pass in self.passes.iter_mut() { pass.$f(context, $($param),*); } @@ -293,7 +431,10 @@ impl<'a> EarlyCheckNode<'a> { EarlyCheckNode::LoadedMod(_id, attrs, _items) => attrs, } } - fn check<'ecx, T: EarlyLintPass>(&self, cx: &mut EarlyContextAndPass<'ecx, T>) { + fn check<'ecx, T: EarlyLintPass, M: EarlyLintMode>( + &self, + cx: &mut EarlyContextAndPass<'ecx, T, M>, + ) { match self { EarlyCheckNode::CrateRoot(crate_, _attrs) => { lint_callback!(cx, check_crate, crate_); @@ -308,38 +449,58 @@ impl<'a> EarlyCheckNode<'a> { } } +pub fn check_ast_node_pre_expansion<'a>( + sess: &Session, + features: &Features, + lint_store: &LintStore, + registered_lint_tools: &RegisteredTools, + check_node: EarlyCheckNode<'a>, +) -> Vec { + let context = EarlyContext::new( + sess, + features, + false, + lint_store, + registered_lint_tools, + LintBuffer::default(), + PreExpansion::default(), + ); + let builtin_lints = crate::BuiltinCombinedPreExpansionLintPass::new(); + let passes = &lint_store.pre_expansion_lint_passes; + let context = run_passes(check_node, context, builtin_lints, passes); + check_buffered_lints_emitted(sess, context.buffered); + context.mode.lints.into_inner() +} + pub fn check_ast_node<'a>( sess: &Session, features: &Features, - pre_expansion: bool, lint_store: &LintStore, registered_lint_tools: &RegisteredTools, - lint_buffer: Option, + mut lint_buffer: LintBuffer, check_node: EarlyCheckNode<'a>, ) { + let pre_expansion_lints = std::mem::take(&mut lint_buffer.pre_expansion); let context = EarlyContext::new( sess, features, - !pre_expansion, + true, lint_store, registered_lint_tools, - lint_buffer.unwrap_or_default(), + lint_buffer, + PostExpansion::new(pre_expansion_lints), ); + let builtin_lints = crate::BuiltinCombinedEarlyLintPass::new(); + let passes = &lint_store.early_lint_passes; + let context = run_passes(check_node, context, builtin_lints, passes); + check_buffered_lints_emitted(sess, context.buffered); +} - let context = if pre_expansion { - let builtin_lints = crate::BuiltinCombinedPreExpansionLintPass::new(); - let passes = &lint_store.pre_expansion_lint_passes; - run_passes(check_node, context, builtin_lints, passes) - } else { - let builtin_lints = crate::BuiltinCombinedEarlyLintPass::new(); - let passes = &lint_store.early_lint_passes; - run_passes(check_node, context, builtin_lints, passes) - }; - +fn check_buffered_lints_emitted(sess: &Session, buffered: LintBuffer) { // All of the buffered lints should have been emitted at this point. // If not, that means that we somehow buffered a lint for a node id // that was not lint-checked (perhaps it doesn't exist?). This is a bug. - for (id, lints) in context.buffered.map { + for (id, lints) in buffered.early { if !lints.is_empty() { assert!( sess.dcx().has_errors().is_some(), @@ -351,12 +512,12 @@ pub fn check_ast_node<'a>( } } -fn run_passes<'a, 'ecx, T: EarlyLintPass + 'static>( +fn run_passes<'a, 'ecx, T: EarlyLintPass + 'static, M: EarlyLintMode>( check_node: EarlyCheckNode<'a>, - context: EarlyContext<'ecx>, + context: EarlyContext<'ecx, M>, builtin_lints: T, - passes: &[EarlyLintPassFactory], -) -> EarlyContext<'ecx> { + passes: &[EarlyLintPassFactory], +) -> EarlyContext<'ecx, M> { // Note: `passes` is often empty. In that case, it's faster to run // `builtin_lints` directly rather than bundling it up into the // `RuntimeCombinedEarlyLintPass`. @@ -370,11 +531,11 @@ fn run_passes<'a, 'ecx, T: EarlyLintPass + 'static>( } } -fn run_pass<'a, 'ecx, T: EarlyLintPass>( +fn run_pass<'a, 'ecx, T: EarlyLintPass, M: EarlyLintMode>( check_node: EarlyCheckNode<'a>, - context: EarlyContext<'ecx>, + context: EarlyContext<'ecx, M>, pass: T, -) -> EarlyContext<'ecx> { +) -> EarlyContext<'ecx, M> { let mut cx = EarlyContextAndPass { context, pass }; cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); cx.context diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index a442c62819c8d..26a28b879743b 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -377,7 +377,7 @@ pub struct LintLevelsBuilder<'s, P> { registered_lint_tools: &'s RegisteredTools, } -pub(crate) struct BuilderPush { +pub struct BuilderPush { prev: LintStackIndex, } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index e144285553188..7df216a8392d8 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -139,7 +139,10 @@ use unused::*; pub use builtin::MissingDoc; pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore}; pub use early::diagnostics::DiagAndSess; -pub use early::{EarlyCheckNode, check_ast_node}; +pub use early::{ + EarlyCheckNode, EarlyLintMode, PostExpansion, PreExpansion, check_ast_node, + check_ast_node_pre_expansion, +}; pub use late::{check_crate, late_lint_mod, unerased_lint_store}; pub use levels::LintLevelsBuilder; pub use passes::{EarlyLintPass, LateLintPass}; @@ -165,7 +168,7 @@ fn lint_mod(tcx: TyCtxt<'_>, mod_id: LocalModId) { early_lint_methods!( declare_combined_early_lint_pass, [ - pub BuiltinCombinedPreExpansionLintPass, + pub BuiltinCombinedPreExpansionLintPass, [ // tidy-alphabetical-start KeywordIdents: KeywordIdents, diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 98ab44c37e26a..99e95bd105850 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -1,6 +1,7 @@ use rustc_lint_defs::LintPass; use crate::context::{EarlyContext, LateContext}; +use crate::early::{EarlyLintMode, PostExpansion}; #[macro_export] macro_rules! late_lint_methods { @@ -173,8 +174,8 @@ macro_rules! early_lint_methods { macro_rules! declare_early_lint_pass { ([], [$(fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - pub trait EarlyLintPass: LintPass { - $(#[inline(always)] fn $name(&mut self, _: &EarlyContext<'_>, $(_: $arg),*) {})* + pub trait EarlyLintPass: LintPass { + $(#[inline(always)] fn $name(&mut self, _: &EarlyContext<'_, M>, $(_: $arg),*) {})* } ) } @@ -192,8 +193,8 @@ macro_rules! expand_combined_early_lint_pass_method { #[macro_export] macro_rules! expand_combined_early_lint_pass_methods { - ($passes:tt, [$(fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - $(fn $name(&mut self, context: &$crate::EarlyContext<'_>, $($param: $arg),*) { + ($passes:tt, $mode:ty, [$(fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + $(fn $name(&mut self, context: &$crate::EarlyContext<'_, $mode>, $($param: $arg),*) { $crate::expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*)); })* ) @@ -207,6 +208,12 @@ macro_rules! expand_combined_early_lint_pass_methods { #[macro_export] macro_rules! declare_combined_early_lint_pass { ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => ( + $crate::declare_combined_early_lint_pass!( + [$v $name<$crate::PostExpansion>, [$($pass: $constructor,)*]], + $methods + ); + ); + ([$v:vis $name:ident<$mode:ty>, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => ( #[allow(non_snake_case)] $v struct $name { $($pass: $pass,)* @@ -226,8 +233,8 @@ macro_rules! declare_combined_early_lint_pass { } } - impl $crate::EarlyLintPass for $name { - $crate::expand_combined_early_lint_pass_methods!([$($pass),*], $methods); + impl $crate::EarlyLintPass<$mode> for $name { + $crate::expand_combined_early_lint_pass_methods!([$($pass),*], $mode, $methods); } #[allow(rustc::lint_pass_impl_without_macro)] @@ -243,5 +250,5 @@ macro_rules! declare_combined_early_lint_pass { } /// A lint pass boxed up as a trait object. -pub(crate) type EarlyLintPassObject = Box; +pub(crate) type EarlyLintPassObject = Box>; pub(crate) type LateLintPassObject<'tcx> = Box + 'tcx>; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 628b93bd5e46c..077db41da7372 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -9,7 +9,7 @@ use rustc_ast_pretty::pprust; use rustc_attr_ir::{Attribute, AttributeKind, CfgEntry, StabilityLevel, StrippedCfgItem}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::sync::RwLock; -use rustc_errors::{Applicability, StashKey}; +use rustc_errors::{Applicability, PreExpansionLint, StashKey}; use rustc_expand::base::{ Annotatable, DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind, @@ -178,6 +178,10 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { self.invocation_parents[&id].parent_def } + fn buffer_pre_expansion_lints(&mut self, lints: Vec) { + self.lint_buffer.pre_expansion.extend(lints); + } + fn mark_scope_with_compile_error(&mut self, id: NodeId) { if let Some(id) = self.owners.get(&id).map(|i| i.def_id) && self.tcx.def_kind(id).is_module_like() diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs index 29169770ca730..caf05a67fdf00 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs @@ -4,9 +4,9 @@ use clippy_utils::msrvs::{self, MsrvStack}; use clippy_utils::sym; use rustc_ast::AttrStyle; use rustc_errors::Applicability; -use rustc_lint::EarlyContext; +use rustc_lint::{EarlyContext, PreExpansion}; -pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) { +pub(super) fn check(cx: &EarlyContext<'_, PreExpansion>, attr: &Attribute, msrv: &MsrvStack) { // check cfg_attr if attr.has_name(sym::cfg_attr) && let Some(items) = attr.meta_item_list() @@ -49,7 +49,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) { } } -pub(super) fn check_clippy(cx: &EarlyContext<'_>, attr: &Attribute) { +pub(super) fn check_clippy(cx: &EarlyContext<'_, PreExpansion>, attr: &Attribute) { if attr.has_name(sym::cfg) && let Some(list) = attr.meta_item_list() { @@ -59,7 +59,7 @@ pub(super) fn check_clippy(cx: &EarlyContext<'_>, attr: &Attribute) { } } -fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_>, attr: &rustc_ast::MetaItem) { +fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_, PreExpansion>, attr: &rustc_ast::MetaItem) { if let Some(ident) = attr.ident() { if matches!(ident.name, sym::any | sym::all | sym::not) { let Some(list) = attr.meta_item_list() else { return }; @@ -72,7 +72,7 @@ fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_>, attr: &rustc_ast::Met } } -fn check_cargo_clippy_attr(cx: &EarlyContext<'_>, item: &rustc_ast::MetaItem) { +fn check_cargo_clippy_attr(cx: &EarlyContext<'_, PreExpansion>, item: &rustc_ast::MetaItem) { if item.has_name(sym::feature) && item.value_str() == Some(sym::cargo_clippy) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index c79c12c5c91c4..df092ce59f877 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -20,7 +20,9 @@ use clippy_utils::msrvs::{self, Msrv, MsrvStack}; use clippy_utils::{check_clippy_attr, is_from_proc_macro}; use rustc_ast::{self as ast, AttrArgs, AttrKind, Attribute, MetaItemInner, MetaItemKind}; use rustc_hir::{ImplItem, ImplItemKind, Item, ItemKind, TraitFn, TraitItem, TraitItemKind}; -use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext as _, impl_lint_pass}; +use rustc_lint::{ + EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext as _, PreExpansion, impl_lint_pass, +}; use rustc_span::sym; use utils::is_lint_level; @@ -629,14 +631,14 @@ impl EarlyAttributes { } } -impl EarlyLintPass for EarlyAttributes { - fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { +impl EarlyLintPass for EarlyAttributes { + fn check_attribute(&mut self, cx: &EarlyContext<'_, PreExpansion>, attr: &Attribute) { deprecated_cfg_attr::check(cx, attr, &self.msrv); deprecated_cfg_attr::check_clippy(cx, attr); non_minimal_cfg::check(cx, attr); } - extract_msrv_attr!(); + extract_msrv_attr!(PreExpansion); } pub struct PostExpansionEarlyAttributes { diff --git a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs index b2b112cc9cf4f..95cfed175b376 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs @@ -3,10 +3,10 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::SpanExt as _; use rustc_ast::{MetaItemInner, MetaItemKind}; use rustc_errors::Applicability; -use rustc_lint::EarlyContext; +use rustc_lint::{EarlyContext, PreExpansion}; use rustc_span::sym; -pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { +pub(super) fn check(cx: &EarlyContext<'_, PreExpansion>, attr: &Attribute) { if attr.has_name(sym::cfg) && let Some(items) = attr.meta_item_list() { @@ -14,7 +14,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { } } -fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[MetaItemInner]) { +fn check_nested_cfg(cx: &EarlyContext<'_, PreExpansion>, items: &[MetaItemInner]) { for item in items { if let MetaItemInner::MetaItem(meta) = item { if !meta.has_name(sym::any) && !meta.has_name(sym::all) { diff --git a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs index 9e9fbb2c52582..3d5383e16e99a 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs @@ -4,11 +4,11 @@ use clippy_utils::source::SpanExt as _; use itertools::Itertools as _; use rustc_ast::AttrStyle; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, Level}; +use rustc_lint::{EarlyContext, Level, PreExpansion}; use rustc_span::sym; pub(super) fn check( - cx: &EarlyContext<'_>, + cx: &EarlyContext<'_, PreExpansion>, cfg_attr: &rustc_ast::MetaItem, behind_cfg_attr: &rustc_ast::MetaItem, attr: &Attribute, diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs index 46a251b7b7278..65660ae690e97 100644 --- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs +++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs @@ -6,7 +6,7 @@ use rustc_ast::token::{Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass, impl_lint_pass}; +use rustc_lint::{EarlyContext, EarlyLintMode, EarlyLintPass, impl_lint_pass}; use rustc_span::Span; use crate::rustc_lint::LintContext as _; @@ -51,8 +51,8 @@ impl MacroBraces { } } -impl EarlyLintPass for MacroBraces { - fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) { +impl EarlyLintPass for MacroBraces { + fn check_mac(&mut self, cx: &EarlyContext<'_, M>, mac: &ast::MacCall) { if let Some(last_segment) = mac.path.segments.last() && let name = last_segment.ident.as_str() && let Some(&braces) = self.macro_braces.0.get(name) @@ -74,7 +74,7 @@ impl EarlyLintPass for MacroBraces { } // See issue #9913 - fn check_stmt(&mut self, _: &EarlyContext<'_>, stmt: &ast::Stmt) { + fn check_stmt(&mut self, _: &EarlyContext<'_, M>, stmt: &ast::Stmt) { if let ast::StmtKind::MacCall(mac_callstmt) = &stmt.kind && let ast::MacCallStmt { style: ast::MacStmtStyle::Braces, @@ -85,8 +85,8 @@ impl EarlyLintPass for MacroBraces { } } - fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacroDef) { - fn check_ts(cx: &EarlyContext<'_>, ts: &TokenStream, macro_braces: &FxHashMap) { + fn check_mac_def(&mut self, cx: &EarlyContext<'_, M>, mac: &ast::MacroDef) { + fn check_ts(cx: &EarlyContext<'_, M>, ts: &TokenStream, macro_braces: &FxHashMap) { for (i, current_token) in ts.iter().enumerate() { if let TokenTree::Delimited(_, _, _, token_stream) = current_token { // Peel extra braces and parenthesis in macros! @@ -137,7 +137,7 @@ impl EarlyLintPass for MacroBraces { } } -fn emit_help(cx: &EarlyContext<'_>, snip: &str, (open, close): (char, char), span: Span, add_semi: bool) { +fn emit_help(cx: &EarlyContext<'_, M>, snip: &str, (open, close): (char, char), span: Span, add_semi: bool) { let semi = if add_semi { ";" } else { "" }; if let Some((macro_name, macro_args_str)) = snip.split_once('!') { let mut macro_args = macro_args_str.trim().to_string(); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 31b96bd4f9085..55fac83c20c46 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -133,12 +133,15 @@ pub const VEC_METHODS_SHADOWING_SLICE_METHODS: [Symbol; 3] = [sym::as_ptr, sym:: #[macro_export] macro_rules! extract_msrv_attr { () => { - fn check_attributes(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::ast::Attribute]) { + $crate::extract_msrv_attr!(rustc_lint::PostExpansion); + }; + ($mode:ty) => { + fn check_attributes(&mut self, cx: &rustc_lint::EarlyContext<'_, $mode>, attrs: &[rustc_ast::ast::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); self.msrv.check_attributes(attrs); } - fn check_attributes_post(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::ast::Attribute]) { + fn check_attributes_post(&mut self, cx: &rustc_lint::EarlyContext<'_, $mode>, attrs: &[rustc_ast::ast::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); self.msrv.check_attributes_post(attrs); } diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs index 69d679bba09b6..2999fd30c5d8d 100644 --- a/src/tools/clippy/clippy_utils/src/source.rs +++ b/src/tools/clippy/clippy_utils/src/source.rs @@ -43,10 +43,10 @@ impl<'sm> HasSourceMap<'sm> for TyCtxt<'sm> { self.sess.source_map() } } -impl<'sm> HasSourceMap<'sm> for &'sm EarlyContext<'_> { +impl<'sm, M: rustc_lint::EarlyLintMode> HasSourceMap<'sm> for &'sm EarlyContext<'_, M> { #[inline] fn source_map(self) -> &'sm SourceMap { - ::rustc_lint::LintContext::sess(self).source_map() + rustc_lint::LintContext::sess(self).source_map() } } impl<'sm> HasSourceMap<'sm> for &LateContext<'sm> { From 43986c49ce7e4a0faeb56850a9db6111f825c364 Mon Sep 17 00:00:00 2001 From: Edvin Bryntesson Date: Tue, 27 Oct 2026 17:47:07 +0100 Subject: [PATCH 2/4] deduplicate lint attr parsing related diagnostics --- .../unsafe/proc-unsafe-attributes.rs | 4 -- .../unsafe/proc-unsafe-attributes.stderr | 52 ++------------ ...deduplicate-diagnostics.deduplicate.stderr | 36 +++++++--- .../deduplicate-diagnostics.duplicate.stderr | 67 +++++++++++++------ .../deduplicate-diagnostics.rs | 10 ++- tests/ui/error-codes/E0452.rs | 2 - tests/ui/error-codes/E0452.stderr | 18 +---- tests/ui/fn/fn-trait-use-named-params.stderr | 28 ++++---- tests/ui/lint/empty-lint-attributes.rs | 4 -- tests/ui/lint/empty-lint-attributes.stderr | 44 ++---------- tests/ui/lint/lint-attribute-literals.rs | 2 - tests/ui/lint/lint-attribute-literals.stderr | 24 +------ tests/ui/lint/lint-malformed.rs | 2 - tests/ui/lint/lint-malformed.stderr | 18 +---- tests/ui/lint/register-tool-lint.rs | 2 - tests/ui/lint/register-tool-lint.stderr | 11 +-- .../lint-attribute-only-with-reason.rs | 5 -- .../lint-attribute-only-with-reason.stderr | 53 ++------------- tests/ui/lint/unused/empty-attributes.rs | 5 -- tests/ui/lint/unused/empty-attributes.stderr | 59 ++-------------- tests/ui/rust-2018/async-ident.stderr | 42 ++++++------ tests/ui/tool-attributes/cross-crate.rs | 1 - tests/ui/tool-attributes/cross-crate.stderr | 11 +-- tests/ui/tool-attributes/tool_lints.rs | 1 - tests/ui/tool-attributes/tool_lints.stderr | 11 +-- .../tool-attributes/unknown-lint-tool-name.rs | 2 - .../unknown-lint-tool-name.stderr | 24 +------ 27 files changed, 150 insertions(+), 388 deletions(-) diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs index 33324685a84f4..11bf36ccada06 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs @@ -23,17 +23,13 @@ pub fn d() {} #[unsafe(allow(dead_code))] //~^ ERROR: allow` is not an unsafe attribute //~| ERROR: `allow` is not an unsafe attribute -//~| ERROR: `allow` is not an unsafe attribute pub fn e() {} #[unsafe(allow(unsafe(dead_code)))] //~^ ERROR: allow` is not an unsafe attribute //~| ERROR: `allow` is not an unsafe attribute -//~| ERROR: `allow` is not an unsafe attribute //~| ERROR: expected identifier, found keyword `unsafe` //~| ERROR: expected identifier, found keyword `unsafe` -//~| ERROR: expected identifier, found keyword `unsafe` -//~| ERROR: malformed lint attribute input //~| ERROR: malformed lint attribute input //~| ERROR: malformed lint attribute input pub fn f() {} diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr index 04e8c4d2dd453..4f2d1261bf93f 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr @@ -1,36 +1,3 @@ -error: `allow` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:23:3 - | -LL | #[unsafe(allow(dead_code))] - | ^^^^^^ this is not an unsafe attribute - | - = note: extraneous unsafe is not allowed in attributes - -error: `allow` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:29:3 - | -LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^ this is not an unsafe attribute - | - = note: extraneous unsafe is not allowed in attributes - -error: expected identifier, found keyword `unsafe` - --> $DIR/proc-unsafe-attributes.rs:29:16 - | -LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^ expected identifier, found keyword - | -help: escape `unsafe` to use it as an identifier - | -LL | #[unsafe(allow(r#unsafe(dead_code)))] - | ++ - -error[E0452]: malformed lint attribute input - --> $DIR/proc-unsafe-attributes.rs:29:16 - | -LL | #[unsafe(allow(unsafe(dead_code)))] - | ^^^^^^^^^^^^^^^^^ bad attribute argument - error: the `proc_macro` attribute is only usable with crates of the `proc-macro` crate type --> $DIR/proc-unsafe-attributes.rs:1:10 | @@ -62,36 +29,31 @@ LL | #[unsafe(allow(dead_code))] | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `allow` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:29:3 + --> $DIR/proc-unsafe-attributes.rs:28:3 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected identifier, found keyword `unsafe` - --> $DIR/proc-unsafe-attributes.rs:29:16 + --> $DIR/proc-unsafe-attributes.rs:28:16 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^ expected identifier, found keyword | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: escape `unsafe` to use it as an identifier | LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ error[E0452]: malformed lint attribute input - --> $DIR/proc-unsafe-attributes.rs:29:16 + --> $DIR/proc-unsafe-attributes.rs:28:16 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^^^^^^^^^^^^ bad attribute argument - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `proc_macro` is not an unsafe attribute --> $DIR/proc-unsafe-attributes.rs:1:3 @@ -156,7 +118,7 @@ LL | #[unsafe(allow(dead_code))] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `allow` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:29:3 + --> $DIR/proc-unsafe-attributes.rs:28:3 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^ this is not an unsafe attribute @@ -165,7 +127,7 @@ LL | #[unsafe(allow(unsafe(dead_code)))] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected identifier, found keyword `unsafe` - --> $DIR/proc-unsafe-attributes.rs:29:16 + --> $DIR/proc-unsafe-attributes.rs:28:16 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^ expected identifier, found keyword @@ -177,14 +139,14 @@ LL | #[unsafe(allow(r#unsafe(dead_code)))] | ++ error[E0452]: malformed lint attribute input - --> $DIR/proc-unsafe-attributes.rs:29:16 + --> $DIR/proc-unsafe-attributes.rs:28:16 | LL | #[unsafe(allow(unsafe(dead_code)))] | ^^^^^^^^^^^^^^^^^ bad attribute argument | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 21 previous errors +error: aborting due to 17 previous errors Some errors have detailed explanations: E0452, E0565. For more information about an error, try `rustc --explain E0452`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr index 114c37188a9ef..3cc870c523602 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.deduplicate.stderr @@ -1,16 +1,34 @@ -error: expected a lint, found literal - --> $DIR/deduplicate-diagnostics.rs:10:8 - | -LL | #[deny("literal")] - | ^^^^^^^^^ not the name of a lint - | - = help: try using `#[deny(literal)]` - error: cannot find derive macro `Unresolved` in this scope --> $DIR/deduplicate-diagnostics.rs:6:10 | LL | #[derive(Unresolved)] | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: `allow` is not an unsafe attribute + --> $DIR/deduplicate-diagnostics.rs:10:3 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^ this is not an unsafe attribute + | + = note: extraneous unsafe is not allowed in attributes + +error: expected identifier, found keyword `unsafe` + --> $DIR/deduplicate-diagnostics.rs:10:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^ expected identifier, found keyword + | +help: escape `unsafe` to use it as an identifier + | +LL | #[unsafe(allow(r#unsafe(dead_code)))] + | ++ + +error[E0452]: malformed lint attribute input + --> $DIR/deduplicate-diagnostics.rs:10:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr index 66d0d94c0e815..9452970752efc 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.duplicate.stderr @@ -1,11 +1,3 @@ -error: expected a lint, found literal - --> $DIR/deduplicate-diagnostics.rs:10:8 - | -LL | #[deny("literal")] - | ^^^^^^^^^ not the name of a lint - | - = help: try using `#[deny(literal)]` - error: cannot find derive macro `Unresolved` in this scope --> $DIR/deduplicate-diagnostics.rs:6:10 | @@ -20,23 +12,60 @@ LL | #[derive(Unresolved)] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal - --> $DIR/deduplicate-diagnostics.rs:10:8 +error: `allow` is not an unsafe attribute + --> $DIR/deduplicate-diagnostics.rs:10:3 | -LL | #[deny("literal")] - | ^^^^^^^^^ not the name of a lint +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^ this is not an unsafe attribute + | + = note: extraneous unsafe is not allowed in attributes + +error: expected identifier, found keyword `unsafe` + --> $DIR/deduplicate-diagnostics.rs:10:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^ expected identifier, found keyword + | +help: escape `unsafe` to use it as an identifier + | +LL | #[unsafe(allow(r#unsafe(dead_code)))] + | ++ + +error[E0452]: malformed lint attribute input + --> $DIR/deduplicate-diagnostics.rs:10:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + +error: `allow` is not an unsafe attribute + --> $DIR/deduplicate-diagnostics.rs:10:3 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^ this is not an unsafe attribute + | + = note: extraneous unsafe is not allowed in attributes + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected identifier, found keyword `unsafe` + --> $DIR/deduplicate-diagnostics.rs:10:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^ expected identifier, found keyword | - = help: try using `#[deny(literal)]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: escape `unsafe` to use it as an identifier + | +LL | #[unsafe(allow(r#unsafe(dead_code)))] + | ++ -error: expected a lint, found literal - --> $DIR/deduplicate-diagnostics.rs:10:8 +error[E0452]: malformed lint attribute input + --> $DIR/deduplicate-diagnostics.rs:10:16 | -LL | #[deny("literal")] - | ^^^^^^^^^ not the name of a lint +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument | - = help: try using `#[deny(literal)]` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs b/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs index b070ec0f7dd93..63455d019baf9 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics.rs @@ -7,7 +7,11 @@ //[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope struct S; -#[deny("literal")] //~ ERROR expected a lint, found literal - //[duplicate]~| ERROR expected a lint, found literal - //[duplicate]~| ERROR expected a lint, found literal +#[unsafe(allow(unsafe(dead_code)))] +//~^ ERROR: allow` is not an unsafe attribute +//[duplicate]~| ERROR: `allow` is not an unsafe attribute +//~| ERROR: expected identifier, found keyword `unsafe` +//[duplicate]~| ERROR: expected identifier, found keyword `unsafe` +//~| ERROR: malformed lint attribute input +//[duplicate]~| ERROR: malformed lint attribute input fn main() {} diff --git a/tests/ui/error-codes/E0452.rs b/tests/ui/error-codes/E0452.rs index 4e5a6c9301467..5066cd99be9fa 100644 --- a/tests/ui/error-codes/E0452.rs +++ b/tests/ui/error-codes/E0452.rs @@ -2,7 +2,5 @@ //~| ERROR E0452 //~| ERROR E0452 //~| ERROR E0452 - //~| ERROR E0452 - //~| ERROR E0452 fn main() { } diff --git a/tests/ui/error-codes/E0452.stderr b/tests/ui/error-codes/E0452.stderr index c20429e363dda..986c135ed89cd 100644 --- a/tests/ui/error-codes/E0452.stderr +++ b/tests/ui/error-codes/E0452.stderr @@ -28,22 +28,6 @@ LL | #![allow(foo = "")] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input - --> $DIR/E0452.rs:1:10 - | -LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0452]: malformed lint attribute input - --> $DIR/E0452.rs:1:10 - | -LL | #![allow(foo = "")] - | ^^^^^^^^ bad attribute argument - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/fn/fn-trait-use-named-params.stderr b/tests/ui/fn/fn-trait-use-named-params.stderr index 6b22fa58c2ffc..7fb297bcd1746 100644 --- a/tests/ui/fn/fn-trait-use-named-params.stderr +++ b/tests/ui/fn/fn-trait-use-named-params.stderr @@ -1,17 +1,3 @@ -error: `gen` is a keyword in the 2024 edition - --> $DIR/fn-trait-use-named-params.rs:14:49 - | -LL | fn f6(_: impl Fn(#[forbid(keyword_idents_2024)] gen: u8)) {} - | ^^^ help: you can use a raw identifier to stay compatible: `r#gen` - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! - = note: for more information, see -note: the lint level is defined here - --> $DIR/fn-trait-use-named-params.rs:14:27 - | -LL | fn f6(_: impl Fn(#[forbid(keyword_idents_2024)] gen: u8)) {} - | ^^^^^^^^^^^^^^^^^^^ - error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters --> $DIR/fn-trait-use-named-params.rs:4:18 | @@ -30,6 +16,20 @@ error: documentation comments cannot be applied to function parameters LL | fn f4(_: impl Fn(/** */ x: u8)) {} | ^^^^^^ doc comments are not allowed here +error: `gen` is a keyword in the 2024 edition + --> $DIR/fn-trait-use-named-params.rs:14:49 + | +LL | fn f6(_: impl Fn(#[forbid(keyword_idents_2024)] gen: u8)) {} + | ^^^ help: you can use a raw identifier to stay compatible: `r#gen` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see +note: the lint level is defined here + --> $DIR/fn-trait-use-named-params.rs:14:27 + | +LL | fn f6(_: impl Fn(#[forbid(keyword_idents_2024)] gen: u8)) {} + | ^^^^^^^^^^^^^^^^^^^ + error: the `inline` attribute cannot be used on function params --> $DIR/fn-trait-use-named-params.rs:4:20 | diff --git a/tests/ui/lint/empty-lint-attributes.rs b/tests/ui/lint/empty-lint-attributes.rs index 9406925444b74..732c37204c32a 100644 --- a/tests/ui/lint/empty-lint-attributes.rs +++ b/tests/ui/lint/empty-lint-attributes.rs @@ -5,19 +5,15 @@ #![allow()] //~^ WARN unused attribute -//~| WARN unused attribute #![warn(reason = "observationalism")] //~^ WARN unused attribute -//~| WARN unused attribute #[forbid()] //~^ WARN unused attribute -//~| WARN unused attribute fn devoir() {} #[deny(reason = "ultion")] //~^ WARN unused attribute -//~| WARN unused attribute fn waldgrave() {} fn main() {} diff --git a/tests/ui/lint/empty-lint-attributes.stderr b/tests/ui/lint/empty-lint-attributes.stderr index 0c9b9771d007a..431cc98f590a6 100644 --- a/tests/ui/lint/empty-lint-attributes.stderr +++ b/tests/ui/lint/empty-lint-attributes.stderr @@ -8,7 +8,7 @@ LL | #![allow()] = note: requested on the command line with `-W unused-attributes` warning: unused attribute - --> $DIR/empty-lint-attributes.rs:9:1 + --> $DIR/empty-lint-attributes.rs:8:1 | LL | #![warn(reason = "observationalism")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute @@ -16,7 +16,7 @@ LL | #![warn(reason = "observationalism")] = note: attribute `warn` without any lints has no effect warning: unused attribute - --> $DIR/empty-lint-attributes.rs:13:1 + --> $DIR/empty-lint-attributes.rs:11:1 | LL | #[forbid()] | ^^^^^^^^^^^ help: remove this attribute @@ -24,48 +24,12 @@ LL | #[forbid()] = note: attribute `forbid` with an empty list has no effect warning: unused attribute - --> $DIR/empty-lint-attributes.rs:18:1 + --> $DIR/empty-lint-attributes.rs:15:1 | LL | #[deny(reason = "ultion")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | = note: attribute `deny` without any lints has no effect -warning: unused attribute - --> $DIR/empty-lint-attributes.rs:6:1 - | -LL | #![allow()] - | ^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `allow` with an empty list has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unused attribute - --> $DIR/empty-lint-attributes.rs:9:1 - | -LL | #![warn(reason = "observationalism")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `warn` without any lints has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unused attribute - --> $DIR/empty-lint-attributes.rs:13:1 - | -LL | #[forbid()] - | ^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `forbid` with an empty list has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unused attribute - --> $DIR/empty-lint-attributes.rs:18:1 - | -LL | #[deny(reason = "ultion")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `deny` without any lints has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 8 warnings emitted +warning: 4 warnings emitted diff --git a/tests/ui/lint/lint-attribute-literals.rs b/tests/ui/lint/lint-attribute-literals.rs index 34a4757adec3c..6aa100067b47d 100644 --- a/tests/ui/lint/lint-attribute-literals.rs +++ b/tests/ui/lint/lint-attribute-literals.rs @@ -3,9 +3,7 @@ #[allow("literal")] //~^ ERROR expected a lint, found literal //~| ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal #[deny(1.0)] //~^ ERROR expected a lint, found literal //~| ERROR expected a lint, found literal -//~| ERROR expected a lint, found literal fn main() {} diff --git a/tests/ui/lint/lint-attribute-literals.stderr b/tests/ui/lint/lint-attribute-literals.stderr index 7434f8b5c5d4b..d56fe7d8f20a0 100644 --- a/tests/ui/lint/lint-attribute-literals.stderr +++ b/tests/ui/lint/lint-attribute-literals.stderr @@ -7,7 +7,7 @@ LL | #[allow("literal")] = help: try using `#[allow(literal)]` error: expected a lint, found literal - --> $DIR/lint-attribute-literals.rs:7:8 + --> $DIR/lint-attribute-literals.rs:6:8 | LL | #[deny(1.0)] | ^^^ not the name of a lint @@ -24,7 +24,7 @@ LL | #[allow("literal")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected a lint, found literal - --> $DIR/lint-attribute-literals.rs:7:8 + --> $DIR/lint-attribute-literals.rs:6:8 | LL | #[deny(1.0)] | ^^^ not the name of a lint @@ -32,23 +32,5 @@ LL | #[deny(1.0)] = help: for example, write `#[deny(dead_code)]` for `dead_code` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: expected a lint, found literal - --> $DIR/lint-attribute-literals.rs:3:9 - | -LL | #[allow("literal")] - | ^^^^^^^^^ not the name of a lint - | - = help: try using `#[allow(literal)]` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: expected a lint, found literal - --> $DIR/lint-attribute-literals.rs:7:8 - | -LL | #[deny(1.0)] - | ^^^ not the name of a lint - | - = help: for example, write `#[deny(dead_code)]` for `dead_code` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/lint/lint-malformed.rs b/tests/ui/lint/lint-malformed.rs index cf5570753d85d..188e702f98b38 100644 --- a/tests/ui/lint/lint-malformed.rs +++ b/tests/ui/lint/lint-malformed.rs @@ -3,6 +3,4 @@ //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute - //~| ERROR malformed lint attribute fn main() { } diff --git a/tests/ui/lint/lint-malformed.stderr b/tests/ui/lint/lint-malformed.stderr index 7be928de86985..2d3da728484bc 100644 --- a/tests/ui/lint/lint-malformed.stderr +++ b/tests/ui/lint/lint-malformed.stderr @@ -12,22 +12,6 @@ LL | #![allow(bar = "baz")] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0452]: malformed lint attribute input - --> $DIR/lint-malformed.rs:2:10 - | -LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0452]: malformed lint attribute input - --> $DIR/lint-malformed.rs:2:10 - | -LL | #![allow(bar = "baz")] - | ^^^^^^^^^^^ bad attribute argument - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0539]: malformed `deny` attribute input --> $DIR/lint-malformed.rs:1:4 | @@ -65,7 +49,7 @@ LL | #![allow(bar = "baz")] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0452, E0539. For more information about an error, try `rustc --explain E0452`. diff --git a/tests/ui/lint/register-tool-lint.rs b/tests/ui/lint/register-tool-lint.rs index 17d3afbf6e26e..f56d9a0a8c362 100644 --- a/tests/ui/lint/register-tool-lint.rs +++ b/tests/ui/lint/register-tool-lint.rs @@ -5,5 +5,3 @@ #![warn(abc::my_lint)] //~^ ERROR unknown tool name `abc` found in scoped lint //~| HELP add `#![register_tool(abc)]` -//~| ERROR unknown tool name `abc` -//~| HELP add `#![register_tool(abc)]` diff --git a/tests/ui/lint/register-tool-lint.stderr b/tests/ui/lint/register-tool-lint.stderr index 7ebdbdec92972..98b4af935d340 100644 --- a/tests/ui/lint/register-tool-lint.stderr +++ b/tests/ui/lint/register-tool-lint.stderr @@ -6,15 +6,6 @@ LL | #![warn(abc::my_lint)] | = help: add `#![register_tool(abc)]` to the crate root -error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint` - --> $DIR/register-tool-lint.rs:5:9 - | -LL | #![warn(abc::my_lint)] - | ^^^ - | - = help: add `#![register_tool(abc)]` to the crate root - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0710`. diff --git a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs index 2d14bcda47ee0..ebca70d9e57b3 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs @@ -2,19 +2,14 @@ #[allow(reason = "I want to allow something")] //~^ ERROR unused attribute -//~| ERROR unused attribute #[expect(reason = "I don't know what I'm waiting for")] //~^ ERROR unused attribute -//~| ERROR unused attribute #[warn(reason = "This should be warn by default")] //~^ ERROR unused attribute -//~| ERROR unused attribute #[deny(reason = "All listed lints are denied")] //~^ ERROR unused attribute -//~| ERROR unused attribute #[forbid(reason = "Just some reason")] //~^ ERROR unused attribute -//~| ERROR unused attribute #[allow(clippy::box_collection, reason = "This is still valid")] #[warn(dead_code, reason = "This is also reasonable")] diff --git a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr index b19514804e44f..df47c91b1edc7 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr @@ -12,7 +12,7 @@ LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:6:1 + --> $DIR/lint-attribute-only-with-reason.rs:5:1 | LL | #[expect(reason = "I don't know what I'm waiting for")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute @@ -20,73 +20,28 @@ LL | #[expect(reason = "I don't know what I'm waiting for")] = note: attribute `expect` without any lints has no effect error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:9:1 + --> $DIR/lint-attribute-only-with-reason.rs:7:1 | LL | #[warn(reason = "This should be warn by default")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | = note: attribute `warn` without any lints has no effect -error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:12:1 - | -LL | #[deny(reason = "All listed lints are denied")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `deny` without any lints has no effect - -error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:15:1 - | -LL | #[forbid(reason = "Just some reason")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `forbid` without any lints has no effect - -error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:3:1 - | -LL | #[allow(reason = "I want to allow something")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `allow` without any lints has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:6:1 - | -LL | #[expect(reason = "I don't know what I'm waiting for")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `expect` without any lints has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error: unused attribute --> $DIR/lint-attribute-only-with-reason.rs:9:1 | -LL | #[warn(reason = "This should be warn by default")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `warn` without any lints has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:12:1 - | LL | #[deny(reason = "All listed lints are denied")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | = note: attribute `deny` without any lints has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:15:1 + --> $DIR/lint-attribute-only-with-reason.rs:11:1 | LL | #[forbid(reason = "Just some reason")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | = note: attribute `forbid` without any lints has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 10 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/lint/unused/empty-attributes.rs b/tests/ui/lint/unused/empty-attributes.rs index c60d19680bf1b..61f43c951895a 100644 --- a/tests/ui/lint/unused/empty-attributes.rs +++ b/tests/ui/lint/unused/empty-attributes.rs @@ -1,19 +1,14 @@ #![deny(unused_attributes)] #![allow()] //~^ ERROR unused attribute -//~| ERROR unused attribute #![expect()] //~^ ERROR unused attribute -//~| ERROR unused attribute #![warn()] //~^ ERROR unused attribute -//~| ERROR unused attribute #![deny()] //~^ ERROR unused attribute -//~| ERROR unused attribute #![forbid()] //~^ ERROR unused attribute -//~| ERROR unused attribute #![feature()] //~ ERROR unused attribute #[repr()] //~ ERROR unused attribute diff --git a/tests/ui/lint/unused/empty-attributes.stderr b/tests/ui/lint/unused/empty-attributes.stderr index 8414b21cd4906..5486f2408c4bb 100644 --- a/tests/ui/lint/unused/empty-attributes.stderr +++ b/tests/ui/lint/unused/empty-attributes.stderr @@ -12,7 +12,7 @@ LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/empty-attributes.rs:5:1 + --> $DIR/empty-attributes.rs:4:1 | LL | #![expect()] | ^^^^^^^^^^^^ help: remove this attribute @@ -20,76 +20,31 @@ LL | #![expect()] = note: attribute `expect` with an empty list has no effect error: unused attribute - --> $DIR/empty-attributes.rs:8:1 + --> $DIR/empty-attributes.rs:6:1 | LL | #![warn()] | ^^^^^^^^^^ help: remove this attribute | = note: attribute `warn` with an empty list has no effect -error: unused attribute - --> $DIR/empty-attributes.rs:11:1 - | -LL | #![deny()] - | ^^^^^^^^^^ help: remove this attribute - | - = note: attribute `deny` with an empty list has no effect - -error: unused attribute - --> $DIR/empty-attributes.rs:14:1 - | -LL | #![forbid()] - | ^^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `forbid` with an empty list has no effect - -error: unused attribute - --> $DIR/empty-attributes.rs:2:1 - | -LL | #![allow()] - | ^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `allow` with an empty list has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: unused attribute - --> $DIR/empty-attributes.rs:5:1 - | -LL | #![expect()] - | ^^^^^^^^^^^^ help: remove this attribute - | - = note: attribute `expect` with an empty list has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error: unused attribute --> $DIR/empty-attributes.rs:8:1 | -LL | #![warn()] - | ^^^^^^^^^^ help: remove this attribute - | - = note: attribute `warn` with an empty list has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: unused attribute - --> $DIR/empty-attributes.rs:11:1 - | LL | #![deny()] | ^^^^^^^^^^ help: remove this attribute | = note: attribute `deny` with an empty list has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused attribute - --> $DIR/empty-attributes.rs:14:1 + --> $DIR/empty-attributes.rs:10:1 | LL | #![forbid()] | ^^^^^^^^^^^^ help: remove this attribute | = note: attribute `forbid` with an empty list has no effect - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused attribute - --> $DIR/empty-attributes.rs:17:1 + --> $DIR/empty-attributes.rs:12:1 | LL | #![feature()] | ^^^^^^^^^^^^^ help: remove this attribute @@ -97,7 +52,7 @@ LL | #![feature()] = note: using `feature` with an empty list has no effect error: unused attribute - --> $DIR/empty-attributes.rs:19:1 + --> $DIR/empty-attributes.rs:14:1 | LL | #[repr()] | ^^^^^^^^^ help: remove this attribute @@ -105,12 +60,12 @@ LL | #[repr()] = note: using `repr` with an empty list has no effect error: unused attribute - --> $DIR/empty-attributes.rs:22:1 + --> $DIR/empty-attributes.rs:17:1 | LL | #[target_feature()] | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute | = note: using `target_feature` with an empty list has no effect -error: aborting due to 13 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/rust-2018/async-ident.stderr b/tests/ui/rust-2018/async-ident.stderr index c9a5e29ef95ea..87725a6a29446 100644 --- a/tests/ui/rust-2018/async-ident.stderr +++ b/tests/ui/rust-2018/async-ident.stderr @@ -1,8 +1,8 @@ error: `async` is a keyword in the 2018 edition - --> $DIR/async-ident.rs:9:4 + --> $DIR/async-ident.rs:69:19 | -LL | fn async() {} - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` +LL | () => (pub fn async() {}) + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see @@ -13,6 +13,24 @@ LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]` +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:76:6 + | +LL | (async) => (1) + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:9:4 + | +LL | fn async() {} + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see + error: `async` is a keyword in the 2018 edition --> $DIR/async-ident.rs:14:19 | @@ -112,23 +130,5 @@ LL | let async: async = async {}; = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see -error: `async` is a keyword in the 2018 edition - --> $DIR/async-ident.rs:69:19 - | -LL | () => (pub fn async() {}) - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! - = note: for more information, see - -error: `async` is a keyword in the 2018 edition - --> $DIR/async-ident.rs:76:6 - | -LL | (async) => (1) - | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! - = note: for more information, see - error: aborting due to 14 previous errors diff --git a/tests/ui/tool-attributes/cross-crate.rs b/tests/ui/tool-attributes/cross-crate.rs index 1992174aca3e1..184582664aff8 100644 --- a/tests/ui/tool-attributes/cross-crate.rs +++ b/tests/ui/tool-attributes/cross-crate.rs @@ -6,5 +6,4 @@ extern crate use_tool; #[foo::bar] //~ ERROR cannot find module or crate `foo` in this scope #[allow(foo::baz)] //~ ERROR unknown tool name `foo` //~| ERROR unknown tool name `foo` - //~| ERROR unknown tool name `foo` fn main() {} diff --git a/tests/ui/tool-attributes/cross-crate.stderr b/tests/ui/tool-attributes/cross-crate.stderr index 051a1b05405e9..38ea406702ab3 100644 --- a/tests/ui/tool-attributes/cross-crate.stderr +++ b/tests/ui/tool-attributes/cross-crate.stderr @@ -1,11 +1,3 @@ -error[E0710]: unknown tool name `foo` found in scoped lint: `foo::baz` - --> $DIR/cross-crate.rs:7:9 - | -LL | #[allow(foo::baz)] - | ^^^ - | - = help: add `#![register_tool(foo)]` to the crate root - error[E0433]: cannot find module or crate `foo` in this scope --> $DIR/cross-crate.rs:6:3 | @@ -19,7 +11,6 @@ LL | #[allow(foo::baz)] | ^^^ | = help: add `#![register_tool(foo)]` to the crate root - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0710]: unknown tool name `foo` found in scoped lint: `foo::baz` --> $DIR/cross-crate.rs:7:9 @@ -30,7 +21,7 @@ LL | #[allow(foo::baz)] = help: add `#![register_tool(foo)]` to the crate root = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0433, E0710. For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/tool-attributes/tool_lints.rs b/tests/ui/tool-attributes/tool_lints.rs index 9e4aa7a939acb..ef27532f6de1f 100644 --- a/tests/ui/tool-attributes/tool_lints.rs +++ b/tests/ui/tool-attributes/tool_lints.rs @@ -1,5 +1,4 @@ #[warn(foo::bar)] //~^ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` -//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` fn main() {} diff --git a/tests/ui/tool-attributes/tool_lints.stderr b/tests/ui/tool-attributes/tool_lints.stderr index eee0a9784ece8..f1d825caba159 100644 --- a/tests/ui/tool-attributes/tool_lints.stderr +++ b/tests/ui/tool-attributes/tool_lints.stderr @@ -15,15 +15,6 @@ LL | #[warn(foo::bar)] = help: add `#![register_tool(foo)]` to the crate root = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` - --> $DIR/tool_lints.rs:1:8 - | -LL | #[warn(foo::bar)] - | ^^^ - | - = help: add `#![register_tool(foo)]` to the crate root - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0710`. diff --git a/tests/ui/tool-attributes/unknown-lint-tool-name.rs b/tests/ui/tool-attributes/unknown-lint-tool-name.rs index 84ab7c1944ab2..cd5d2f028af02 100644 --- a/tests/ui/tool-attributes/unknown-lint-tool-name.rs +++ b/tests/ui/tool-attributes/unknown-lint-tool-name.rs @@ -1,8 +1,6 @@ #![deny(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` - //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` #[allow(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` - //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` fn main() {} diff --git a/tests/ui/tool-attributes/unknown-lint-tool-name.stderr b/tests/ui/tool-attributes/unknown-lint-tool-name.stderr index 91baf88273756..72731ab1e3db4 100644 --- a/tests/ui/tool-attributes/unknown-lint-tool-name.stderr +++ b/tests/ui/tool-attributes/unknown-lint-tool-name.stderr @@ -7,7 +7,7 @@ LL | #![deny(foo::bar)] = help: add `#![register_tool(foo)]` to the crate root error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` - --> $DIR/unknown-lint-tool-name.rs:5:9 + --> $DIR/unknown-lint-tool-name.rs:4:9 | LL | #[allow(foo::bar)] | ^^^ @@ -24,7 +24,7 @@ LL | #![deny(foo::bar)] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` - --> $DIR/unknown-lint-tool-name.rs:5:9 + --> $DIR/unknown-lint-tool-name.rs:4:9 | LL | #[allow(foo::bar)] | ^^^ @@ -32,24 +32,6 @@ LL | #[allow(foo::bar)] = help: add `#![register_tool(foo)]` to the crate root = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` - --> $DIR/unknown-lint-tool-name.rs:1:9 - | -LL | #![deny(foo::bar)] - | ^^^ - | - = help: add `#![register_tool(foo)]` to the crate root - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` - --> $DIR/unknown-lint-tool-name.rs:5:9 - | -LL | #[allow(foo::bar)] - | ^^^ - | - = help: add `#![register_tool(foo)]` to the crate root - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0710`. From 12820515e3c8e9f56cd4cd3cb3accb8bbae3febd Mon Sep 17 00:00:00 2001 From: Edvin Bryntesson Date: Tue, 27 Oct 2026 17:47:34 +0100 Subject: [PATCH 3/4] update test for keyword_idents affecting submodules --- tests/ui/lint/keyword-idents/multi-file.rs | 18 ++++--- .../ui/lint/keyword-idents/multi-file.stderr | 54 +++++++++++++++++++ 2 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 tests/ui/lint/keyword-idents/multi-file.stderr diff --git a/tests/ui/lint/keyword-idents/multi-file.rs b/tests/ui/lint/keyword-idents/multi-file.rs index 703e13f9ef6b7..c5d733287ded2 100644 --- a/tests/ui/lint/keyword-idents/multi-file.rs +++ b/tests/ui/lint/keyword-idents/multi-file.rs @@ -1,12 +1,16 @@ -#![deny(keyword_idents)] // Should affect the submodule, but doesn't. +#![deny(keyword_idents)] // Should affect the submodule //@ edition: 2015 -//@ known-bug: #132218 -//@ check-pass (known bug; should be check-fail) +//~? ERROR: `async` is a keyword in the 2018 edition +//~? WARN this is accepted in the current edition +//~? ERROR: `await` is a keyword in the 2018 edition +//~? WARN this is accepted in the current edition +//~? ERROR: `dyn` is a keyword in the 2018 edition +//~? WARN this is accepted in the current edition +//~? ERROR: `try` is a keyword in the 2018 edition +//~? WARN this is accepted in the current edition +//~? ERROR: `gen` is a keyword in the 2024 edition +//~? WARN this is accepted in the current edition -// Because `keyword_idents_2018` and `keyword_idents_2024` are pre-expansion -// lints, configuring them via lint attributes doesn't propagate to submodules -// in other files. -// #[path = "./auxiliary/multi_file_submod.rs"] mod multi_file_submod; diff --git a/tests/ui/lint/keyword-idents/multi-file.stderr b/tests/ui/lint/keyword-idents/multi-file.stderr new file mode 100644 index 0000000000000..e46c3f989102a --- /dev/null +++ b/tests/ui/lint/keyword-idents/multi-file.stderr @@ -0,0 +1,54 @@ +error: `async` is a keyword in the 2018 edition + --> $DIR/./auxiliary/multi_file_submod.rs:4:4 + | +LL | fn async() {} + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see +note: the lint level is defined here + --> $DIR/multi-file.rs:1:9 + | +LL | #![deny(keyword_idents)] // Should affect the submodule + | ^^^^^^^^^^^^^^ + = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]` + +error: `await` is a keyword in the 2018 edition + --> $DIR/./auxiliary/multi_file_submod.rs:5:4 + | +LL | fn await() {} + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see + +error: `try` is a keyword in the 2018 edition + --> $DIR/./auxiliary/multi_file_submod.rs:6:4 + | +LL | fn try() {} + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/./auxiliary/multi_file_submod.rs:7:4 + | +LL | fn dyn() {} + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see + +error: `gen` is a keyword in the 2024 edition + --> $DIR/./auxiliary/multi_file_submod.rs:10:4 + | +LL | fn gen() {} + | ^^^ help: you can use a raw identifier to stay compatible: `r#gen` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see + = note: `#[deny(keyword_idents_2024)]` implied by `#[deny(keyword_idents)]` + +error: aborting due to 5 previous errors + From 4a035f92b78eef22eef813e2f1a3897add7f1c90 Mon Sep 17 00:00:00 2001 From: Edvin Bryntesson Date: Tue, 27 Oct 2026 17:48:18 +0100 Subject: [PATCH 4/4] fix pre-expansion-parsing test --- tests/ui/lint/pre-expansion-parsing.rs | 4 +++- tests/ui/lint/pre-expansion-parsing.stderr | 9 --------- 2 files changed, 3 insertions(+), 10 deletions(-) delete mode 100644 tests/ui/lint/pre-expansion-parsing.stderr diff --git a/tests/ui/lint/pre-expansion-parsing.rs b/tests/ui/lint/pre-expansion-parsing.rs index 7cfc57ff4e903..b495626d54faa 100644 --- a/tests/ui/lint/pre-expansion-parsing.rs +++ b/tests/ui/lint/pre-expansion-parsing.rs @@ -1,9 +1,11 @@ #![crate_type = "lib"] +//@ check-pass + #[expect] // OK #[expect[wut]] // OK #[expect(expect)] // OK -#[expect(expect(expect))] //~ ERROR malformed lint attribute input +#[expect(expect(expect))] // OK #[deny(({!}))] // OK #[expect[helix::]] // OK #[cfg(false)] diff --git a/tests/ui/lint/pre-expansion-parsing.stderr b/tests/ui/lint/pre-expansion-parsing.stderr deleted file mode 100644 index ecc8b7017d92d..0000000000000 --- a/tests/ui/lint/pre-expansion-parsing.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0452]: malformed lint attribute input - --> $DIR/pre-expansion-parsing.rs:6:10 - | -LL | #[expect(expect(expect))] - | ^^^^^^^^^^^^^^ bad attribute argument - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0452`.