about summary refs log tree commit diff
path: root/compiler/rustc_attr_parsing/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_attr_parsing/src')
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/crate_level.rs172
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/prelude.rs5
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/repr.rs27
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs27
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs10
6 files changed, 229 insertions, 13 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index ffdacff7152..d5d51f2e79a 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -218,6 +218,7 @@ impl<S: Stage> AttributeParser<S> for NakedParser {
             sym::rustc_std_internal_symbol,
             // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
             sym::rustc_align,
+            sym::rustc_align_static,
             // obviously compatible with self
             sym::naked,
             // documentation
diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
index 2fed09b85e8..0b2c05482bf 100644
--- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
@@ -1,6 +1,40 @@
-use rustc_feature::AttributeType;
+use std::num::IntErrorKind;
+
+use rustc_hir::limit::Limit;
 
 use super::prelude::*;
+use crate::session_diagnostics::LimitInvalid;
+
+impl<S: Stage> AcceptContext<'_, '_, S> {
+    fn parse_limit_int(&self, nv: &NameValueParser) -> Option<Limit> {
+        let Some(limit) = nv.value_as_str() else {
+            self.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
+            return None;
+        };
+
+        let error_str = match limit.as_str().parse() {
+            Ok(i) => return Some(Limit::new(i)),
+            Err(e) => match e.kind() {
+                IntErrorKind::PosOverflow => "`limit` is too large",
+                IntErrorKind::Empty => "`limit` must be a non-negative integer",
+                IntErrorKind::InvalidDigit => "not a valid integer",
+                IntErrorKind::NegOverflow => {
+                    panic!(
+                        "`limit` should never negatively overflow since we're parsing into a usize and we'd get Empty instead"
+                    )
+                }
+                IntErrorKind::Zero => {
+                    panic!("zero is a valid `limit` so should have returned Ok() when parsing")
+                }
+                kind => panic!("unimplemented IntErrorKind variant: {:?}", kind),
+            },
+        };
+
+        self.emit_err(LimitInvalid { span: self.attr_span, value_span: nv.value_span, error_str });
+
+        None
+    }
+}
 
 pub(crate) struct CrateNameParser;
 
@@ -11,8 +45,8 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
     const TYPE: AttributeType = AttributeType::CrateLevel;
 
-    // FIXME: crate name is allowed on all targets and ignored,
-    //        even though it should only be valid on crates of course
+    // because it's a crate-level attribute, we already warn about it.
+    // Putting target limitations here would give duplicate warnings
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
@@ -34,3 +68,135 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
         })
     }
 }
+
+pub(crate) struct RecursionLimitParser;
+
+impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
+    const PATH: &[Symbol] = &[sym::recursion_limit];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
+    const TYPE: AttributeType = AttributeType::CrateLevel;
+
+    // because it's a crate-level attribute, we already warn about it.
+    // Putting target limitations here would give duplicate warnings
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let ArgParser::NameValue(nv) = args else {
+            cx.expected_name_value(cx.attr_span, None);
+            return None;
+        };
+
+        Some(AttributeKind::RecursionLimit {
+            limit: cx.parse_limit_int(nv)?,
+            attr_span: cx.attr_span,
+            limit_span: nv.value_span,
+        })
+    }
+}
+
+pub(crate) struct MoveSizeLimitParser;
+
+impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
+    const PATH: &[Symbol] = &[sym::move_size_limit];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
+    const TYPE: AttributeType = AttributeType::CrateLevel;
+
+    // because it's a crate-level attribute, we already warn about it.
+    // Putting target limitations here would give duplicate warnings
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let ArgParser::NameValue(nv) = args else {
+            cx.expected_name_value(cx.attr_span, None);
+            return None;
+        };
+
+        Some(AttributeKind::MoveSizeLimit {
+            limit: cx.parse_limit_int(nv)?,
+            attr_span: cx.attr_span,
+            limit_span: nv.value_span,
+        })
+    }
+}
+
+pub(crate) struct TypeLengthLimitParser;
+
+impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
+    const PATH: &[Symbol] = &[sym::type_length_limit];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
+    const TYPE: AttributeType = AttributeType::CrateLevel;
+
+    // because it's a crate-level attribute, we already warn about it.
+    // Putting target limitations here would give duplicate warnings
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let ArgParser::NameValue(nv) = args else {
+            cx.expected_name_value(cx.attr_span, None);
+            return None;
+        };
+
+        Some(AttributeKind::TypeLengthLimit {
+            limit: cx.parse_limit_int(nv)?,
+            attr_span: cx.attr_span,
+            limit_span: nv.value_span,
+        })
+    }
+}
+
+pub(crate) struct PatternComplexityLimitParser;
+
+impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
+    const PATH: &[Symbol] = &[sym::pattern_complexity_limit];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
+    const TYPE: AttributeType = AttributeType::CrateLevel;
+
+    // because it's a crate-level attribute, we already warn about it.
+    // Putting target limitations here would give duplicate warnings
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let ArgParser::NameValue(nv) = args else {
+            cx.expected_name_value(cx.attr_span, None);
+            return None;
+        };
+
+        Some(AttributeKind::PatternComplexityLimit {
+            limit: cx.parse_limit_int(nv)?,
+            attr_span: cx.attr_span,
+            limit_span: nv.value_span,
+        })
+    }
+}
+
+pub(crate) struct NoCoreParser;
+
+impl<S: Stage> NoArgsAttributeParser<S> for NoCoreParser {
+    const PATH: &[Symbol] = &[sym::no_core];
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    // because it's a crate-level attribute, we already warn about it.
+    // Putting target limitations here would give duplicate warnings
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+    const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore;
+    const TYPE: AttributeType = AttributeType::CrateLevel;
+}
+
+pub(crate) struct NoStdParser;
+
+impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
+    const PATH: &[Symbol] = &[sym::no_std];
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    // because it's a crate-level attribute, we already warn about it.
+    // Putting target limitations here would give duplicate warnings
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+    const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
+    const TYPE: AttributeType = AttributeType::CrateLevel;
+}
diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
index 6aef7e7a67b..8f040ffb9d4 100644
--- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
@@ -1,8 +1,7 @@
-// templates
-#[doc(hidden)]
-pub(super) use rustc_feature::{AttributeTemplate, template};
 // data structures
 #[doc(hidden)]
+pub(super) use rustc_feature::{AttributeTemplate, AttributeType, template};
+#[doc(hidden)]
 pub(super) use rustc_hir::attrs::AttributeKind;
 #[doc(hidden)]
 pub(super) use rustc_hir::lints::AttributeLintKind;
diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs
index 23aabd15597..0330e2515c7 100644
--- a/compiler/rustc_attr_parsing/src/attributes/repr.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs
@@ -331,3 +331,30 @@ impl<S: Stage> AttributeParser<S> for AlignParser {
         Some(AttributeKind::Align { align, span })
     }
 }
+
+#[derive(Default)]
+pub(crate) struct AlignStaticParser(AlignParser);
+
+impl AlignStaticParser {
+    const PATH: &'static [Symbol] = &[sym::rustc_align_static];
+    const TEMPLATE: AttributeTemplate = AlignParser::TEMPLATE;
+
+    fn parse<'c, S: Stage>(
+        &mut self,
+        cx: &'c mut AcceptContext<'_, '_, S>,
+        args: &'c ArgParser<'_>,
+    ) {
+        self.0.parse(cx, args)
+    }
+}
+
+impl<S: Stage> AttributeParser<S> for AlignStaticParser {
+    const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)];
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]);
+
+    fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
+        let (align, span) = self.0.0?;
+        Some(AttributeKind::Align { align, span })
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 7f5b810f244..b3ab1d3edd6 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -24,7 +24,10 @@ use crate::attributes::codegen_attrs::{
     UsedParser,
 };
 use crate::attributes::confusables::ConfusablesParser;
-use crate::attributes::crate_level::CrateNameParser;
+use crate::attributes::crate_level::{
+    CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
+    RecursionLimitParser, TypeLengthLimitParser,
+};
 use crate::attributes::deprecation::DeprecationParser;
 use crate::attributes::dummy::DummyParser;
 use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
@@ -47,7 +50,7 @@ use crate::attributes::proc_macro_attrs::{
     ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
 };
 use crate::attributes::prototype::CustomMirParser;
-use crate::attributes::repr::{AlignParser, ReprParser};
+use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
 use crate::attributes::rustc_internal::{
     RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
     RustcObjectLifetimeDefaultParser,
@@ -149,6 +152,7 @@ attribute_parsers!(
     pub(crate) static ATTRIBUTE_PARSERS = [
         // tidy-alphabetical-start
         AlignParser,
+        AlignStaticParser,
         BodyStabilityParser,
         ConfusablesParser,
         ConstStabilityParser,
@@ -181,10 +185,13 @@ attribute_parsers!(
         Single<LinkOrdinalParser>,
         Single<LinkSectionParser>,
         Single<LinkageParser>,
+        Single<MoveSizeLimitParser>,
         Single<MustUseParser>,
         Single<OptimizeParser>,
         Single<PathAttributeParser>,
+        Single<PatternComplexityLimitParser>,
         Single<ProcMacroDeriveParser>,
+        Single<RecursionLimitParser>,
         Single<RustcBuiltinMacroParser>,
         Single<RustcForceInlineParser>,
         Single<RustcLayoutScalarValidRangeEnd>,
@@ -194,6 +201,7 @@ attribute_parsers!(
         Single<ShouldPanicParser>,
         Single<SkipDuringMethodDispatchParser>,
         Single<TransparencyParser>,
+        Single<TypeLengthLimitParser>,
         Single<WithoutArgs<AllowIncoherentImplParser>>,
         Single<WithoutArgs<AllowInternalUnsafeParser>>,
         Single<WithoutArgs<AsPtrParser>>,
@@ -215,8 +223,10 @@ attribute_parsers!(
         Single<WithoutArgs<MacroEscapeParser>>,
         Single<WithoutArgs<MarkerParser>>,
         Single<WithoutArgs<MayDangleParser>>,
+        Single<WithoutArgs<NoCoreParser>>,
         Single<WithoutArgs<NoImplicitPreludeParser>>,
         Single<WithoutArgs<NoMangleParser>>,
+        Single<WithoutArgs<NoStdParser>>,
         Single<WithoutArgs<NonExhaustiveParser>>,
         Single<WithoutArgs<ParenSugarParser>>,
         Single<WithoutArgs<PassByValueParser>>,
@@ -346,7 +356,10 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
     /// must be delayed until after HIR is built. This method will take care of the details of
     /// that.
     pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
-        if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
+        if !matches!(
+            self.stage.should_emit(),
+            ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
+        ) {
             return;
         }
         let id = self.target_id;
@@ -670,20 +683,20 @@ pub enum ShouldEmit {
     ///
     /// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`.
     /// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible.
-    EarlyFatal,
+    EarlyFatal { also_emit_lints: bool },
     /// The operation will emit errors and lints.
     /// This is usually what you need.
     ErrorsAndLints,
     /// The operation will emit *not* errors and lints.
-    /// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::Emit`.
+    /// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::ErrorsAndLints`.
     Nothing,
 }
 
 impl ShouldEmit {
     pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
         match self {
-            ShouldEmit::EarlyFatal if diag.level() == Level::DelayedBug => diag.emit(),
-            ShouldEmit::EarlyFatal => diag.upgrade_to_fatal().emit(),
+            ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),
+            ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),
             ShouldEmit::ErrorsAndLints => diag.emit(),
             ShouldEmit::Nothing => diag.delay_as_bug(),
         }
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index a9dee23bf6a..32ea9005a97 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -930,3 +930,13 @@ pub(crate) struct ImportNameTypeRaw {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_limit_invalid)]
+pub(crate) struct LimitInvalid<'a> {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub value_span: Span,
+    pub error_str: &'a str,
+}