Skip to content

Commit abea43c

Browse files
committed
port #[recursion_limit] to the new attribute parsing infrastructure
1 parent 93edf9f commit abea43c

File tree

8 files changed

+83
-2
lines changed

8 files changed

+83
-2
lines changed

compiler/rustc_attr_parsing/messages.ftl

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

compiler/rustc_attr_parsing/src/attributes/crate_level.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
1+
use std::num::IntErrorKind;
2+
3+
use crate::session_diagnostics::LimitInvalid;
4+
15
use super::prelude::*;
26

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+
338
pub(crate) struct CrateNameParser;
439

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

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};
@@ -182,6 +182,7 @@ attribute_parsers!(
182182
Single<OptimizeParser>,
183183
Single<PathAttributeParser>,
184184
Single<ProcMacroDeriveParser>,
185+
Single<RecursionLimitParser>,
185186
Single<RustcBuiltinMacroParser>,
186187
Single<RustcForceInlineParser>,
187188
Single<RustcLayoutScalarValidRangeEnd>,

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,3 +826,13 @@ pub(crate) struct SuffixedLiteralInAttribute {
826826
#[primary_span]
827827
pub span: Span,
828828
}
829+
830+
#[derive(Diagnostic)]
831+
#[diag(attr_parsing_limit_invalid)]
832+
pub(crate) struct LimitInvalid<'a> {
833+
#[primary_span]
834+
pub span: Span,
835+
#[label]
836+
pub value_span: Span,
837+
pub error_str: &'a str,
838+
}

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)