Port #[thread_local] to attribute parser

This commit is contained in:
Edvin Bryntesson 2025-12-20 15:35:52 +01:00
parent d0835adc4e
commit 120f0d4f07
No known key found for this signature in database
11 changed files with 48 additions and 58 deletions

View file

@ -690,6 +690,16 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
}
}
pub(crate) struct ThreadLocalParser;
impl<S: Stage> NoArgsAttributeParser<S> for ThreadLocalParser {
const PATH: &[Symbol] = &[sym::thread_local];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ThreadLocal;
}
pub(crate) struct RustcPassIndirectlyInNonRusticAbisParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcPassIndirectlyInNonRusticAbisParser {

View file

@ -23,7 +23,7 @@ use crate::attributes::codegen_attrs::{
ColdParser, CoverageParser, EiiExternItemParser, ExportNameParser, ForceTargetFeatureParser,
NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser, TargetFeatureParser,
TrackCallerParser, UsedParser,
ThreadLocalParser, TrackCallerParser, UsedParser,
};
use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::crate_level::{
@ -269,6 +269,7 @@ attribute_parsers!(
Single<WithoutArgs<RustcShouldNotBeCalledOnConstItems>>,
Single<WithoutArgs<SpecializationTraitParser>>,
Single<WithoutArgs<StdInternalSymbolParser>>,
Single<WithoutArgs<ThreadLocalParser>>,
Single<WithoutArgs<TrackCallerParser>>,
Single<WithoutArgs<TypeConstParser>>,
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,

View file

@ -350,6 +350,9 @@ fn process_builtin_attrs(
codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM;
}
}
AttributeKind::ThreadLocal => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL
}
_ => {}
}
}
@ -366,7 +369,6 @@ fn process_builtin_attrs(
sym::rustc_allocator_zeroed => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
}
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
sym::instruction_set => {
codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
}

View file

@ -1010,6 +1010,9 @@ pub enum AttributeKind {
/// `#[unsafe(force_target_feature(enable = "...")]`.
TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool },
/// Represents `#[thread_local]`
ThreadLocal,
/// Represents `#[track_caller]`
TrackCaller(Span),

View file

@ -114,6 +114,7 @@ impl AttributeKind {
Stability { .. } => Yes,
StdInternalSymbol(..) => No,
TargetFeature { .. } => No,
ThreadLocal => No,
TrackCaller(..) => Yes,
TypeConst(..) => Yes,
TypeLengthLimit { .. } => No,

View file

@ -484,10 +484,6 @@ passes_sanitize_attribute_not_allowed =
.no_body = function has no body
.help = sanitize attribute can be applied to a function (with body), impl block, or module
passes_should_be_applied_to_static =
attribute should be applied to a static
.label = not a static
passes_should_be_applied_to_trait =
attribute should be applied to a trait
.label = not a trait

View file

@ -297,6 +297,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::RustcPassIndirectlyInNonRusticAbis(..)
| AttributeKind::PinV2(..)
| AttributeKind::WindowsSubsystem(..)
| AttributeKind::ThreadLocal
) => { /* do nothing */ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
@ -310,7 +311,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::diagnostic, sym::on_const, ..] => {
self.check_diagnostic_on_const(attr.span(), hir_id, target, item)
}
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
[sym::rustc_clean, ..]
| [sym::rustc_dirty, ..]
| [sym::rustc_if_this_changed, ..]
@ -768,19 +768,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
/// Checks if the `#[thread_local]` attribute on `item` is valid.
fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) {
match target {
Target::ForeignStatic | Target::Static => {}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToStatic {
attr_span: attr.span(),
defn_span: span,
});
}
}
}
fn check_doc_alias_value(&self, span: Span, hir_id: HirId, target: Target, alias: Symbol) {
if let Some(location) = match target {
Target::AssocTy => {

View file

@ -98,15 +98,6 @@ pub(crate) struct AttrShouldBeAppliedToTrait {
pub defn_span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_should_be_applied_to_static)]
pub(crate) struct AttrShouldBeAppliedToStatic {
#[primary_span]
pub attr_span: Span,
#[label]
pub defn_span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_doc_alias_bad_location)]
pub(crate) struct DocAliasBadLocation<'a> {

View file

@ -141,12 +141,6 @@ LL | #[forbid(lint1, lint2, ...)]
LL | #[forbid(lint1, lint2, lint3, reason = "...")]
| +++++++++++++++++++++++++++++++++++++
error: malformed `thread_local` attribute input
--> $DIR/malformed-attrs.rs:210:1
|
LL | #[thread_local()]
| ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]`
error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
--> $DIR/malformed-attrs.rs:105:1
|
@ -618,6 +612,15 @@ LL | #[non_exhaustive = 1]
| | didn't expect any arguments here
| help: must be of the form: `#[non_exhaustive]`
error[E0565]: malformed `thread_local` attribute input
--> $DIR/malformed-attrs.rs:210:1
|
LL | #[thread_local()]
| ^^^^^^^^^^^^^^--^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[thread_local]`
error[E0565]: malformed `no_link` attribute input
--> $DIR/malformed-attrs.rs:214:1
|

View file

@ -2,19 +2,19 @@
#![feature(thread_local)]
#[thread_local]
//~^ ERROR attribute should be applied to a static
//~^ ERROR `#[thread_local]` attribute cannot be used on constants
const A: u32 = 0;
#[thread_local]
//~^ ERROR attribute should be applied to a static
//~^ ERROR `#[thread_local]` attribute cannot be used on functions
fn main() {
#[thread_local] || {};
//~^ ERROR attribute should be applied to a static
//~^ ERROR `#[thread_local]` attribute cannot be used on closures
}
struct S {
#[thread_local]
//~^ ERROR attribute should be applied to a static
//~^ ERROR `#[thread_local]` attribute cannot be used on struct fields
a: String,
b: String,
}

View file

@ -1,38 +1,34 @@
error: attribute should be applied to a static
error: `#[thread_local]` attribute cannot be used on constants
--> $DIR/non-static.rs:4:1
|
LL | #[thread_local]
| ^^^^^^^^^^^^^^^
LL |
LL | const A: u32 = 0;
| ----------------- not a static
|
= help: `#[thread_local]` can be applied to foreign statics and statics
error: attribute should be applied to a static
error: `#[thread_local]` attribute cannot be used on functions
--> $DIR/non-static.rs:8:1
|
LL | #[thread_local]
| ^^^^^^^^^^^^^^^
LL |
LL | / fn main() {
LL | | #[thread_local] || {};
LL | |
LL | | }
| |_- not a static
LL | #[thread_local]
| ^^^^^^^^^^^^^^^
|
= help: `#[thread_local]` can be applied to foreign statics and statics
error: attribute should be applied to a static
error: `#[thread_local]` attribute cannot be used on closures
--> $DIR/non-static.rs:11:5
|
LL | #[thread_local] || {};
| ^^^^^^^^^^^^^^^ ----- not a static
| ^^^^^^^^^^^^^^^
|
= help: `#[thread_local]` can be applied to foreign statics and statics
error: attribute should be applied to a static
error: `#[thread_local]` attribute cannot be used on struct fields
--> $DIR/non-static.rs:16:5
|
LL | #[thread_local]
| ^^^^^^^^^^^^^^^
LL |
LL | a: String,
| --------- not a static
|
= help: `#[thread_local]` can be applied to foreign statics and statics
error: aborting due to 4 previous errors