Skip to content

Commit 96a8466

Browse files
committed
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
1 parent 42ec52b commit 96a8466

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

compiler/rustc_builtin_macros/messages.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,3 +306,9 @@ builtin_macros_unexpected_lit = expected path to a trait, found literal
306306
.other = for example, write `#[derive(Debug)]` for `Debug`
307307
308308
builtin_macros_unnameable_test_items = cannot test inner items
309+
310+
# New: Disallow simultaneous use of #[global_allocator] and #[thread_local]
311+
builtin_macros_global_allocator_thread_local_conflict =
312+
`#[global_allocator]` cannot be used with `#[thread_local]` on the same static
313+
.note = The global allocator must be a single, program-wide instance.
314+
.help = Remove either the `#[global_allocator]` or `#[thread_local]` attribute.

compiler/rustc_builtin_macros/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ pub(crate) struct AllocMustStatics {
150150
pub(crate) span: Span,
151151
}
152152

153+
/// The `#[global_allocator]` attribute cannot be used with `#[thread_local]`.
154+
#[derive(Diagnostic)]
155+
#[diag(builtin_macros_global_allocator_thread_local_conflict)]
156+
pub(crate) struct GlobalAllocatorThreadLocalConflict {
157+
#[primary_span]
158+
pub(crate) span: Span,
159+
}
160+
153161
pub(crate) use autodiff::*;
154162

155163
mod autodiff {

compiler/rustc_builtin_macros/src/global_allocator.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,15 @@ pub(crate) fn expand(
3737
ecx.dcx().emit_err(errors::AllocMustStatics { span: item.span() });
3838
return vec![orig_item];
3939
};
40-
40+
41+
// Check if the static item also has the `#[thread_local]` attribute, which is incompatible with `#[global_allocator]`.
42+
if item.attrs.iter().any(|a| a.path().is_ident(sym::thread_local)) {
43+
ecx.dcx().emit_err(errors::GlobalAllocatorThreadLocalConflict {
44+
span: item.span,
45+
});
46+
return vec![orig_item];
47+
}
48+
4149
// Generate a bunch of new items using the AllocFnFactory
4250
let span = ecx.with_def_site_ctxt(item.span);
4351
let f = AllocFnFactory { span, ty_span, global: ident, cx: ecx };

0 commit comments

Comments
 (0)