diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index e59f70877c948..c68c66b271857 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -690,6 +690,16 @@ impl SingleAttributeParser for SanitizeParser { } } +pub(crate) struct ThreadLocalParser; + +impl NoArgsAttributeParser for ThreadLocalParser { + const PATH: &[Symbol] = &[sym::thread_local]; + const ON_DUPLICATE: OnDuplicate = 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 NoArgsAttributeParser for RustcPassIndirectlyInNonRusticAbisParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index a752869c2eb27..df4970d8aa90c 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -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>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 473598bad3947..8135fd43dd93f 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -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) } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 1a382d8f124b6..e9f9b2445deb8 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -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), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 7c1e71f258bee..68456dfe4c293 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -114,6 +114,7 @@ impl AttributeKind { Stability { .. } => Yes, StdInternalSymbol(..) => No, TargetFeature { .. } => No, + ThreadLocal => No, TrackCaller(..) => Yes, TypeConst(..) => Yes, TypeLengthLimit { .. } => No, diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index abfd078f7462d..af8ff5643f2c6 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -251,9 +251,7 @@ impl<'a> MissingNativeLibrary<'a> { // if it looks like the user has provided a complete filename rather just the bare lib name, // then provide a note that they might want to try trimming the name let suggested_name = if !verbatim { - if let Some(libname) = libname.strip_prefix("lib") - && let Some(libname) = libname.strip_suffix(".a") - { + if let Some(libname) = libname.strip_circumfix("lib", ".a") { // this is a unix style filename so trim prefix & suffix Some(libname) } else if let Some(libname) = libname.strip_suffix(".lib") { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index f31c4938e118a..f3b738f93d2d7 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -10,6 +10,7 @@ #![feature(never_type)] #![feature(proc_macro_internals)] #![feature(result_option_map_or_default)] +#![feature(strip_circumfix)] #![feature(trusted_len)] // tidy-alphabetical-end diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index c0106ea0c6276..cf069b364be8a 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -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 diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 945dcec798e3a..7822614a05cb1 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -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 => { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 4f97f74c78047..2b817c6dd106e 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -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> { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 32be23eed7658..4de3ba3e2781d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1758,8 +1758,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // specify a byte literal (ty::Uint(ty::UintTy::U8), ty::Char) => { if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) - && let Some(code) = - code.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) + && let Some(code) = code.strip_circumfix('\'', '\'') // forbid all Unicode escapes && !code.starts_with("\\u") // forbids literal Unicode characters beyond ASCII @@ -1776,7 +1775,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // specify a character literal (issue #92479) (ty::Char, ty::Ref(_, r, _)) if r.is_str() => { if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) - && let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"')) + && let Some(code) = code.strip_circumfix('"', '"') && code.chars().count() == 1 { suggestions.push(TypeErrorAdditionalDiags::MeantCharLiteral { diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 0184b2ccde784..6705d271bc7d9 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -22,6 +22,7 @@ #![feature(iter_intersperse)] #![feature(iterator_try_reduce)] #![feature(never_type)] +#![feature(strip_circumfix)] #![feature(try_blocks)] #![feature(unwrap_infallible)] #![feature(yeet_expr)] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 228ea12cba8be..d0e5cb631c1ea 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -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 | diff --git a/tests/ui/thread-local/non-static.rs b/tests/ui/thread-local/non-static.rs index f1c4273870bff..f14ff20f449b6 100644 --- a/tests/ui/thread-local/non-static.rs +++ b/tests/ui/thread-local/non-static.rs @@ -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, } diff --git a/tests/ui/thread-local/non-static.stderr b/tests/ui/thread-local/non-static.stderr index 09a1618d6e710..c83a6beb4c6ad 100644 --- a/tests/ui/thread-local/non-static.stderr +++ b/tests/ui/thread-local/non-static.stderr @@ -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