Skip to content

Commit 762ccfb

Browse files
committed
port #[recursion_limit] to the new attribute parsing infrastructure
1 parent b2dd217 commit 762ccfb

File tree

9 files changed

+84
-3
lines changed

9 files changed

+84
-3
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,7 @@ attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`
195195
196196
attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
197197
.help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
198+
199+
attr_parsing_limit_invalid =
200+
`limit` must be a non-negative integer
201+
.label = {$error_str}

compiler/rustc_attr_parsing/src/attributes/crate_level.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,40 @@
1-
use rustc_feature::AttributeType;
1+
use std::num::IntErrorKind;
2+
3+
use crate::session_diagnostics::LimitInvalid;
24

35
use super::prelude::*;
46

7+
impl<S: Stage> AcceptContext<'_, '_, S> {
8+
fn parse_limit_int(&self, nv: &NameValueParser) -> Option<usize> {
9+
let Some(limit) = nv.value_as_str() else {
10+
self.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
11+
return None;
12+
};
13+
14+
let error_str = match limit.as_str().parse() {
15+
Ok(i) => return Some(i),
16+
Err(e) => match e.kind() {
17+
IntErrorKind::PosOverflow => "`limit` is too large",
18+
IntErrorKind::Empty => "`limit` must be a non-negative integer",
19+
IntErrorKind::InvalidDigit => "not a valid integer",
20+
IntErrorKind::NegOverflow => {
21+
panic!(
22+
"`limit` should never negatively overflow since we're parsing into a usize and we'd get Empty instead"
23+
)
24+
}
25+
IntErrorKind::Zero => {
26+
panic!("zero is a valid `limit` so should have returned Ok() when parsing")
27+
}
28+
kind => panic!("unimplemented IntErrorKind variant: {:?}", kind),
29+
},
30+
};
31+
32+
self.emit_err(LimitInvalid { span: self.attr_span, value_span: nv.value_span, error_str });
33+
34+
None
35+
}
36+
}
37+
538
pub(crate) struct CrateNameParser;
639

740
impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
@@ -34,3 +67,30 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
3467
})
3568
}
3669
}
70+
71+
pub(crate) struct RecursionLimitParser;
72+
73+
impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
74+
const PATH: &[Symbol] = &[sym::recursion_limit];
75+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
76+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
77+
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
78+
const TYPE: AttributeType = AttributeType::CrateLevel;
79+
80+
// FIXME: recursion limit is allowed on all targets and ignored,
81+
// even though it should only be valid on crates of course
82+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
83+
84+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
85+
let ArgParser::NameValue(nv) = args else {
86+
cx.expected_name_value(cx.attr_span, None);
87+
return None;
88+
};
89+
90+
Some(AttributeKind::RecursionLimit {
91+
limit: cx.parse_limit_int(nv)?,
92+
attr_span: cx.attr_span,
93+
limit_span: nv.value_span,
94+
})
95+
}
96+
}

compiler/rustc_attr_parsing/src/attributes/prelude.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// templates
33
pub(super) use rustc_feature::{AttributeTemplate, template};
44
// data structures
5+
pub(super) use rustc_feature::AttributeType;
56
pub(super) use rustc_hir::attrs::AttributeKind;
67
pub(super) use rustc_hir::lints::AttributeLintKind;
78
pub(super) use rustc_hir::{MethodKind, Target};

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::attributes::codegen_attrs::{
2424
UsedParser,
2525
};
2626
use crate::attributes::confusables::ConfusablesParser;
27-
use crate::attributes::crate_level::CrateNameParser;
27+
use crate::attributes::crate_level::{CrateNameParser, RecursionLimitParser};
2828
use crate::attributes::deprecation::DeprecationParser;
2929
use crate::attributes::dummy::DummyParser;
3030
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
@@ -184,6 +184,7 @@ attribute_parsers!(
184184
Single<OptimizeParser>,
185185
Single<PathAttributeParser>,
186186
Single<ProcMacroDeriveParser>,
187+
Single<RecursionLimitParser>,
187188
Single<RustcBuiltinMacroParser>,
188189
Single<RustcForceInlineParser>,
189190
Single<RustcLayoutScalarValidRangeEnd>,

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,3 +836,13 @@ pub(crate) struct InvalidAttrStyle {
836836
pub target_span: Option<Span>,
837837
pub target: Target,
838838
}
839+
840+
#[derive(Diagnostic)]
841+
#[diag(attr_parsing_limit_invalid)]
842+
pub(crate) struct LimitInvalid<'a> {
843+
#[primary_span]
844+
pub span: Span,
845+
#[label]
846+
pub value_span: Span,
847+
pub error_str: &'a str,
848+
}

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,9 @@ pub enum AttributeKind {
494494
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
495495
PubTransparent(Span),
496496

497+
/// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute)
498+
RecursionLimit { attr_span: Span, limit_span: Span, limit: usize },
499+
497500
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
498501
Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
499502

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ impl AttributeKind {
7474
ProcMacroAttribute(..) => No,
7575
ProcMacroDerive { .. } => No,
7676
PubTransparent(..) => Yes,
77+
RecursionLimit { .. } => No,
7778
Repr { .. } => No,
7879
RustcBuiltinMacro { .. } => Yes,
7980
RustcLayoutScalarValidRangeEnd(..) => Yes,

compiler/rustc_hir/src/attrs/pretty_printing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ macro_rules! print_tup {
146146

147147
print_tup!(A B C D E F G H);
148148
print_skip!(Span, (), ErrorGuaranteed);
149-
print_disp!(u16, bool, NonZero<u32>);
149+
print_disp!(u16, bool, NonZero<u32>, usize);
150150
print_debug!(
151151
Symbol,
152152
Ident,

compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
252252
| AttributeKind::Linkage(..)
253253
| AttributeKind::MustUse { .. }
254254
| AttributeKind::CrateName { .. }
255+
| AttributeKind::RecursionLimit { .. }
255256
) => { /* do nothing */ }
256257
Attribute::Unparsed(attr_item) => {
257258
style = Some(attr_item.style);

0 commit comments

Comments
 (0)