Skip to content

Commit 92f2402

Browse files
committed
port #[recursion_limit] to the new attribute parsing infrastructure
1 parent a78f9aa commit 92f2402

File tree

9 files changed

+84
-4
lines changed

9 files changed

+84
-4
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,7 @@ attr_parsing_raw_dylib_only_windows =
247247
248248
attr_parsing_whole_archive_needs_static =
249249
linking modifier `whole-archive` is only compatible with `static` linking kind
250+
251+
attr_parsing_limit_invalid =
252+
`limit` must be a non-negative integer
253+
.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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// templates
22
#[doc(hidden)]
3-
pub(super) use rustc_feature::{AttributeTemplate, template};
3+
pub(super) use rustc_feature::{AttributeTemplate, AttributeType, template};
44
// data structures
55
#[doc(hidden)]
66
pub(super) use rustc_hir::attrs::AttributeKind;

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};
@@ -185,6 +185,7 @@ attribute_parsers!(
185185
Single<OptimizeParser>,
186186
Single<PathAttributeParser>,
187187
Single<ProcMacroDeriveParser>,
188+
Single<RecursionLimitParser>,
188189
Single<RustcBuiltinMacroParser>,
189190
Single<RustcForceInlineParser>,
190191
Single<RustcLayoutScalarValidRangeEnd>,

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,3 +930,13 @@ pub(crate) struct ImportNameTypeRaw {
930930
#[primary_span]
931931
pub span: Span,
932932
}
933+
934+
#[derive(Diagnostic)]
935+
#[diag(attr_parsing_limit_invalid)]
936+
pub(crate) struct LimitInvalid<'a> {
937+
#[primary_span]
938+
pub span: Span,
939+
#[label]
940+
pub value_span: Span,
941+
pub error_str: &'a str,
942+
}

compiler/rustc_hir/src/attrs/data_structures.rs

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

614+
/// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute)
615+
RecursionLimit { attr_span: Span, limit_span: Span, limit: usize },
616+
614617
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
615618
Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
616619

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ impl AttributeKind {
7575
ProcMacroAttribute(..) => No,
7676
ProcMacroDerive { .. } => No,
7777
PubTransparent(..) => Yes,
78+
RecursionLimit { .. } => No,
7879
Repr { .. } => No,
7980
RustcBuiltinMacro { .. } => Yes,
8081
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
@@ -270,6 +270,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
270270
| AttributeKind::Linkage(..)
271271
| AttributeKind::MustUse { .. }
272272
| AttributeKind::CrateName { .. }
273+
| AttributeKind::RecursionLimit { .. }
273274
) => { /* do nothing */ }
274275
Attribute::Unparsed(attr_item) => {
275276
style = Some(attr_item.style);

0 commit comments

Comments
 (0)