From b507c75d037a834d592e02d0f354dae008788331 Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:11:22 -0400 Subject: [PATCH 01/13] add regression test --- .../auxiliary/cross_crate_generic_typedef.rs | 6 ++++- .../typedef-inner-variants-document-hidden.rs | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-html/typedef-inner-variants-document-hidden.rs diff --git a/tests/rustdoc-html/auxiliary/cross_crate_generic_typedef.rs b/tests/rustdoc-html/auxiliary/cross_crate_generic_typedef.rs index d85129a69fc6e..f102e682877f2 100644 --- a/tests/rustdoc-html/auxiliary/cross_crate_generic_typedef.rs +++ b/tests/rustdoc-html/auxiliary/cross_crate_generic_typedef.rs @@ -1,5 +1,7 @@ pub struct InlineOne { - pub inline: A + pub inline: A, + #[doc(hidden)] + pub hidden: A, } pub type InlineU64 = InlineOne; @@ -7,4 +9,6 @@ pub type InlineU64 = InlineOne; pub enum GenericEnum { Variant(T), Variant2(T, T), + #[doc(hidden)] + Hidden(T), } diff --git a/tests/rustdoc-html/typedef-inner-variants-document-hidden.rs b/tests/rustdoc-html/typedef-inner-variants-document-hidden.rs new file mode 100644 index 0000000000000..9e7e4273c248a --- /dev/null +++ b/tests/rustdoc-html/typedef-inner-variants-document-hidden.rs @@ -0,0 +1,26 @@ +// Regression test for . + +//@ compile-flags: -Z unstable-options --document-hidden-items +//@ aux-build:cross_crate_generic_typedef.rs + +#![crate_name = "document_hidden_aliased_items"] + +extern crate cross_crate_generic_typedef; + +use std::collections::BTreeMap; + +//@ has 'document_hidden_aliased_items/type.InlineU64.html' +//@ count - '//*[@class="structfield section-header"]' 2 +//@ has - '//pre[@class="rust item-decl"]//code' 'pub hidden' +//@ count - '//pre[@class="rust item-decl"]//code' '/* private fields */' 0 +pub type InlineU64 = cross_crate_generic_typedef::InlineOne; + +//@ has 'document_hidden_aliased_items/type.InlineEnum.html' +//@ count - '//*[@class="variant"]' 3 +//@ has - '//pre[@class="rust item-decl"]//code' 'Hidden' +//@ count - '//pre[@class="rust item-decl"]//code' '// some variants omitted' 0 +pub type InlineEnum = cross_crate_generic_typedef::GenericEnum; + +//@ has 'document_hidden_aliased_items/type.PrivateFields.html' +//@ has - '//*[@class="rust item-decl"]/code' 'struct PrivateFields { /* private fields */ }' +pub type PrivateFields = BTreeMap; From 900b2e720fb5bd6f099a3abb3a2c6c56fb8b1b82 Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:15:21 -0400 Subject: [PATCH 02/13] don't strip hidden items in `AliasedNonLocalStripper` --- src/librustdoc/passes/strip_aliased_non_local.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index bb13308e6c2a9..18865f90e9031 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -47,9 +47,8 @@ impl DocFolder for NonLocalStripper<'_> { // FIXME(#125009): Not-local should probably consider same Cargo workspace if let Some(def_id) = i.def_id() && !def_id.is_local() - && (i.is_doc_hidden() - // Default to *not* stripping items with inherited visibility. - || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public)) + // Default to *not* stripping items with inherited visibility. + && i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public) { return Some(strip_item(i)); } From edad2648fa121ea67ecd4ad2a56101e540aa3b5e Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Sat, 13 Jun 2026 07:26:22 -0400 Subject: [PATCH 03/13] test without --document-hidden-items --- tests/rustdoc-html/typedef-inner-variants.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/rustdoc-html/typedef-inner-variants.rs b/tests/rustdoc-html/typedef-inner-variants.rs index 51644546c01eb..02f83c40b1b08 100644 --- a/tests/rustdoc-html/typedef-inner-variants.rs +++ b/tests/rustdoc-html/typedef-inner-variants.rs @@ -116,6 +116,7 @@ pub type HighlyGenericAABB = HighlyGenericStruct; //@ count - '//*[@id="aliased-type"]' 1 //@ count - '//*[@id="variants"]' 0 //@ count - '//*[@id="fields"]' 1 +//@ has - '//pre[@class="rust item-decl"]//code' '/* private fields */' pub use cross_crate_generic_typedef::InlineU64; //@ has 'inner_variants/type.InlineEnum.html' @@ -123,4 +124,5 @@ pub use cross_crate_generic_typedef::InlineU64; //@ count - '//*[@id="variants"]' 1 //@ count - '//*[@id="fields"]' 0 //@ count - '//*[@class="variant"]' 2 +//@ has - '//pre[@class="rust item-decl"]//code' '// some variants omitted' pub type InlineEnum = cross_crate_generic_typedef::GenericEnum; From 91b5e6b3f3a0dd22bb25876aad1e30232b356da6 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Wed, 3 Jun 2026 13:33:24 +0200 Subject: [PATCH 04/13] Improve invalid cfg predicate error --- .../rustc_attr_parsing/src/attributes/cfg.rs | 6 ++--- .../src/session_diagnostics.rs | 9 ------- .../src/error_codes/E0537.md | 1 + .../unsafe/extraneous-unsafe-attributes.rs | 2 +- .../extraneous-unsafe-attributes.stderr | 17 ++++++++++--- .../cfg-attr-invalid-predicate.rs | 2 +- .../cfg-attr-invalid-predicate.stderr | 17 ++++++++++--- .../cfg-attr-syntax-validation.rs | 4 ++- .../cfg-attr-syntax-validation.stderr | 25 +++++++++++++------ .../cfg_attr-attr-syntax-validation.rs | 2 +- .../cfg_attr-attr-syntax-validation.stderr | 19 ++++++++++---- tests/ui/macros/cfg_select.rs | 2 +- tests/ui/macros/cfg_select.stderr | 8 +++--- tests/ui/span/E0537.rs | 4 --- tests/ui/span/E0537.stderr | 9 ------- 15 files changed, 71 insertions(+), 56 deletions(-) delete mode 100644 tests/ui/span/E0537.rs delete mode 100644 tests/ui/span/E0537.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 3a2f0ea74ba25..4b0affc57165e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -103,10 +103,8 @@ pub fn parse_cfg_entry( Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?, Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?, _ => { - return Err(cx.emit_err(session_diagnostics::InvalidPredicate { - span: meta.span(), - predicate: meta.path().to_string(), - })); + let possibilities = &[sym::any, sym::all, sym::not, sym::target, sym::version]; + return Err(cx.adcx().expected_specific_argument(meta.span(), possibilities)); } }, a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => { diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 121cac79e6382..193ffe195fb6c 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -13,15 +13,6 @@ use rustc_target::spec::TargetTuple; use crate::AttributeTemplate; use crate::context::Suggestion; -#[derive(Diagnostic)] -#[diag("invalid predicate `{$predicate}`", code = E0537)] -pub(crate) struct InvalidPredicate { - #[primary_span] - pub span: Span, - - pub predicate: String, -} - #[derive(Diagnostic)] #[diag("{$attr_str} attribute cannot have empty value")] pub(crate) struct DocAliasEmpty<'a> { diff --git a/compiler/rustc_error_codes/src/error_codes/E0537.md b/compiler/rustc_error_codes/src/error_codes/E0537.md index 123efd4f57df3..da0cc9d9ee1ea 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0537.md +++ b/compiler/rustc_error_codes/src/error_codes/E0537.md @@ -1,3 +1,4 @@ +#### Note: this error code is no longer emitted by the compiler An unknown predicate was used inside the `cfg` attribute. Erroneous code example: diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs index a034b7246a347..dd3097119271b 100644 --- a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs @@ -29,5 +29,5 @@ static FOO: usize = 0; fn main() { let _a = cfg!(unsafe(foo)); //~^ ERROR: expected identifier, found keyword `unsafe` - //~^^ ERROR: invalid predicate `r#unsafe` + //~^^ ERROR: malformed `cfg` macro input [E0539] } diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr index dec8c4d3542b4..49f28a55c7f89 100644 --- a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr @@ -33,11 +33,20 @@ help: escape `unsafe` to use it as an identifier LL | let _a = cfg!(r#unsafe(foo)); | ++ -error[E0537]: invalid predicate `r#unsafe` - --> $DIR/extraneous-unsafe-attributes.rs:30:19 +error[E0539]: malformed `cfg` macro input + --> $DIR/extraneous-unsafe-attributes.rs:30:14 | LL | let _a = cfg!(unsafe(foo)); - | ^^^^^^^^^^^ + | ^^^^^-----------^ + | | + | valid arguments are `any`, `all`, `not`, `target` or `version` + | + = note: for more information, visit +help: must be of the form + | +LL - let _a = cfg!(unsafe(foo)); +LL + let _a = cfg!(predicate); + | error: `ignore` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:12:3 @@ -81,4 +90,4 @@ LL | #[unsafe(used)] error: aborting due to 10 previous errors -For more information about this error, try `rustc --explain E0537`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.rs b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.rs index 496d196c94ae5..61d0f45437c00 100644 --- a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.rs +++ b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.rs @@ -1,4 +1,4 @@ -#[cfg(foo(bar))] //~ ERROR invalid predicate `foo` +#[cfg(foo(bar))] //~ ERROR malformed `cfg` attribute input [E0539] fn check() {} fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr index 2033894b3b4f6..d815cbde08736 100644 --- a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr @@ -1,9 +1,18 @@ -error[E0537]: invalid predicate `foo` - --> $DIR/cfg-attr-invalid-predicate.rs:1:7 +error[E0539]: malformed `cfg` attribute input + --> $DIR/cfg-attr-invalid-predicate.rs:1:1 | LL | #[cfg(foo(bar))] - | ^^^^^^^^ + | ^^^^^^--------^^ + | | + | valid arguments are `any`, `all`, `not`, `target` or `version` + | + = note: for more information, visit +help: must be of the form + | +LL - #[cfg(foo(bar))] +LL + #[cfg(predicate)] + | error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0537`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index 5f319555b9a19..b08bdc59339b3 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -34,7 +34,9 @@ struct S5; //~| NOTE for more information, visit struct S6; -#[cfg(a())] //~ ERROR invalid predicate `a` +#[cfg(a())] //~ ERROR malformed `cfg` attribute input +//~| NOTE valid arguments are `any`, `all`, `not`, `target` or `version` +//~| NOTE for more information, visit struct S7; #[cfg(a = 10)] //~ ERROR malformed `cfg` attribute input diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 8098e09fba567..65730e2ecf6e9 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -89,14 +89,23 @@ LL - #[cfg(a::b)] LL + #[cfg(predicate)] | -error[E0537]: invalid predicate `a` - --> $DIR/cfg-attr-syntax-validation.rs:37:7 +error[E0539]: malformed `cfg` attribute input + --> $DIR/cfg-attr-syntax-validation.rs:37:1 | LL | #[cfg(a())] - | ^^^ + | ^^^^^^---^^ + | | + | valid arguments are `any`, `all`, `not`, `target` or `version` + | + = note: for more information, visit +help: must be of the form + | +LL - #[cfg(a())] +LL + #[cfg(predicate)] + | error[E0539]: malformed `cfg` attribute input - --> $DIR/cfg-attr-syntax-validation.rs:40:1 + --> $DIR/cfg-attr-syntax-validation.rs:42:1 | LL | #[cfg(a = 10)] | ^^^^^^^^^^--^^ @@ -111,7 +120,7 @@ LL + #[cfg(predicate)] | error[E0539]: malformed `cfg` attribute input - --> $DIR/cfg-attr-syntax-validation.rs:45:1 + --> $DIR/cfg-attr-syntax-validation.rs:47:1 | LL | #[cfg(a = b"hi")] | ^^^^^^^^^^-^^^^^^ @@ -121,7 +130,7 @@ LL | #[cfg(a = b"hi")] = note: expected a normal string literal, not a byte string literal error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable - --> $DIR/cfg-attr-syntax-validation.rs:51:25 + --> $DIR/cfg-attr-syntax-validation.rs:53:25 | LL | #[cfg(feature = $expr)] | ^^^^^ @@ -133,5 +142,5 @@ LL | generate_s10!(concat!("nonexistent")); error: aborting due to 10 previous errors -Some errors have detailed explanations: E0537, E0539, E0565, E0805. -For more information about an error, try `rustc --explain E0537`. +Some errors have detailed explanations: E0539, E0565, E0805. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs index a0f86e3e771fd..907e1b966766f 100644 --- a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs @@ -16,7 +16,7 @@ struct S5; #[cfg_attr(a::b)] //~ ERROR malformed `cfg_attr` attribute input struct S6; -#[cfg_attr(a())] //~ ERROR invalid predicate `a` +#[cfg_attr(a())] //~ ERROR malformed `cfg_attr` attribute input [E0539] struct S7; #[cfg_attr(a = 10)] //~ ERROR malformed `cfg_attr` attribute input diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr index 41b2b416509b0..dd28f37e59afe 100644 --- a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr @@ -67,11 +67,20 @@ LL - #[cfg_attr(a::b)] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0537]: invalid predicate `a` - --> $DIR/cfg_attr-attr-syntax-validation.rs:19:12 +error[E0539]: malformed `cfg_attr` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:19:1 | LL | #[cfg_attr(a())] - | ^^^ + | ^^^^^^^^^^^---^^ + | | + | valid arguments are `any`, `all`, `not`, `target` or `version` + | + = note: for more information, visit +help: must be of the form + | +LL - #[cfg_attr(a())] +LL + #[cfg_attr(predicate, attr1, attr2, ...)] + | error[E0539]: malformed `cfg_attr` attribute input --> $DIR/cfg_attr-attr-syntax-validation.rs:22:1 @@ -177,5 +186,5 @@ LL | #[cfg_attr(true, link_section)] error: aborting due to 13 previous errors; 1 warning emitted -Some errors have detailed explanations: E0537, E0539, E0565, E0805. -For more information about an error, try `rustc --explain E0537`. +Some errors have detailed explanations: E0539, E0565, E0805. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 99db268bd28b7..0f03a8a99c4fb 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -188,7 +188,7 @@ cfg_select! { cfg_select! { a() => {} - //~^ ERROR invalid predicate `a` [E0537] + //~^ ERROR malformed `cfg_select` macro input [E0539] } cfg_select! { diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index e5871619b957a..2c6bdd8e353d3 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -37,11 +37,11 @@ error[E0565]: malformed `cfg_select` macro input LL | a::b => {} | ^^^^ expected a valid identifier here -error[E0537]: invalid predicate `a` +error[E0539]: malformed `cfg_select` macro input --> $DIR/cfg_select.rs:190:5 | LL | a() => {} - | ^^^ + | ^^^ valid arguments are `any`, `all`, `not`, `target` or `version` error: expected one of `(`, `::`, `=>`, or `=`, found `+` --> $DIR/cfg_select.rs:195:7 @@ -185,5 +185,5 @@ LL | cfg!() => {} error: aborting due to 17 previous errors; 7 warnings emitted -Some errors have detailed explanations: E0537, E0565, E0753. -For more information about an error, try `rustc --explain E0537`. +Some errors have detailed explanations: E0539, E0565, E0753. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/span/E0537.rs b/tests/ui/span/E0537.rs deleted file mode 100644 index 4088a9ae53a27..0000000000000 --- a/tests/ui/span/E0537.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[cfg(unknown())] //~ ERROR E0537 -pub fn something() {} - -pub fn main() {} diff --git a/tests/ui/span/E0537.stderr b/tests/ui/span/E0537.stderr deleted file mode 100644 index 4254d3893b83f..0000000000000 --- a/tests/ui/span/E0537.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0537]: invalid predicate `unknown` - --> $DIR/E0537.rs:1:7 - | -LL | #[cfg(unknown())] - | ^^^^^^^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0537`. From 57c762e4c034d84a797d83fea93f98db06992d38 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 12 Jun 2026 12:19:44 +0200 Subject: [PATCH 05/13] Add feature check for cfg_version --- compiler/rustc_attr_parsing/src/attributes/cfg.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 4b0affc57165e..47d3a1249c846 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -103,8 +103,11 @@ pub fn parse_cfg_entry( Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?, Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?, _ => { - let possibilities = &[sym::any, sym::all, sym::not, sym::target, sym::version]; - return Err(cx.adcx().expected_specific_argument(meta.span(), possibilities)); + let mut possibilities = vec![sym::any, sym::all, sym::not, sym::target]; + if cx.features().cfg_version() { + possibilities.push(sym::version); + } + return Err(cx.adcx().expected_specific_argument(meta.span(), &possibilities)); } }, a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => { From 34cb96a41fe2780114cd30b06cd52de508720ab6 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Fri, 12 Jun 2026 13:58:55 +0200 Subject: [PATCH 06/13] Fix ui tests with bless --- bad_error.rs | 6 ++++++ .../attributes/unsafe/extraneous-unsafe-attributes.stderr | 2 +- .../cfg-attr-invalid-predicate.stderr | 2 +- .../conditional-compilation/cfg-attr-syntax-validation.rs | 2 +- .../cfg-attr-syntax-validation.stderr | 2 +- .../cfg_attr-attr-syntax-validation.stderr | 2 +- tests/ui/macros/cfg_select.stderr | 2 +- 7 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 bad_error.rs diff --git a/bad_error.rs b/bad_error.rs new file mode 100644 index 0000000000000..c7ef5f0c26bbe --- /dev/null +++ b/bad_error.rs @@ -0,0 +1,6 @@ +// Hint: expected_specific_argument +#![feature(cfg_version)] +#[cfg(does_not_exist())] +fn test() {} + +fn main() {} diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr index 49f28a55c7f89..0236f79d0bc3e 100644 --- a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr @@ -39,7 +39,7 @@ error[E0539]: malformed `cfg` macro input LL | let _a = cfg!(unsafe(foo)); | ^^^^^-----------^ | | - | valid arguments are `any`, `all`, `not`, `target` or `version` + | valid arguments are `any`, `all`, `not` or `target` | = note: for more information, visit help: must be of the form diff --git a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr index d815cbde08736..5e15ecd66bcd6 100644 --- a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr @@ -4,7 +4,7 @@ error[E0539]: malformed `cfg` attribute input LL | #[cfg(foo(bar))] | ^^^^^^--------^^ | | - | valid arguments are `any`, `all`, `not`, `target` or `version` + | valid arguments are `any`, `all`, `not` or `target` | = note: for more information, visit help: must be of the form diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index b08bdc59339b3..f78353d10991f 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -35,7 +35,7 @@ struct S5; struct S6; #[cfg(a())] //~ ERROR malformed `cfg` attribute input -//~| NOTE valid arguments are `any`, `all`, `not`, `target` or `version` +//~| NOTE valid arguments are `any`, `all`, `not` or `target` //~| NOTE for more information, visit struct S7; diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 65730e2ecf6e9..97792a9a151d7 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -95,7 +95,7 @@ error[E0539]: malformed `cfg` attribute input LL | #[cfg(a())] | ^^^^^^---^^ | | - | valid arguments are `any`, `all`, `not`, `target` or `version` + | valid arguments are `any`, `all`, `not` or `target` | = note: for more information, visit help: must be of the form diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr index dd28f37e59afe..ff7c289ef1f6f 100644 --- a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr @@ -73,7 +73,7 @@ error[E0539]: malformed `cfg_attr` attribute input LL | #[cfg_attr(a())] | ^^^^^^^^^^^---^^ | | - | valid arguments are `any`, `all`, `not`, `target` or `version` + | valid arguments are `any`, `all`, `not` or `target` | = note: for more information, visit help: must be of the form diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 2c6bdd8e353d3..1199b1f4d026c 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -41,7 +41,7 @@ error[E0539]: malformed `cfg_select` macro input --> $DIR/cfg_select.rs:190:5 | LL | a() => {} - | ^^^ valid arguments are `any`, `all`, `not`, `target` or `version` + | ^^^ valid arguments are `any`, `all`, `not` or `target` error: expected one of `(`, `::`, `=>`, or `=`, found `+` --> $DIR/cfg_select.rs:195:7 From 851ab7aecc170305848f7c4f4634d5d44820ff40 Mon Sep 17 00:00:00 2001 From: Eva van Houten Date: Sat, 13 Jun 2026 16:17:18 +0200 Subject: [PATCH 07/13] Fix error-index test (and remove accidentally committed file) --- bad_error.rs | 6 ------ compiler/rustc_error_codes/src/error_codes/E0537.md | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 bad_error.rs diff --git a/bad_error.rs b/bad_error.rs deleted file mode 100644 index c7ef5f0c26bbe..0000000000000 --- a/bad_error.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Hint: expected_specific_argument -#![feature(cfg_version)] -#[cfg(does_not_exist())] -fn test() {} - -fn main() {} diff --git a/compiler/rustc_error_codes/src/error_codes/E0537.md b/compiler/rustc_error_codes/src/error_codes/E0537.md index da0cc9d9ee1ea..8d5b3b3fb8714 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0537.md +++ b/compiler/rustc_error_codes/src/error_codes/E0537.md @@ -3,7 +3,7 @@ An unknown predicate was used inside the `cfg` attribute. Erroneous code example: -```compile_fail,E0537 +```compile_fail,E0539 #[cfg(unknown())] // error: invalid predicate `unknown` pub fn something() {} From b5e7310a446721653b8637f6eaea7c38d6fe5ad5 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:37:48 +0200 Subject: [PATCH 08/13] Move declaration of `UNSAFE_CODE` to `rustc_lint_defs` --- compiler/rustc_lint/src/builtin.rs | 40 ------------------------- compiler/rustc_lint_defs/src/builtin.rs | 40 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5e239ad6beeb3..e3b9bc575574d 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -189,46 +189,6 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns { } } -declare_lint! { - /// The `unsafe_code` lint catches usage of `unsafe` code and other - /// potentially unsound constructs like `no_mangle`, `export_name`, - /// and `link_section`. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![deny(unsafe_code)] - /// fn main() { - /// unsafe { - /// - /// } - /// } - /// - /// #[no_mangle] - /// fn func_0() { } - /// - /// #[export_name = "exported_symbol_name"] - /// pub fn name_in_rust() { } - /// - /// #[no_mangle] - /// #[link_section = ".example_section"] - /// pub static VAR1: u32 = 1; - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// This lint is intended to restrict the usage of `unsafe` blocks and other - /// constructs (including, but not limited to `no_mangle`, `link_section` - /// and `export_name` attributes) wrong usage of which causes undefined - /// behavior. - UNSAFE_CODE, - Allow, - "usage of `unsafe` code and other potentially unsound constructs", - @eval_always = true -} - declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]); impl UnsafeCode { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 130ae0a178442..8408db6687eb4 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -5513,3 +5513,43 @@ declare_lint! { report_in_deps: false, }; } + +declare_lint! { + /// The `unsafe_code` lint catches usage of `unsafe` code and other + /// potentially unsound constructs like `no_mangle`, `export_name`, + /// and `link_section`. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(unsafe_code)] + /// fn main() { + /// unsafe { + /// + /// } + /// } + /// + /// #[no_mangle] + /// fn func_0() { } + /// + /// #[export_name = "exported_symbol_name"] + /// pub fn name_in_rust() { } + /// + /// #[no_mangle] + /// #[link_section = ".example_section"] + /// pub static VAR1: u32 = 1; + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// This lint is intended to restrict the usage of `unsafe` blocks and other + /// constructs (including, but not limited to `no_mangle`, `link_section` + /// and `export_name` attributes) wrong usage of which causes undefined + /// behavior. + pub UNSAFE_CODE, + Allow, + "usage of `unsafe` code and other potentially unsound constructs", + @eval_always = true +} From 765c5f5fb8930aa2573ae1b2d30ff9ad3cb36d0a Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:38:52 +0200 Subject: [PATCH 09/13] Move logic for emitting `UNSAFE_CODE` for unsafe attributes to attr parsing --- .../src/attributes/codegen_attrs.rs | 10 +- .../src/attributes/link_attrs.rs | 5 +- .../rustc_attr_parsing/src/attributes/mod.rs | 6 +- .../rustc_attr_parsing/src/diagnostics.rs | 8 + compiler/rustc_attr_parsing/src/safety.rs | 16 +- compiler/rustc_lint/src/builtin.rs | 39 ---- compiler/rustc_lint/src/lints.rs | 40 ---- tests/ui/lint/lint-unsafe-code.rs | 28 +-- tests/ui/lint/lint-unsafe-code.stderr | 209 +++++++++--------- 9 files changed, 159 insertions(+), 202 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 1ff3d6c13d0aa..2386c736b641c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -108,7 +108,10 @@ pub(crate) struct ExportNameParser; impl SingleAttributeParser for ExportNameParser { const PATH: &[rustc_span::Symbol] = &[sym::export_name]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: Some(Edition2024) }; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { + note: "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them", + unsafe_since: Some(Edition2024), + }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Static), Allow(Target::Fn), @@ -347,7 +350,10 @@ pub(crate) struct NoMangleParser; impl NoArgsAttributeParser for NoMangleParser { const PATH: &[Symbol] = &[sym::no_mangle]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: Some(Edition2024) }; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { + note: "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them", + unsafe_since: Some(Edition2024), + }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Fn), Allow(Target::Static), diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index bc500ddd48acf..59eae835801aa 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -489,7 +489,10 @@ fn check_link_section_macho(name: Symbol) -> Result<(), InvalidMachoSectionReaso impl SingleAttributeParser for LinkSectionParser { const PATH: &[Symbol] = &[sym::link_section]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: Some(Edition2024) }; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { + note: "the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them", + unsafe_since: Some(Edition2024), + }; const STABILITY: AttributeStability = AttributeStability::Stable; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Static), diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 7ea4c7fc6fe73..824ac08367017 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -236,7 +236,11 @@ pub enum AttributeSafety { /// An error is emitted when `#[unsafe(...)]` is omitted, except when the attribute's edition /// is less than the one stored in `unsafe_since`. This handles attributes that were safe in /// earlier editions, but become unsafe in later ones. - Unsafe { unsafe_since: Option }, + Unsafe { + /// The `note` is emitted during the `unsafe_code`, and explains to the user why this attribute is unsafe. + note: &'static str, + unsafe_since: Option, + }, } /// An even simpler version of [`SingleAttributeParser`]: diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 220da9b92938b..32bd6ee57a00f 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -826,3 +826,11 @@ pub(crate) enum InvalidOnClause { "using multiple `rustc_on_unimplemented` (or mixing it with `diagnostic::on_unimplemented`) is not supported" )] pub(crate) struct DupesNotAllowed; + +#[derive(Diagnostic)] +#[diag("usage of the unsafe `#[{$attr_path}]` attribute")] +#[note("{$note}")] +pub(crate) struct UnsafeAttribute { + pub attr_path: AttrPath, + pub note: &'static str, +} diff --git a/compiler/rustc_attr_parsing/src/safety.rs b/compiler/rustc_attr_parsing/src/safety.rs index 857ba23910656..5b1e50ffa5603 100644 --- a/compiler/rustc_attr_parsing/src/safety.rs +++ b/compiler/rustc_attr_parsing/src/safety.rs @@ -1,6 +1,7 @@ use rustc_ast::Safety; use rustc_errors::{Diagnostic, MultiSpan}; use rustc_hir::AttrPath; +use rustc_lint_defs::builtin::UNSAFE_CODE; use rustc_session::lint::LintId; use rustc_session::lint::builtin::UNSAFE_ATTR_OUTSIDE_UNSAFE; use rustc_span::Span; @@ -21,6 +22,7 @@ impl<'sess> AttributeParser<'sess> { return; } + // Check if expected & actual safety match match (expected_safety, attr_safety) { // - Unsafe builtin attribute // - User wrote `#[unsafe(..)]`, which is permitted on any edition @@ -30,7 +32,7 @@ impl<'sess> AttributeParser<'sess> { // - Unsafe builtin attribute // - User did not write `#[unsafe(..)]` - (AttributeSafety::Unsafe { unsafe_since }, Safety::Default) => { + (AttributeSafety::Unsafe { unsafe_since, note: _ }, Safety::Default) => { let path_span = attr_path.span; // If the `attr_item`'s span is not from a macro, then just suggest @@ -112,5 +114,17 @@ impl<'sess> AttributeParser<'sess> { ); } } + + // Emit `unsafe_code` lint + if let AttributeSafety::Unsafe { note, .. } = expected_safety { + let attr_path = attr_path.clone(); + emit_lint( + LintId::of(UNSAFE_CODE), + attr_span.into(), + EmitAttribute(Box::new(move |dcx, level, _| { + diagnostics::UnsafeAttribute { attr_path, note }.into_diag(dcx, level) + })), + ) + } } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e3b9bc575574d..2bee8949c384e 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -231,34 +231,6 @@ impl EarlyLintPass for UnsafeCode { self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeImpl); } - ast::ItemKind::Fn(..) => { - if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleFn); - } - - if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameFn); - } - - if let Some(attr) = attr::find_by_name(&it.attrs, sym::link_section) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::LinkSectionFn); - } - } - - ast::ItemKind::Static(..) => { - if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleStatic); - } - - if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameStatic); - } - - if let Some(attr) = attr::find_by_name(&it.attrs, sym::link_section) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::LinkSectionStatic); - } - } - ast::ItemKind::GlobalAsm(..) => { self.report_unsafe(cx, it.span, BuiltinUnsafe::GlobalAsm); } @@ -285,17 +257,6 @@ impl EarlyLintPass for UnsafeCode { } } - fn check_impl_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { - if let ast::AssocItemKind::Fn(..) = it.kind { - if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::NoMangleMethod); - } - if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::ExportNameMethod); - } - } - } - fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast::NodeId) { if let FnKind::Fn( ctxt, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a77ee599395b1..d3048d08ebf77 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -160,46 +160,6 @@ pub(crate) enum BuiltinUnsafe { UnsafeTrait, #[diag("implementation of an `unsafe` trait")] UnsafeImpl, - #[diag("declaration of a `no_mangle` function")] - #[note( - "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" - )] - NoMangleFn, - #[diag("declaration of a function with `export_name`")] - #[note( - "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" - )] - ExportNameFn, - #[diag("declaration of a function with `link_section`")] - #[note( - "the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them" - )] - LinkSectionFn, - #[diag("declaration of a `no_mangle` static")] - #[note( - "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" - )] - NoMangleStatic, - #[diag("declaration of a static with `export_name`")] - #[note( - "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" - )] - ExportNameStatic, - #[diag("declaration of a static with `link_section`")] - #[note( - "the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them" - )] - LinkSectionStatic, - #[diag("declaration of a `no_mangle` method")] - #[note( - "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" - )] - NoMangleMethod, - #[diag("declaration of a method with `export_name`")] - #[note( - "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" - )] - ExportNameMethod, #[diag("declaration of an `unsafe` function")] DeclUnsafeFn, #[diag("declaration of an `unsafe` method")] diff --git a/tests/ui/lint/lint-unsafe-code.rs b/tests/ui/lint/lint-unsafe-code.rs index 9b32336b05d49..014488b3d284c 100644 --- a/tests/ui/lint/lint-unsafe-code.rs +++ b/tests/ui/lint/lint-unsafe-code.rs @@ -18,18 +18,18 @@ mod allowed_unsafe { macro_rules! unsafe_in_macro { () => {{ - #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function - #[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static + #[no_mangle] fn foo() {} //~ ERROR: usage of the unsafe `#[no_mangle]` attribute + #[no_mangle] static FOO: u32 = 5; //~ ERROR: usage of the unsafe `#[no_mangle]` attribute #[export_name = "bar"] fn bar() {} - //~^ ERROR: declaration of a function with `export_name` + //~^ ERROR: usage of the unsafe `#[export_name]` attribute #[export_name = "BAR"] static BAR: u32 = 5; - //~^ ERROR: declaration of a static with `export_name` + //~^ ERROR: usage of the unsafe `#[export_name]` attribute unsafe {} //~ ERROR: usage of an `unsafe` block }} } -#[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function -#[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static +#[no_mangle] fn foo() {} //~ ERROR: usage of the unsafe `#[no_mangle]` attribute +#[no_mangle] static FOO: u32 = 5; //~ ERROR: usage of the unsafe `#[no_mangle]` attribute trait AssocFnTrait { fn foo(); @@ -38,27 +38,27 @@ trait AssocFnTrait { struct AssocFnFoo; impl AssocFnFoo { - #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` method + #[no_mangle] fn foo() {} //~ ERROR: usage of the unsafe `#[no_mangle]` attribute } impl AssocFnTrait for AssocFnFoo { - #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` method + #[no_mangle] fn foo() {} //~ ERROR: usage of the unsafe `#[no_mangle]` attribute } -#[export_name = "bar"] fn bar() {} //~ ERROR: declaration of a function with `export_name` -#[export_name = "BAR"] static BAR: u32 = 5; //~ ERROR: declaration of a static with `export_name` +#[export_name = "bar"] fn bar() {} //~ ERROR: usage of the unsafe `#[export_name]` attribute +#[export_name = "BAR"] static BAR: u32 = 5; //~ ERROR: usage of the unsafe `#[export_name]` attribute -#[link_section = "__TEXT,__text"] fn uwu() {} //~ ERROR: declaration of a function with `link_section` -#[link_section = "__TEXT,__text"] static UWU: u32 = 5; //~ ERROR: declaration of a static with `link_section` +#[link_section = "__TEXT,__text"] fn uwu() {} //~ ERROR: usage of the unsafe `#[link_section]` attribute +#[link_section = "__TEXT,__text"] static UWU: u32 = 5; //~ ERROR: usage of the unsafe `#[link_section]` attribute struct AssocFnBar; impl AssocFnBar { - #[export_name = "bar"] fn bar() {} //~ ERROR: declaration of a method with `export_name` + #[export_name = "bar"] fn bar() {} //~ ERROR: usage of the unsafe `#[export_name]` attribute } impl AssocFnTrait for AssocFnBar { - #[export_name = "bar"] fn foo() {} //~ ERROR: declaration of a method with `export_name` + #[export_name = "bar"] fn foo() {} //~ ERROR: usage of the unsafe `#[export_name]` attribute } unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function diff --git a/tests/ui/lint/lint-unsafe-code.stderr b/tests/ui/lint/lint-unsafe-code.stderr index aade33aef44ee..8f316f1d27ce8 100644 --- a/tests/ui/lint/lint-unsafe-code.stderr +++ b/tests/ui/lint/lint-unsafe-code.stderr @@ -1,94 +1,15 @@ -error: declaration of a `no_mangle` function - --> $DIR/lint-unsafe-code.rs:31:1 +error: declaration of an `unsafe` function + --> $DIR/lint-unsafe-code.rs:64:1 | -LL | #[no_mangle] fn foo() {} - | ^^^^^^^^^^^^ +LL | unsafe fn baz() {} + | ^^^^^^^^^^^^^^^^^^ | - = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them note: the lint level is defined here --> $DIR/lint-unsafe-code.rs:3:9 | LL | #![deny(unsafe_code)] | ^^^^^^^^^^^ -error: declaration of a `no_mangle` static - --> $DIR/lint-unsafe-code.rs:32:1 - | -LL | #[no_mangle] static FOO: u32 = 5; - | ^^^^^^^^^^^^ - | - = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - -error: declaration of a `no_mangle` method - --> $DIR/lint-unsafe-code.rs:41:5 - | -LL | #[no_mangle] fn foo() {} - | ^^^^^^^^^^^^ - | - = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - -error: declaration of a `no_mangle` method - --> $DIR/lint-unsafe-code.rs:45:5 - | -LL | #[no_mangle] fn foo() {} - | ^^^^^^^^^^^^ - | - = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - -error: declaration of a function with `export_name` - --> $DIR/lint-unsafe-code.rs:48:1 - | -LL | #[export_name = "bar"] fn bar() {} - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - -error: declaration of a static with `export_name` - --> $DIR/lint-unsafe-code.rs:49:1 - | -LL | #[export_name = "BAR"] static BAR: u32 = 5; - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - -error: declaration of a function with `link_section` - --> $DIR/lint-unsafe-code.rs:51:1 - | -LL | #[link_section = "__TEXT,__text"] fn uwu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them - -error: declaration of a static with `link_section` - --> $DIR/lint-unsafe-code.rs:52:1 - | -LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them - -error: declaration of a method with `export_name` - --> $DIR/lint-unsafe-code.rs:57:5 - | -LL | #[export_name = "bar"] fn bar() {} - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - -error: declaration of a method with `export_name` - --> $DIR/lint-unsafe-code.rs:61:5 - | -LL | #[export_name = "bar"] fn foo() {} - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - -error: declaration of an `unsafe` function - --> $DIR/lint-unsafe-code.rs:64:1 - | -LL | unsafe fn baz() {} - | ^^^^^^^^^^^^^^^^^^ - error: declaration of an `unsafe` trait --> $DIR/lint-unsafe-code.rs:65:1 | @@ -161,23 +82,102 @@ error: usage of an `unsafe` block LL | unsafe {} | ^^^^^^^^^ -error: declaration of a `no_mangle` function - --> $DIR/lint-unsafe-code.rs:21:9 +error: usage of an `unsafe` block + --> $DIR/lint-unsafe-code.rs:27:9 | -LL | #[no_mangle] fn foo() {} - | ^^^^^^^^^^^^ +LL | unsafe {} + | ^^^^^^^^^ ... LL | unsafe_in_macro!() | ------------------ in this macro invocation | - = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error: declaration of a `no_mangle` static - --> $DIR/lint-unsafe-code.rs:22:9 +error: usage of the unsafe `#[no_mangle]` attribute + --> $DIR/lint-unsafe-code.rs:31:3 | -LL | #[no_mangle] static FOO: u32 = 5; - | ^^^^^^^^^^^^ +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[no_mangle]` attribute + --> $DIR/lint-unsafe-code.rs:32:3 + | +LL | #[no_mangle] static FOO: u32 = 5; + | ^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[no_mangle]` attribute + --> $DIR/lint-unsafe-code.rs:41:7 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[no_mangle]` attribute + --> $DIR/lint-unsafe-code.rs:45:7 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[export_name]` attribute + --> $DIR/lint-unsafe-code.rs:48:3 + | +LL | #[export_name = "bar"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[export_name]` attribute + --> $DIR/lint-unsafe-code.rs:49:3 + | +LL | #[export_name = "BAR"] static BAR: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[link_section]` attribute + --> $DIR/lint-unsafe-code.rs:51:3 + | +LL | #[link_section = "__TEXT,__text"] fn uwu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[link_section]` attribute + --> $DIR/lint-unsafe-code.rs:52:3 + | +LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[export_name]` attribute + --> $DIR/lint-unsafe-code.rs:57:7 + | +LL | #[export_name = "bar"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[export_name]` attribute + --> $DIR/lint-unsafe-code.rs:61:7 + | +LL | #[export_name = "bar"] fn foo() {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: usage of the unsafe `#[no_mangle]` attribute + --> $DIR/lint-unsafe-code.rs:21:11 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^ ... LL | unsafe_in_macro!() | ------------------ in this macro invocation @@ -185,11 +185,11 @@ LL | unsafe_in_macro!() = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error: declaration of a function with `export_name` - --> $DIR/lint-unsafe-code.rs:23:9 +error: usage of the unsafe `#[no_mangle]` attribute + --> $DIR/lint-unsafe-code.rs:22:11 | -LL | #[export_name = "bar"] fn bar() {} - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #[no_mangle] static FOO: u32 = 5; + | ^^^^^^^^^ ... LL | unsafe_in_macro!() | ------------------ in this macro invocation @@ -197,11 +197,11 @@ LL | unsafe_in_macro!() = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error: declaration of a static with `export_name` - --> $DIR/lint-unsafe-code.rs:25:9 +error: usage of the unsafe `#[export_name]` attribute + --> $DIR/lint-unsafe-code.rs:23:11 | -LL | #[export_name = "BAR"] static BAR: u32 = 5; - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #[export_name = "bar"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^ ... LL | unsafe_in_macro!() | ------------------ in this macro invocation @@ -209,15 +209,16 @@ LL | unsafe_in_macro!() = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error: usage of an `unsafe` block - --> $DIR/lint-unsafe-code.rs:27:9 +error: usage of the unsafe `#[export_name]` attribute + --> $DIR/lint-unsafe-code.rs:25:11 | -LL | unsafe {} - | ^^^^^^^^^ +LL | #[export_name = "BAR"] static BAR: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^ ... LL | unsafe_in_macro!() | ------------------ in this macro invocation | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 28 previous errors From 3cdf0379670755739a9366dc7a176842dcd18b74 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:48:17 +0200 Subject: [PATCH 10/13] Add support for `#[unsafe(naked)]` to the UNSAFE_CODE lint --- .../src/attributes/codegen_attrs.rs | 5 +- tests/ui/lint/lint-unsafe-code.rs | 22 +++++ tests/ui/lint/lint-unsafe-code.stderr | 90 +++++++++++++------ 3 files changed, 87 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 2386c736b641c..9274dd3409008 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -220,7 +220,10 @@ impl AttributeParser for NakedParser { this.span = Some(cx.attr_span); } })]; - const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { + note: "the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code).", + unsafe_since: None, + }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), diff --git a/tests/ui/lint/lint-unsafe-code.rs b/tests/ui/lint/lint-unsafe-code.rs index 014488b3d284c..6eef952f29a31 100644 --- a/tests/ui/lint/lint-unsafe-code.rs +++ b/tests/ui/lint/lint-unsafe-code.rs @@ -1,6 +1,9 @@ #![allow(unused_unsafe)] #![allow(dead_code)] #![deny(unsafe_code)] +#![feature(naked_functions_rustic_abi)] + +use std::arch::naked_asm; struct Bar; struct Bar2; @@ -128,3 +131,22 @@ fn main() { unsafe_in_macro!() } + +#[unsafe(naked)] fn naked1() { naked_asm!("halt") } +//~^ ERROR usage of the unsafe `#[naked]` attribute + +struct Naked; +impl Naked { + #[unsafe(naked)] fn naked2() { naked_asm!("halt") } + //~^ ERROR usage of the unsafe `#[naked]` attribute +} + +trait NakedTrait { + #[unsafe(naked)] fn naked3() { naked_asm!("halt") } + //~^ ERROR usage of the unsafe `#[naked]` attribute + fn naked4(); +} +impl NakedTrait for Naked { + #[unsafe(naked)] fn naked4() { naked_asm!("halt") } + //~^ ERROR usage of the unsafe `#[naked]` attribute +} diff --git a/tests/ui/lint/lint-unsafe-code.stderr b/tests/ui/lint/lint-unsafe-code.stderr index 8f316f1d27ce8..b8ef6bc7725e6 100644 --- a/tests/ui/lint/lint-unsafe-code.stderr +++ b/tests/ui/lint/lint-unsafe-code.stderr @@ -1,5 +1,5 @@ error: declaration of an `unsafe` function - --> $DIR/lint-unsafe-code.rs:64:1 + --> $DIR/lint-unsafe-code.rs:67:1 | LL | unsafe fn baz() {} | ^^^^^^^^^^^^^^^^^^ @@ -11,79 +11,79 @@ LL | #![deny(unsafe_code)] | ^^^^^^^^^^^ error: declaration of an `unsafe` trait - --> $DIR/lint-unsafe-code.rs:65:1 + --> $DIR/lint-unsafe-code.rs:68:1 | LL | unsafe trait Foo {} | ^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` trait - --> $DIR/lint-unsafe-code.rs:66:1 + --> $DIR/lint-unsafe-code.rs:69:1 | LL | unsafe impl Foo for Bar {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: declaration of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:69:5 + --> $DIR/lint-unsafe-code.rs:72:5 | LL | unsafe fn baz(&self); | ^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:70:5 + --> $DIR/lint-unsafe-code.rs:73:5 | LL | unsafe fn provided(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:71:5 + --> $DIR/lint-unsafe-code.rs:74:5 | LL | unsafe fn provided_override(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:75:5 + --> $DIR/lint-unsafe-code.rs:78:5 | LL | unsafe fn baz(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:76:5 + --> $DIR/lint-unsafe-code.rs:79:5 | LL | unsafe fn provided_override(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:95:5 + --> $DIR/lint-unsafe-code.rs:98:5 | LL | unsafe fn provided_override(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:106:5 + --> $DIR/lint-unsafe-code.rs:109:5 | LL | unsafe fn provided(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:112:5 + --> $DIR/lint-unsafe-code.rs:115:5 | LL | unsafe fn provided(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:116:5 + --> $DIR/lint-unsafe-code.rs:119:5 | LL | unsafe fn baz(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of an `unsafe` block - --> $DIR/lint-unsafe-code.rs:127:5 + --> $DIR/lint-unsafe-code.rs:130:5 | LL | unsafe {} | ^^^^^^^^^ error: usage of an `unsafe` block - --> $DIR/lint-unsafe-code.rs:27:9 + --> $DIR/lint-unsafe-code.rs:30:9 | LL | unsafe {} | ^^^^^^^^^ @@ -94,7 +94,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:31:3 + --> $DIR/lint-unsafe-code.rs:34:3 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -102,7 +102,7 @@ LL | #[no_mangle] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:32:3 + --> $DIR/lint-unsafe-code.rs:35:3 | LL | #[no_mangle] static FOO: u32 = 5; | ^^^^^^^^^ @@ -110,7 +110,7 @@ LL | #[no_mangle] static FOO: u32 = 5; = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:41:7 + --> $DIR/lint-unsafe-code.rs:44:7 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -118,7 +118,7 @@ LL | #[no_mangle] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:45:7 + --> $DIR/lint-unsafe-code.rs:48:7 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -126,7 +126,7 @@ LL | #[no_mangle] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:48:3 + --> $DIR/lint-unsafe-code.rs:51:3 | LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | #[export_name = "bar"] fn bar() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:49:3 + --> $DIR/lint-unsafe-code.rs:52:3 | LL | #[export_name = "BAR"] static BAR: u32 = 5; | ^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | #[export_name = "BAR"] static BAR: u32 = 5; = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[link_section]` attribute - --> $DIR/lint-unsafe-code.rs:51:3 + --> $DIR/lint-unsafe-code.rs:54:3 | LL | #[link_section = "__TEXT,__text"] fn uwu() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -150,7 +150,7 @@ LL | #[link_section = "__TEXT,__text"] fn uwu() {} = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[link_section]` attribute - --> $DIR/lint-unsafe-code.rs:52:3 + --> $DIR/lint-unsafe-code.rs:55:3 | LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,7 +158,7 @@ LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:57:7 + --> $DIR/lint-unsafe-code.rs:60:7 | LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL | #[export_name = "bar"] fn bar() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:61:7 + --> $DIR/lint-unsafe-code.rs:64:7 | LL | #[export_name = "bar"] fn foo() {} | ^^^^^^^^^^^^^^^^^^^ @@ -174,7 +174,7 @@ LL | #[export_name = "bar"] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:21:11 + --> $DIR/lint-unsafe-code.rs:24:11 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -186,7 +186,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:22:11 + --> $DIR/lint-unsafe-code.rs:25:11 | LL | #[no_mangle] static FOO: u32 = 5; | ^^^^^^^^^ @@ -198,7 +198,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:23:11 + --> $DIR/lint-unsafe-code.rs:26:11 | LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -210,7 +210,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:25:11 + --> $DIR/lint-unsafe-code.rs:28:11 | LL | #[export_name = "BAR"] static BAR: u32 = 5; | ^^^^^^^^^^^^^^^^^^^ @@ -221,5 +221,37 @@ LL | unsafe_in_macro!() = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 28 previous errors +error: usage of the unsafe `#[naked]` attribute + --> $DIR/lint-unsafe-code.rs:135:10 + | +LL | #[unsafe(naked)] fn naked1() { naked_asm!("halt") } + | ^^^^^ + | + = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). + +error: usage of the unsafe `#[naked]` attribute + --> $DIR/lint-unsafe-code.rs:140:14 + | +LL | #[unsafe(naked)] fn naked2() { naked_asm!("halt") } + | ^^^^^ + | + = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). + +error: usage of the unsafe `#[naked]` attribute + --> $DIR/lint-unsafe-code.rs:145:14 + | +LL | #[unsafe(naked)] fn naked3() { naked_asm!("halt") } + | ^^^^^ + | + = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). + +error: usage of the unsafe `#[naked]` attribute + --> $DIR/lint-unsafe-code.rs:150:14 + | +LL | #[unsafe(naked)] fn naked4() { naked_asm!("halt") } + | ^^^^^ + | + = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). + +error: aborting due to 32 previous errors From bce1306af2b28c1b7c1caa3a7d70dfc86ea2677b Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:46:41 +0200 Subject: [PATCH 11/13] Add support for `#[ffi_pure]` and `#[ffi_const]` to the UNSAFE_CODE lint --- .../src/attributes/link_attrs.rs | 10 ++- tests/ui/lint/lint-unsafe-code.rs | 12 +++ tests/ui/lint/lint-unsafe-code.stderr | 82 +++++++++++-------- 3 files changed, 69 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 59eae835801aa..9e1d062baba0b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -543,7 +543,10 @@ impl NoArgsAttributeParser for ExportStableParser { pub(crate) struct FfiConstParser; impl NoArgsAttributeParser for FfiConstParser { const PATH: &[Symbol] = &[sym::ffi_const]; - const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { + note: "`#[ffi_const]` functions shall have no effects except for its return value, which can only depend on the values of the function parameters, and is not affected by changes to the observable state of the program.", + unsafe_since: None, + }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const STABILITY: AttributeStability = unstable!(ffi_const); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::FfiConst; @@ -552,7 +555,10 @@ impl NoArgsAttributeParser for FfiConstParser { pub(crate) struct FfiPureParser; impl NoArgsAttributeParser for FfiPureParser { const PATH: &[Symbol] = &[sym::ffi_pure]; - const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { + note: "`#[ffi_pure]` functions shall have no effects except for its return value, which shall not change across two consecutive function calls with the same parameters.", + unsafe_since: None, + }; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const STABILITY: AttributeStability = unstable!(ffi_pure); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; diff --git a/tests/ui/lint/lint-unsafe-code.rs b/tests/ui/lint/lint-unsafe-code.rs index 6eef952f29a31..f39562c7ed668 100644 --- a/tests/ui/lint/lint-unsafe-code.rs +++ b/tests/ui/lint/lint-unsafe-code.rs @@ -2,6 +2,8 @@ #![allow(dead_code)] #![deny(unsafe_code)] #![feature(naked_functions_rustic_abi)] +#![feature(ffi_pure)] +#![feature(ffi_const)] use std::arch::naked_asm; @@ -150,3 +152,13 @@ impl NakedTrait for Naked { #[unsafe(naked)] fn naked4() { naked_asm!("halt") } //~^ ERROR usage of the unsafe `#[naked]` attribute } + +extern "C" { + #[unsafe(ffi_pure)] + //~^ ERROR usage of the unsafe `#[ffi_pure]` attribute + fn ffi_pure(); + + #[unsafe(ffi_const)] + //~^ ERROR usage of the unsafe `#[ffi_const]` attribute + fn ffi_const(); +} diff --git a/tests/ui/lint/lint-unsafe-code.stderr b/tests/ui/lint/lint-unsafe-code.stderr index b8ef6bc7725e6..4b4af70531ef6 100644 --- a/tests/ui/lint/lint-unsafe-code.stderr +++ b/tests/ui/lint/lint-unsafe-code.stderr @@ -1,5 +1,5 @@ error: declaration of an `unsafe` function - --> $DIR/lint-unsafe-code.rs:67:1 + --> $DIR/lint-unsafe-code.rs:69:1 | LL | unsafe fn baz() {} | ^^^^^^^^^^^^^^^^^^ @@ -11,79 +11,79 @@ LL | #![deny(unsafe_code)] | ^^^^^^^^^^^ error: declaration of an `unsafe` trait - --> $DIR/lint-unsafe-code.rs:68:1 + --> $DIR/lint-unsafe-code.rs:70:1 | LL | unsafe trait Foo {} | ^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` trait - --> $DIR/lint-unsafe-code.rs:69:1 + --> $DIR/lint-unsafe-code.rs:71:1 | LL | unsafe impl Foo for Bar {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: declaration of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:72:5 + --> $DIR/lint-unsafe-code.rs:74:5 | LL | unsafe fn baz(&self); | ^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:73:5 + --> $DIR/lint-unsafe-code.rs:75:5 | LL | unsafe fn provided(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:74:5 + --> $DIR/lint-unsafe-code.rs:76:5 | LL | unsafe fn provided_override(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:78:5 + --> $DIR/lint-unsafe-code.rs:80:5 | LL | unsafe fn baz(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:79:5 + --> $DIR/lint-unsafe-code.rs:81:5 | LL | unsafe fn provided_override(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:98:5 + --> $DIR/lint-unsafe-code.rs:100:5 | LL | unsafe fn provided_override(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:109:5 + --> $DIR/lint-unsafe-code.rs:111:5 | LL | unsafe fn provided(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:115:5 + --> $DIR/lint-unsafe-code.rs:117:5 | LL | unsafe fn provided(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:119:5 + --> $DIR/lint-unsafe-code.rs:121:5 | LL | unsafe fn baz(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of an `unsafe` block - --> $DIR/lint-unsafe-code.rs:130:5 + --> $DIR/lint-unsafe-code.rs:132:5 | LL | unsafe {} | ^^^^^^^^^ error: usage of an `unsafe` block - --> $DIR/lint-unsafe-code.rs:30:9 + --> $DIR/lint-unsafe-code.rs:32:9 | LL | unsafe {} | ^^^^^^^^^ @@ -94,7 +94,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:34:3 + --> $DIR/lint-unsafe-code.rs:36:3 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -102,7 +102,7 @@ LL | #[no_mangle] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:35:3 + --> $DIR/lint-unsafe-code.rs:37:3 | LL | #[no_mangle] static FOO: u32 = 5; | ^^^^^^^^^ @@ -110,7 +110,7 @@ LL | #[no_mangle] static FOO: u32 = 5; = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:44:7 + --> $DIR/lint-unsafe-code.rs:46:7 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -118,7 +118,7 @@ LL | #[no_mangle] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:48:7 + --> $DIR/lint-unsafe-code.rs:50:7 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -126,7 +126,7 @@ LL | #[no_mangle] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:51:3 + --> $DIR/lint-unsafe-code.rs:53:3 | LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | #[export_name = "bar"] fn bar() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:52:3 + --> $DIR/lint-unsafe-code.rs:54:3 | LL | #[export_name = "BAR"] static BAR: u32 = 5; | ^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | #[export_name = "BAR"] static BAR: u32 = 5; = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[link_section]` attribute - --> $DIR/lint-unsafe-code.rs:54:3 + --> $DIR/lint-unsafe-code.rs:56:3 | LL | #[link_section = "__TEXT,__text"] fn uwu() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -150,7 +150,7 @@ LL | #[link_section = "__TEXT,__text"] fn uwu() {} = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[link_section]` attribute - --> $DIR/lint-unsafe-code.rs:55:3 + --> $DIR/lint-unsafe-code.rs:57:3 | LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,7 +158,7 @@ LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:60:7 + --> $DIR/lint-unsafe-code.rs:62:7 | LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL | #[export_name = "bar"] fn bar() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:64:7 + --> $DIR/lint-unsafe-code.rs:66:7 | LL | #[export_name = "bar"] fn foo() {} | ^^^^^^^^^^^^^^^^^^^ @@ -174,7 +174,7 @@ LL | #[export_name = "bar"] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:24:11 + --> $DIR/lint-unsafe-code.rs:26:11 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -186,7 +186,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:25:11 + --> $DIR/lint-unsafe-code.rs:27:11 | LL | #[no_mangle] static FOO: u32 = 5; | ^^^^^^^^^ @@ -198,7 +198,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:26:11 + --> $DIR/lint-unsafe-code.rs:28:11 | LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -210,7 +210,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:28:11 + --> $DIR/lint-unsafe-code.rs:30:11 | LL | #[export_name = "BAR"] static BAR: u32 = 5; | ^^^^^^^^^^^^^^^^^^^ @@ -222,7 +222,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[naked]` attribute - --> $DIR/lint-unsafe-code.rs:135:10 + --> $DIR/lint-unsafe-code.rs:137:10 | LL | #[unsafe(naked)] fn naked1() { naked_asm!("halt") } | ^^^^^ @@ -230,7 +230,7 @@ LL | #[unsafe(naked)] fn naked1() { naked_asm!("halt") } = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). error: usage of the unsafe `#[naked]` attribute - --> $DIR/lint-unsafe-code.rs:140:14 + --> $DIR/lint-unsafe-code.rs:142:14 | LL | #[unsafe(naked)] fn naked2() { naked_asm!("halt") } | ^^^^^ @@ -238,7 +238,7 @@ LL | #[unsafe(naked)] fn naked2() { naked_asm!("halt") } = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). error: usage of the unsafe `#[naked]` attribute - --> $DIR/lint-unsafe-code.rs:145:14 + --> $DIR/lint-unsafe-code.rs:147:14 | LL | #[unsafe(naked)] fn naked3() { naked_asm!("halt") } | ^^^^^ @@ -246,12 +246,28 @@ LL | #[unsafe(naked)] fn naked3() { naked_asm!("halt") } = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). error: usage of the unsafe `#[naked]` attribute - --> $DIR/lint-unsafe-code.rs:150:14 + --> $DIR/lint-unsafe-code.rs:152:14 | LL | #[unsafe(naked)] fn naked4() { naked_asm!("halt") } | ^^^^^ | = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). -error: aborting due to 32 previous errors +error: usage of the unsafe `#[ffi_pure]` attribute + --> $DIR/lint-unsafe-code.rs:157:14 + | +LL | #[unsafe(ffi_pure)] + | ^^^^^^^^ + | + = note: `#[ffi_pure]` functions shall have no effects except for its return value, which shall not change across two consecutive function calls with the same parameters. + +error: usage of the unsafe `#[ffi_const]` attribute + --> $DIR/lint-unsafe-code.rs:161:14 + | +LL | #[unsafe(ffi_const)] + | ^^^^^^^^^ + | + = note: `#[ffi_const]` functions shall have no effects except for its return value, which can only depend on the values of the function parameters, and is not affected by changes to the observable state of the program. + +error: aborting due to 34 previous errors From 7ff784f7ed2dd755e17ceba9c02bb006e7998832 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:52:05 +0200 Subject: [PATCH 12/13] Add support for `#[unsafe(force_target_feature)]` to the UNSAFE_CODE lint --- .../src/attributes/codegen_attrs.rs | 5 +- tests/ui/lint/lint-unsafe-code.rs | 20 ++++ tests/ui/lint/lint-unsafe-code.stderr | 104 ++++++++++++------ 3 files changed, 92 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 9274dd3409008..320d198415164 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -549,7 +549,10 @@ pub(crate) struct ForceTargetFeatureParser; impl CombineAttributeParser for ForceTargetFeatureParser { type Item = (Symbol, Span); const PATH: &[Symbol] = &[sym::force_target_feature]; - const SAFETY: AttributeSafety = AttributeSafety::Unsafe { unsafe_since: None }; + const SAFETY: AttributeSafety = AttributeSafety::Unsafe { + note: "a function with the signature of the function the attribute is applied to must only be callable if the force-enabled features are guaranteed to be present", + unsafe_since: None, + }; const CONVERT: ConvertFn = |items, span| AttributeKind::TargetFeature { features: items, attr_span: span, diff --git a/tests/ui/lint/lint-unsafe-code.rs b/tests/ui/lint/lint-unsafe-code.rs index f39562c7ed668..1f032fdca1315 100644 --- a/tests/ui/lint/lint-unsafe-code.rs +++ b/tests/ui/lint/lint-unsafe-code.rs @@ -1,9 +1,11 @@ +//@ only-x86_64 (for the force_target_feature tests) #![allow(unused_unsafe)] #![allow(dead_code)] #![deny(unsafe_code)] #![feature(naked_functions_rustic_abi)] #![feature(ffi_pure)] #![feature(ffi_const)] +#![feature(effective_target_features)] use std::arch::naked_asm; @@ -162,3 +164,21 @@ extern "C" { //~^ ERROR usage of the unsafe `#[ffi_const]` attribute fn ffi_const(); } + +#[unsafe(force_target_feature(enable = "avx2"))] fn force_target_feature() { } +//~^ ERROR usage of the unsafe `#[force_target_feature]` attribute + +struct ForceTargetFeature; +impl ForceTargetFeature { + #[unsafe(force_target_feature(enable = "avx2"))] fn force_target_feature() { } + //~^ ERROR usage of the unsafe `#[force_target_feature]` attribute +} + +trait ForceTargetFeatureTrait { + #[unsafe(force_target_feature(enable = "avx2"))] fn force_target_feature() { } + //~^ ERROR usage of the unsafe `#[force_target_feature]` attribute +} +impl ForceTargetFeatureTrait for ForceTargetFeature { + #[unsafe(force_target_feature(enable = "avx2"))] fn force_target_feature() { } + //~^ ERROR usage of the unsafe `#[force_target_feature]` attribute +} diff --git a/tests/ui/lint/lint-unsafe-code.stderr b/tests/ui/lint/lint-unsafe-code.stderr index 4b4af70531ef6..a3a3a5315602a 100644 --- a/tests/ui/lint/lint-unsafe-code.stderr +++ b/tests/ui/lint/lint-unsafe-code.stderr @@ -1,89 +1,89 @@ error: declaration of an `unsafe` function - --> $DIR/lint-unsafe-code.rs:69:1 + --> $DIR/lint-unsafe-code.rs:71:1 | LL | unsafe fn baz() {} | ^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-unsafe-code.rs:3:9 + --> $DIR/lint-unsafe-code.rs:4:9 | LL | #![deny(unsafe_code)] | ^^^^^^^^^^^ error: declaration of an `unsafe` trait - --> $DIR/lint-unsafe-code.rs:70:1 + --> $DIR/lint-unsafe-code.rs:72:1 | LL | unsafe trait Foo {} | ^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` trait - --> $DIR/lint-unsafe-code.rs:71:1 + --> $DIR/lint-unsafe-code.rs:73:1 | LL | unsafe impl Foo for Bar {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: declaration of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:74:5 + --> $DIR/lint-unsafe-code.rs:76:5 | LL | unsafe fn baz(&self); | ^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:75:5 + --> $DIR/lint-unsafe-code.rs:77:5 | LL | unsafe fn provided(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:76:5 + --> $DIR/lint-unsafe-code.rs:78:5 | LL | unsafe fn provided_override(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:80:5 + --> $DIR/lint-unsafe-code.rs:82:5 | LL | unsafe fn baz(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:81:5 + --> $DIR/lint-unsafe-code.rs:83:5 | LL | unsafe fn provided_override(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:100:5 + --> $DIR/lint-unsafe-code.rs:102:5 | LL | unsafe fn provided_override(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:111:5 + --> $DIR/lint-unsafe-code.rs:113:5 | LL | unsafe fn provided(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:117:5 + --> $DIR/lint-unsafe-code.rs:119:5 | LL | unsafe fn provided(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of an `unsafe` method - --> $DIR/lint-unsafe-code.rs:121:5 + --> $DIR/lint-unsafe-code.rs:123:5 | LL | unsafe fn baz(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of an `unsafe` block - --> $DIR/lint-unsafe-code.rs:132:5 + --> $DIR/lint-unsafe-code.rs:134:5 | LL | unsafe {} | ^^^^^^^^^ error: usage of an `unsafe` block - --> $DIR/lint-unsafe-code.rs:32:9 + --> $DIR/lint-unsafe-code.rs:34:9 | LL | unsafe {} | ^^^^^^^^^ @@ -94,7 +94,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:36:3 + --> $DIR/lint-unsafe-code.rs:38:3 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -102,7 +102,7 @@ LL | #[no_mangle] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:37:3 + --> $DIR/lint-unsafe-code.rs:39:3 | LL | #[no_mangle] static FOO: u32 = 5; | ^^^^^^^^^ @@ -110,7 +110,7 @@ LL | #[no_mangle] static FOO: u32 = 5; = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:46:7 + --> $DIR/lint-unsafe-code.rs:48:7 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -118,7 +118,7 @@ LL | #[no_mangle] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:50:7 + --> $DIR/lint-unsafe-code.rs:52:7 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -126,7 +126,7 @@ LL | #[no_mangle] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:53:3 + --> $DIR/lint-unsafe-code.rs:55:3 | LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | #[export_name = "bar"] fn bar() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:54:3 + --> $DIR/lint-unsafe-code.rs:56:3 | LL | #[export_name = "BAR"] static BAR: u32 = 5; | ^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | #[export_name = "BAR"] static BAR: u32 = 5; = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[link_section]` attribute - --> $DIR/lint-unsafe-code.rs:56:3 + --> $DIR/lint-unsafe-code.rs:58:3 | LL | #[link_section = "__TEXT,__text"] fn uwu() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -150,7 +150,7 @@ LL | #[link_section = "__TEXT,__text"] fn uwu() {} = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[link_section]` attribute - --> $DIR/lint-unsafe-code.rs:57:3 + --> $DIR/lint-unsafe-code.rs:59:3 | LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,7 +158,7 @@ LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:62:7 + --> $DIR/lint-unsafe-code.rs:64:7 | LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -166,7 +166,7 @@ LL | #[export_name = "bar"] fn bar() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:66:7 + --> $DIR/lint-unsafe-code.rs:68:7 | LL | #[export_name = "bar"] fn foo() {} | ^^^^^^^^^^^^^^^^^^^ @@ -174,7 +174,7 @@ LL | #[export_name = "bar"] fn foo() {} = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:26:11 + --> $DIR/lint-unsafe-code.rs:28:11 | LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ @@ -186,7 +186,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[no_mangle]` attribute - --> $DIR/lint-unsafe-code.rs:27:11 + --> $DIR/lint-unsafe-code.rs:29:11 | LL | #[no_mangle] static FOO: u32 = 5; | ^^^^^^^^^ @@ -198,7 +198,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:28:11 + --> $DIR/lint-unsafe-code.rs:30:11 | LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ @@ -210,7 +210,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[export_name]` attribute - --> $DIR/lint-unsafe-code.rs:30:11 + --> $DIR/lint-unsafe-code.rs:32:11 | LL | #[export_name = "BAR"] static BAR: u32 = 5; | ^^^^^^^^^^^^^^^^^^^ @@ -222,7 +222,7 @@ LL | unsafe_in_macro!() = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `#[naked]` attribute - --> $DIR/lint-unsafe-code.rs:137:10 + --> $DIR/lint-unsafe-code.rs:139:10 | LL | #[unsafe(naked)] fn naked1() { naked_asm!("halt") } | ^^^^^ @@ -230,7 +230,7 @@ LL | #[unsafe(naked)] fn naked1() { naked_asm!("halt") } = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). error: usage of the unsafe `#[naked]` attribute - --> $DIR/lint-unsafe-code.rs:142:14 + --> $DIR/lint-unsafe-code.rs:144:14 | LL | #[unsafe(naked)] fn naked2() { naked_asm!("halt") } | ^^^^^ @@ -238,7 +238,7 @@ LL | #[unsafe(naked)] fn naked2() { naked_asm!("halt") } = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). error: usage of the unsafe `#[naked]` attribute - --> $DIR/lint-unsafe-code.rs:147:14 + --> $DIR/lint-unsafe-code.rs:149:14 | LL | #[unsafe(naked)] fn naked3() { naked_asm!("halt") } | ^^^^^ @@ -246,7 +246,7 @@ LL | #[unsafe(naked)] fn naked3() { naked_asm!("halt") } = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). error: usage of the unsafe `#[naked]` attribute - --> $DIR/lint-unsafe-code.rs:152:14 + --> $DIR/lint-unsafe-code.rs:154:14 | LL | #[unsafe(naked)] fn naked4() { naked_asm!("halt") } | ^^^^^ @@ -254,7 +254,7 @@ LL | #[unsafe(naked)] fn naked4() { naked_asm!("halt") } = note: the `#[naked]` attribute adds the safety obligation that the function's body must respect the function’s calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code). error: usage of the unsafe `#[ffi_pure]` attribute - --> $DIR/lint-unsafe-code.rs:157:14 + --> $DIR/lint-unsafe-code.rs:159:14 | LL | #[unsafe(ffi_pure)] | ^^^^^^^^ @@ -262,12 +262,44 @@ LL | #[unsafe(ffi_pure)] = note: `#[ffi_pure]` functions shall have no effects except for its return value, which shall not change across two consecutive function calls with the same parameters. error: usage of the unsafe `#[ffi_const]` attribute - --> $DIR/lint-unsafe-code.rs:161:14 + --> $DIR/lint-unsafe-code.rs:163:14 | LL | #[unsafe(ffi_const)] | ^^^^^^^^^ | = note: `#[ffi_const]` functions shall have no effects except for its return value, which can only depend on the values of the function parameters, and is not affected by changes to the observable state of the program. -error: aborting due to 34 previous errors +error: usage of the unsafe `#[force_target_feature]` attribute + --> $DIR/lint-unsafe-code.rs:168:10 + | +LL | #[unsafe(force_target_feature(enable = "avx2"))] fn force_target_feature() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a function with the signature of the function the attribute is applied to must only be callable if the force-enabled features are guaranteed to be present + +error: usage of the unsafe `#[force_target_feature]` attribute + --> $DIR/lint-unsafe-code.rs:173:14 + | +LL | #[unsafe(force_target_feature(enable = "avx2"))] fn force_target_feature() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a function with the signature of the function the attribute is applied to must only be callable if the force-enabled features are guaranteed to be present + +error: usage of the unsafe `#[force_target_feature]` attribute + --> $DIR/lint-unsafe-code.rs:178:14 + | +LL | #[unsafe(force_target_feature(enable = "avx2"))] fn force_target_feature() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a function with the signature of the function the attribute is applied to must only be callable if the force-enabled features are guaranteed to be present + +error: usage of the unsafe `#[force_target_feature]` attribute + --> $DIR/lint-unsafe-code.rs:182:14 + | +LL | #[unsafe(force_target_feature(enable = "avx2"))] fn force_target_feature() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a function with the signature of the function the attribute is applied to must only be callable if the force-enabled features are guaranteed to be present + +error: aborting due to 38 previous errors From 56810797ee0a2745a88cc454bfa0e807376772a3 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 18:32:31 +0200 Subject: [PATCH 13/13] Fix incremental tests --- tests/incremental/hashes/function_interfaces.rs | 4 ++-- tests/incremental/hashes/inherent_impls.rs | 8 ++++---- tests/incremental/hashes/statics.rs | 4 ++-- tests/incremental/hashes/trait_impls.rs | 14 +++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index 8e9830e0d83d4..265aa1d79206d 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -275,9 +275,9 @@ pub fn inline_never() {} pub fn no_mangle() {} #[cfg(not(any(bpass1,bpass4)))] -#[rustc_clean(cfg = "bpass2")] +#[rustc_clean(cfg = "bpass2", except="hir_owner")] // dirty because of stashed UNSAFE_CODE lint #[rustc_clean(cfg = "bpass3")] -#[rustc_clean(cfg = "bpass5")] +#[rustc_clean(cfg = "bpass5", except="hir_owner")] // dirty because of stashed UNSAFE_CODE lint #[rustc_clean(cfg = "bpass6")] #[unsafe(no_mangle)] pub fn no_mangle() {} diff --git a/tests/incremental/hashes/inherent_impls.rs b/tests/incremental/hashes/inherent_impls.rs index edda93ec55127..a403894c6f979 100644 --- a/tests/incremental/hashes/inherent_impls.rs +++ b/tests/incremental/hashes/inherent_impls.rs @@ -645,9 +645,9 @@ impl Foo { // Add #[no_mangle] to Method -------------------------------------------------- #[cfg(any(bpass1,bpass4))] impl Foo { + //------------------------------------------------------------------------------------------- //-------------------------- - //-------------------------- - //-------------------------- + //------------------------------------------------------------------------------------------- //-------------------------- //------------------ pub fn add_no_mangle_to_method(&self) { } @@ -659,9 +659,9 @@ impl Foo { #[rustc_clean(cfg="bpass5")] #[rustc_clean(cfg="bpass6")] impl Foo { - #[rustc_clean(cfg="bpass2")] + #[rustc_clean(cfg="bpass2", except="hir_owner")] // dirty because of stashed UNSAFE_CODE lint #[rustc_clean(cfg="bpass3")] - #[rustc_clean(cfg="bpass5")] + #[rustc_clean(cfg="bpass5", except="hir_owner")] // dirty because of stashed UNSAFE_CODE lint #[rustc_clean(cfg="bpass6")] #[unsafe(no_mangle)] pub fn add_no_mangle_to_method(&self) { } diff --git a/tests/incremental/hashes/statics.rs b/tests/incremental/hashes/statics.rs index eccf59907c622..d72ab503ed881 100644 --- a/tests/incremental/hashes/statics.rs +++ b/tests/incremental/hashes/statics.rs @@ -62,9 +62,9 @@ static STATIC_LINKAGE: u8 = 0; static STATIC_NO_MANGLE: u8 = 0; #[cfg(not(any(bpass1,bpass4)))] -#[rustc_clean(cfg="bpass2")] +#[rustc_clean(cfg="bpass2", except="hir_owner")] // dirty because of stashed UNSAFE_CODE lint #[rustc_clean(cfg="bpass3")] -#[rustc_clean(cfg="bpass5")] +#[rustc_clean(cfg="bpass5", except="hir_owner")] // dirty because of stashed UNSAFE_CODE lint #[rustc_clean(cfg="bpass6")] #[unsafe(no_mangle)] static STATIC_NO_MANGLE: u8 = 0; diff --git a/tests/incremental/hashes/trait_impls.rs b/tests/incremental/hashes/trait_impls.rs index b4a72feb700f1..9fafba46a0d21 100644 --- a/tests/incremental/hashes/trait_impls.rs +++ b/tests/incremental/hashes/trait_impls.rs @@ -565,11 +565,11 @@ trait AddNoMangleToMethod { #[cfg(any(bpass1,bpass4))] impl AddNoMangleToMethod for Foo { - // ------------------------- - // ------------------------- - // ------------------------- - // ------------------------- - // ----------------- + //------------------------------------------------------------------------------------------- + //-------------------------- + //------------------------------------------------------------------------------------------- + //-------------------------- + //------------------ fn add_no_mangle_to_method(&self) { } } @@ -579,9 +579,9 @@ impl AddNoMangleToMethod for Foo { #[rustc_clean(cfg="bpass5")] #[rustc_clean(cfg="bpass6")] impl AddNoMangleToMethod for Foo { - #[rustc_clean(cfg="bpass2")] + #[rustc_clean(cfg="bpass2", except="hir_owner")] // dirty because of stashed UNSAFE_CODE lint #[rustc_clean(cfg="bpass3")] - #[rustc_clean(cfg="bpass5")] + #[rustc_clean(cfg="bpass5", except="hir_owner")] // dirty because of stashed UNSAFE_CODE lint #[rustc_clean(cfg="bpass6")] #[unsafe(no_mangle)] fn add_no_mangle_to_method(&self) { }