port #[recursion_limit] to the new attribute parsing infrastructure
This commit is contained in:
parent
a78f9aa87f
commit
92f2402096
9 changed files with 84 additions and 4 deletions
|
|
@ -247,3 +247,7 @@ attr_parsing_raw_dylib_only_windows =
|
|||
|
||||
attr_parsing_whole_archive_needs_static =
|
||||
linking modifier `whole-archive` is only compatible with `static` linking kind
|
||||
|
||||
attr_parsing_limit_invalid =
|
||||
`limit` must be a non-negative integer
|
||||
.label = {$error_str}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,40 @@
|
|||
use rustc_feature::AttributeType;
|
||||
use std::num::IntErrorKind;
|
||||
|
||||
use crate::session_diagnostics::LimitInvalid;
|
||||
|
||||
use super::prelude::*;
|
||||
|
||||
impl<S: Stage> AcceptContext<'_, '_, S> {
|
||||
fn parse_limit_int(&self, nv: &NameValueParser) -> Option<usize> {
|
||||
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(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;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
|
||||
|
|
@ -34,3 +67,30 @@ 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;
|
||||
|
||||
// FIXME: recursion limit is allowed on all targets and ignored,
|
||||
// even though it should only be valid on crates of course
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// templates
|
||||
#[doc(hidden)]
|
||||
pub(super) use rustc_feature::{AttributeTemplate, template};
|
||||
pub(super) use rustc_feature::{AttributeTemplate, AttributeType, template};
|
||||
// data structures
|
||||
#[doc(hidden)]
|
||||
pub(super) use rustc_hir::attrs::AttributeKind;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use crate::attributes::codegen_attrs::{
|
|||
UsedParser,
|
||||
};
|
||||
use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::crate_level::CrateNameParser;
|
||||
use crate::attributes::crate_level::{CrateNameParser, RecursionLimitParser};
|
||||
use crate::attributes::deprecation::DeprecationParser;
|
||||
use crate::attributes::dummy::DummyParser;
|
||||
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
|
||||
|
|
@ -185,6 +185,7 @@ attribute_parsers!(
|
|||
Single<OptimizeParser>,
|
||||
Single<PathAttributeParser>,
|
||||
Single<ProcMacroDeriveParser>,
|
||||
Single<RecursionLimitParser>,
|
||||
Single<RustcBuiltinMacroParser>,
|
||||
Single<RustcForceInlineParser>,
|
||||
Single<RustcLayoutScalarValidRangeEnd>,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -611,6 +611,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
|
||||
PubTransparent(Span),
|
||||
|
||||
/// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute)
|
||||
RecursionLimit { attr_span: Span, limit_span: Span, limit: usize },
|
||||
|
||||
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
|
||||
Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ impl AttributeKind {
|
|||
ProcMacroAttribute(..) => No,
|
||||
ProcMacroDerive { .. } => No,
|
||||
PubTransparent(..) => Yes,
|
||||
RecursionLimit { .. } => No,
|
||||
Repr { .. } => No,
|
||||
RustcBuiltinMacro { .. } => Yes,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ macro_rules! print_tup {
|
|||
|
||||
print_tup!(A B C D E F G H);
|
||||
print_skip!(Span, (), ErrorGuaranteed);
|
||||
print_disp!(u16, bool, NonZero<u32>);
|
||||
print_disp!(u16, bool, NonZero<u32>, usize);
|
||||
print_debug!(
|
||||
Symbol,
|
||||
Ident,
|
||||
|
|
|
|||
|
|
@ -270,6 +270,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::Linkage(..)
|
||||
| AttributeKind::MustUse { .. }
|
||||
| AttributeKind::CrateName { .. }
|
||||
| AttributeKind::RecursionLimit { .. }
|
||||
) => { /* do nothing */ }
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue