From 730221e654d2d017465807f16cddef4a88b72d7c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 8 Oct 2025 09:39:11 +0200 Subject: [PATCH 1/2] Fix double error for `#[no_mangle]` on closures --- .../src/attributes/codegen_attrs.rs | 1 + compiler/rustc_codegen_ssa/messages.ftl | 2 -- compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 13 ++++--------- compiler/rustc_codegen_ssa/src/errors.rs | 8 -------- tests/ui/attributes/no-mangle-closure.rs | 2 +- tests/ui/attributes/no-mangle-closure.stderr | 4 +++- 6 files changed, 9 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 7978bf28214cf..0f92968385f6f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -362,6 +362,7 @@ impl NoArgsAttributeParser for NoMangleParser { Allow(Target::Static), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::TraitImpl)), + Error(Target::Closure), ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoMangle; } diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 97ff04f66daec..e321b0773ec39 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -223,8 +223,6 @@ codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple time codegen_ssa_no_field = no field `{$name}` -codegen_ssa_no_mangle_nameless = `#[no_mangle]` cannot be used on {$definition} as it has no name - codegen_ssa_no_module_named = no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names} diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 2c7643e46ceaa..e8c8729f597b9 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -19,7 +19,6 @@ use rustc_span::{Ident, Span, sym}; use rustc_target::spec::SanitizerSet; use crate::errors; -use crate::errors::NoMangleNameless; use crate::target_features::{ check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr, }; @@ -182,14 +181,10 @@ fn process_builtin_attrs( if tcx.opt_item_name(did.to_def_id()).is_some() { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; } else { - tcx.dcx().emit_err(NoMangleNameless { - span: *attr_span, - definition: format!( - "{} {}", - tcx.def_descr_article(did.to_def_id()), - tcx.def_descr(did.to_def_id()) - ), - }); + tcx.dcx().span_delayed_bug( + *attr_span, + "no_mangle should be on a named function", + ); } } AttributeKind::Optimize(optimize, _) => codegen_fn_attrs.optimize = *optimize, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index d5c30c5c7a6b0..2dd7c6fa7c080 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1284,14 +1284,6 @@ impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_ } } -#[derive(Diagnostic)] -#[diag(codegen_ssa_no_mangle_nameless)] -pub(crate) struct NoMangleNameless { - #[primary_span] - pub span: Span, - pub definition: String, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_feature_not_valid)] pub(crate) struct FeatureNotValid<'a> { diff --git a/tests/ui/attributes/no-mangle-closure.rs b/tests/ui/attributes/no-mangle-closure.rs index c76baa27f38a0..05dcbf8e5bed7 100644 --- a/tests/ui/attributes/no-mangle-closure.rs +++ b/tests/ui/attributes/no-mangle-closure.rs @@ -7,5 +7,5 @@ pub struct S([usize; 8]); pub fn outer_function(x: S, y: S) -> usize { (#[no_mangle] || y.0[0])() - //~^ ERROR `#[no_mangle]` cannot be used on a closure as it has no name + //~^ ERROR `#[no_mangle]` attribute cannot be used on closures } diff --git a/tests/ui/attributes/no-mangle-closure.stderr b/tests/ui/attributes/no-mangle-closure.stderr index c183783493bdb..f81e65d926752 100644 --- a/tests/ui/attributes/no-mangle-closure.stderr +++ b/tests/ui/attributes/no-mangle-closure.stderr @@ -1,8 +1,10 @@ -error: `#[no_mangle]` cannot be used on a closure as it has no name +error: `#[no_mangle]` attribute cannot be used on closures --> $DIR/no-mangle-closure.rs:9:6 | LL | (#[no_mangle] || y.0[0])() | ^^^^^^^^^^^^ + | + = help: `#[no_mangle]` can be applied to functions, methods, and statics error: aborting due to 1 previous error From c050bfbf6f1c932ae955a81a0571a0fa354442fc Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 8 Oct 2025 10:10:20 +0200 Subject: [PATCH 2/2] Fix double error for `#[no_mangle]` on consts --- .../src/attributes/codegen_attrs.rs | 2 ++ .../rustc_attr_parsing/src/target_checking.rs | 17 +++++++++++++++-- tests/ui/issues/issue-45562.fixed | 2 ++ tests/ui/issues/issue-45562.rs | 2 ++ tests/ui/issues/issue-45562.stderr | 2 +- 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 0f92968385f6f..f09b02251e4d0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -6,6 +6,7 @@ use crate::session_diagnostics::{ NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral, }; +use crate::target_checking::Policy::AllowSilent; pub(crate) struct OptimizeParser; @@ -362,6 +363,7 @@ impl NoArgsAttributeParser for NoMangleParser { Allow(Target::Static), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::TraitImpl)), + AllowSilent(Target::Const), // Handled in the `InvalidNoMangleItems` pass Error(Target::Closure), ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoMangle; diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index d28f43943ba84..fabd364d3d7f8 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -31,7 +31,9 @@ impl AllowedTargets { pub(crate) fn is_allowed(&self, target: Target) -> AllowedResult { match self { AllowedTargets::AllowList(list) => { - if list.contains(&Policy::Allow(target)) { + if list.contains(&Policy::Allow(target)) + || list.contains(&Policy::AllowSilent(target)) + { AllowedResult::Allowed } else if list.contains(&Policy::Warn(target)) { AllowedResult::Warn @@ -40,7 +42,9 @@ impl AllowedTargets { } } AllowedTargets::AllowListWarnRest(list) => { - if list.contains(&Policy::Allow(target)) { + if list.contains(&Policy::Allow(target)) + || list.contains(&Policy::AllowSilent(target)) + { AllowedResult::Allowed } else if list.contains(&Policy::Error(target)) { AllowedResult::Error @@ -61,6 +65,7 @@ impl AllowedTargets { .iter() .filter_map(|target| match target { Policy::Allow(target) => Some(*target), + Policy::AllowSilent(_) => None, // Not listed in possible targets Policy::Warn(_) => None, Policy::Error(_) => None, }) @@ -68,10 +73,18 @@ impl AllowedTargets { } } +/// This policy determines what diagnostics should be emitted based on the `Target` of the attribute. #[derive(Debug, Eq, PartialEq)] pub(crate) enum Policy { + /// A target that is allowed. Allow(Target), + /// A target that is allowed and not listed in the possible targets. + /// This is useful if the target is checked elsewhere. + AllowSilent(Target), + /// Emits a FCW on this target. + /// This is useful if the target was previously allowed but should not be. Warn(Target), + /// Emits an error on this target. Error(Target), } diff --git a/tests/ui/issues/issue-45562.fixed b/tests/ui/issues/issue-45562.fixed index 8dcdd3a541ce4..529b5bd744e03 100644 --- a/tests/ui/issues/issue-45562.fixed +++ b/tests/ui/issues/issue-45562.fixed @@ -1,5 +1,7 @@ //@ run-rustfix +#![deny(unused_attributes)] + #[no_mangle] pub static RAH: usize = 5; //~^ ERROR const items should never be `#[no_mangle]` diff --git a/tests/ui/issues/issue-45562.rs b/tests/ui/issues/issue-45562.rs index 08f6c8046dce4..7c30a967c7848 100644 --- a/tests/ui/issues/issue-45562.rs +++ b/tests/ui/issues/issue-45562.rs @@ -1,5 +1,7 @@ //@ run-rustfix +#![deny(unused_attributes)] + #[no_mangle] pub const RAH: usize = 5; //~^ ERROR const items should never be `#[no_mangle]` diff --git a/tests/ui/issues/issue-45562.stderr b/tests/ui/issues/issue-45562.stderr index 6fae86f9f31ca..55d35f76a0198 100644 --- a/tests/ui/issues/issue-45562.stderr +++ b/tests/ui/issues/issue-45562.stderr @@ -1,5 +1,5 @@ error: const items should never be `#[no_mangle]` - --> $DIR/issue-45562.rs:3:14 + --> $DIR/issue-45562.rs:5:14 | LL | #[no_mangle] pub const RAH: usize = 5; | ---------^^^^^^^^^^^^^^^^