From 45bea6c327a782d35ef87b6ef791df5f946decfd Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Thu, 5 Nov 2026 20:22:19 +0600 Subject: [PATCH 1/2] add tests for -Zcrate-attr ordering rfc 3791 says crate attributes from the command line apply before the attributes in the crate root. ordering-cli checks that several -Zcrate-attr flags apply in command line order. ordering-source records the current behaviour where the command line deny overrides the source warn, which is the wrong way round. --- tests/ui/attributes/z-crate-attr/ordering-cli.rs | 6 ++++++ .../attributes/z-crate-attr/ordering-cli.stderr | 15 +++++++++++++++ .../ui/attributes/z-crate-attr/ordering-source.rs | 8 ++++++++ .../z-crate-attr/ordering-source.stderr | 15 +++++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 tests/ui/attributes/z-crate-attr/ordering-cli.rs create mode 100644 tests/ui/attributes/z-crate-attr/ordering-cli.stderr create mode 100644 tests/ui/attributes/z-crate-attr/ordering-source.rs create mode 100644 tests/ui/attributes/z-crate-attr/ordering-source.stderr diff --git a/tests/ui/attributes/z-crate-attr/ordering-cli.rs b/tests/ui/attributes/z-crate-attr/ordering-cli.rs new file mode 100644 index 0000000000000..877a25939b9f3 --- /dev/null +++ b/tests/ui/attributes/z-crate-attr/ordering-cli.rs @@ -0,0 +1,6 @@ +// Multiple `-Zcrate-attr` flags apply in command-line order, so the later `deny` wins. +//@ compile-flags: -Zcrate-attr=warn(unused) -Zcrate-attr=deny(unused) + +fn foo() {} //~ ERROR function `foo` is never used + +fn main() {} diff --git a/tests/ui/attributes/z-crate-attr/ordering-cli.stderr b/tests/ui/attributes/z-crate-attr/ordering-cli.stderr new file mode 100644 index 0000000000000..84c47716e62fb --- /dev/null +++ b/tests/ui/attributes/z-crate-attr/ordering-cli.stderr @@ -0,0 +1,15 @@ +error: function `foo` is never used + --> $DIR/ordering-cli.rs:4:4 + | +LL | fn foo() {} + | ^^^ + | +note: the lint level is defined here + --> :1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/attributes/z-crate-attr/ordering-source.rs b/tests/ui/attributes/z-crate-attr/ordering-source.rs new file mode 100644 index 0000000000000..d4a248a6be5ca --- /dev/null +++ b/tests/ui/attributes/z-crate-attr/ordering-source.rs @@ -0,0 +1,8 @@ +// RFC 3791: `-Zcrate-attr` applies before the crate's own attributes, so `warn` here wins. +//@ compile-flags: -Zcrate-attr=deny(unused) + +#![warn(unused)] + +fn foo() {} //~ ERROR function `foo` is never used + +fn main() {} diff --git a/tests/ui/attributes/z-crate-attr/ordering-source.stderr b/tests/ui/attributes/z-crate-attr/ordering-source.stderr new file mode 100644 index 0000000000000..75af32fc695cd --- /dev/null +++ b/tests/ui/attributes/z-crate-attr/ordering-source.stderr @@ -0,0 +1,15 @@ +error: function `foo` is never used + --> $DIR/ordering-source.rs:6:4 + | +LL | fn foo() {} + | ^^^ + | +note: the lint level is defined here + --> :1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to 1 previous error + From 851c9e042bf06381d712e4d79fe6fac826b1d8d3 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Thu, 5 Nov 2026 07:52:35 +0600 Subject: [PATCH 2/2] apply -Zcrate-attr attributes before the crate attributes cmdline attributes were pushed after the attributes parsed from source, so a -Zcrate-attr lint level overrode the same lint set in the crate root. rfc 3791 says they apply before the source attributes. they are now inserted at the front of the crate attributes in command line order. --- .../rustc_builtin_macros/src/cmdline_attrs.rs | 15 +++++++-------- .../ui/attributes/z-crate-attr/ordering-source.rs | 3 ++- .../z-crate-attr/ordering-source.stderr | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs index b294328b0bb17..b0045c359160d 100644 --- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs +++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs @@ -8,7 +8,7 @@ use rustc_session::parse::ParseSess; use rustc_span::FileName; pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) { - for raw_attr in attrs { + let injected = attrs.iter().filter_map(|raw_attr| { let source = format!("#![{raw_attr}]"); let parse = || -> Result>> { let tokens = source_str_to_stream( @@ -22,16 +22,15 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) { }) .map_err(|e| vec![e]) }; - let meta = match parse() { - Ok(meta) => meta, + match parse() { + Ok(meta) => Some(meta), Err(errs) => { for err in errs { err.emit(); } - continue; + None } - }; - - krate.attrs.push(meta); - } + } + }); + krate.attrs.splice(0..0, injected); } diff --git a/tests/ui/attributes/z-crate-attr/ordering-source.rs b/tests/ui/attributes/z-crate-attr/ordering-source.rs index d4a248a6be5ca..914851d3bb055 100644 --- a/tests/ui/attributes/z-crate-attr/ordering-source.rs +++ b/tests/ui/attributes/z-crate-attr/ordering-source.rs @@ -1,8 +1,9 @@ // RFC 3791: `-Zcrate-attr` applies before the crate's own attributes, so `warn` here wins. +//@ check-pass //@ compile-flags: -Zcrate-attr=deny(unused) #![warn(unused)] -fn foo() {} //~ ERROR function `foo` is never used +fn foo() {} //~ WARN function `foo` is never used fn main() {} diff --git a/tests/ui/attributes/z-crate-attr/ordering-source.stderr b/tests/ui/attributes/z-crate-attr/ordering-source.stderr index 75af32fc695cd..66cf78738bf7c 100644 --- a/tests/ui/attributes/z-crate-attr/ordering-source.stderr +++ b/tests/ui/attributes/z-crate-attr/ordering-source.stderr @@ -1,15 +1,15 @@ -error: function `foo` is never used - --> $DIR/ordering-source.rs:6:4 +warning: function `foo` is never used + --> $DIR/ordering-source.rs:7:4 | LL | fn foo() {} | ^^^ | note: the lint level is defined here - --> :1:9 + --> $DIR/ordering-source.rs:5:9 | -LL | #![deny(unused)] +LL | #![warn(unused)] | ^^^^^^ - = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` -error: aborting due to 1 previous error +warning: 1 warning emitted