From 7f2e9665fb4b73df6b49d30a663fd59e29983cc2 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:37:48 +0200 Subject: [PATCH 1/6] 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 2c7ccfb25ae9b..427d78df5c91c 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 8ddaf7a630d31..4eee828d72008 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -5586,3 +5586,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 b3b275eb4b8b81bf6cd351dbd44b679ff616fda3 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:38:52 +0200 Subject: [PATCH 2/6] 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 +- compiler/rustc_attr_parsing/src/errors.rs | 9 + 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, 160 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 41abb4806567f..000a010af7326 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -103,7 +103,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), @@ -338,7 +341,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 ec084a9fba09c..7b40cd637c537 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -486,7 +486,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 ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ Allow(Target::Static), Allow(Target::Fn), diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 42c6828ef57b7..6098bf019c24e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -224,7 +224,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/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs index 56f6d29778414..4e3337463fe17 100644 --- a/compiler/rustc_attr_parsing/src/errors.rs +++ b/compiler/rustc_attr_parsing/src/errors.rs @@ -1,4 +1,5 @@ use rustc_errors::{Applicability, DiagArgValue, MultiSpan}; +use rustc_hir::AttrPath; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; @@ -792,3 +793,11 @@ pub(crate) mod unexpected_cfg_value { Other(#[subdiagnostic] super::UnexpectedCfgCargoHelp), } } + +#[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 5f22c0a1cf88a..08b467f9df31d 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, _| { + errors::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 427d78df5c91c..775cec1242f42 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 c77e70dcbe9bb..9f77e91570a03 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 8c2ea8f19e4d198fd3d97ec5b8214999e703ef33 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:48:17 +0200 Subject: [PATCH 3/6] 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 000a010af7326..d9d664045156b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -212,7 +212,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 04976b4912d0de2560593b263abcf339a6f26504 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:46:41 +0200 Subject: [PATCH 4/6] 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 7b40cd637c537..ac18fc8b9c146 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -538,7 +538,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 CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::FfiConst; } @@ -546,7 +549,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 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 5f78f9bd27e1fcb2cf29a6422b069daac2d431ca Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 16:52:05 +0200 Subject: [PATCH 5/6] 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 d9d664045156b..4337f3df519ce 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -537,7 +537,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 d7bad7fde7352a42a654fa703716aa60ac786bea Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 31 May 2026 18:32:31 +0200 Subject: [PATCH 6/6] 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) { }