From 96a8466a5f93f8fd795007acbc7c4e91c3816310 Mon Sep 17 00:00:00 2001 From: zhiping <18238287433@163.com> Date: Tue, 25 Nov 2025 10:06:03 +0800 Subject: [PATCH] fix: Disallow #[global_allocator] with #[thread_local] This change adds a check in the #[global_allocator] macro to prevent simultaneous use with #[thread_local], which is logically incompatible. The global allocator must be a single instance across all threads. Fixes #85517 --- compiler/rustc_builtin_macros/messages.ftl | 6 ++++++ compiler/rustc_builtin_macros/src/errors.rs | 8 ++++++++ compiler/rustc_builtin_macros/src/global_allocator.rs | 10 +++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index c9dd92ff2f243..ee3a2ae510fad 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -306,3 +306,9 @@ builtin_macros_unexpected_lit = expected path to a trait, found literal .other = for example, write `#[derive(Debug)]` for `Debug` builtin_macros_unnameable_test_items = cannot test inner items + +# New: Disallow simultaneous use of #[global_allocator] and #[thread_local] +builtin_macros_global_allocator_thread_local_conflict = + `#[global_allocator]` cannot be used with `#[thread_local]` on the same static + .note = The global allocator must be a single, program-wide instance. + .help = Remove either the `#[global_allocator]` or `#[thread_local]` attribute. diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index dd6a5a20ccebc..db0f419e3a576 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -150,6 +150,14 @@ pub(crate) struct AllocMustStatics { pub(crate) span: Span, } +/// The `#[global_allocator]` attribute cannot be used with `#[thread_local]`. +#[derive(Diagnostic)] +#[diag(builtin_macros_global_allocator_thread_local_conflict)] +pub(crate) struct GlobalAllocatorThreadLocalConflict { + #[primary_span] + pub(crate) span: Span, +} + pub(crate) use autodiff::*; mod autodiff { diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index e69f0838f22e9..24bdf0b30e1e6 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -37,7 +37,15 @@ pub(crate) fn expand( ecx.dcx().emit_err(errors::AllocMustStatics { span: item.span() }); return vec![orig_item]; }; - + + // Check if the static item also has the `#[thread_local]` attribute, which is incompatible with `#[global_allocator]`. + if item.attrs.iter().any(|a| a.path().is_ident(sym::thread_local)) { + ecx.dcx().emit_err(errors::GlobalAllocatorThreadLocalConflict { + span: item.span, + }); + return vec![orig_item]; + } + // Generate a bunch of new items using the AllocFnFactory let span = ecx.with_def_site_ctxt(item.span); let f = AllocFnFactory { span, ty_span, global: ident, cx: ecx };