rustc_attr_parsing/attributes/
crate_level.rs1use std::num::IntErrorKind;
2
3use rustc_hir::limit::Limit;
4
5use super::prelude::*;
6use crate::session_diagnostics::LimitInvalid;
7
8impl<S: Stage> AcceptContext<'_, '_, S> {
9 fn parse_limit_int(&self, nv: &NameValueParser) -> Option<Limit> {
10 let Some(limit) = nv.value_as_str() else {
11 self.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
12 return None;
13 };
14
15 let error_str = match limit.as_str().parse() {
16 Ok(i) => return Some(Limit::new(i)),
17 Err(e) => match e.kind() {
18 IntErrorKind::PosOverflow => "`limit` is too large",
19 IntErrorKind::Empty => "`limit` must be a non-negative integer",
20 IntErrorKind::InvalidDigit => "not a valid integer",
21 IntErrorKind::NegOverflow => {
22 panic!(
23 "`limit` should never negatively overflow since we're parsing into a usize and we'd get Empty instead"
24 )
25 }
26 IntErrorKind::Zero => {
27 panic!("zero is a valid `limit` so should have returned Ok() when parsing")
28 }
29 kind => panic!("unimplemented IntErrorKind variant: {:?}", kind),
30 },
31 };
32
33 self.emit_err(LimitInvalid { span: self.attr_span, value_span: nv.value_span, error_str });
34
35 None
36 }
37}
38
39pub(crate) struct CrateNameParser;
40
41impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
42 const PATH: &[Symbol] = &[sym::crate_name];
43 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
44 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
45 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
46 const TYPE: AttributeType = AttributeType::CrateLevel;
47
48 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
51
52 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
53 let ArgParser::NameValue(n) = args else {
54 cx.expected_name_value(cx.attr_span, None);
55 return None;
56 };
57
58 let Some(name) = n.value_as_str() else {
59 cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
60 return None;
61 };
62
63 Some(AttributeKind::CrateName {
64 name,
65 name_span: n.value_span,
66 attr_span: cx.attr_span,
67 style: cx.attr_style,
68 })
69 }
70}
71
72pub(crate) struct RecursionLimitParser;
73
74impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
75 const PATH: &[Symbol] = &[sym::recursion_limit];
76 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
77 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
78 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
79 const TYPE: AttributeType = AttributeType::CrateLevel;
80
81 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
84
85 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
86 let ArgParser::NameValue(nv) = args else {
87 cx.expected_name_value(cx.attr_span, None);
88 return None;
89 };
90
91 Some(AttributeKind::RecursionLimit {
92 limit: cx.parse_limit_int(nv)?,
93 attr_span: cx.attr_span,
94 limit_span: nv.value_span,
95 })
96 }
97}
98
99pub(crate) struct MoveSizeLimitParser;
100
101impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
102 const PATH: &[Symbol] = &[sym::move_size_limit];
103 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
104 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
105 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
106 const TYPE: AttributeType = AttributeType::CrateLevel;
107
108 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
111
112 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
113 let ArgParser::NameValue(nv) = args else {
114 cx.expected_name_value(cx.attr_span, None);
115 return None;
116 };
117
118 Some(AttributeKind::MoveSizeLimit {
119 limit: cx.parse_limit_int(nv)?,
120 attr_span: cx.attr_span,
121 limit_span: nv.value_span,
122 })
123 }
124}
125
126pub(crate) struct TypeLengthLimitParser;
127
128impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
129 const PATH: &[Symbol] = &[sym::type_length_limit];
130 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
131 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
132 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
133 const TYPE: AttributeType = AttributeType::CrateLevel;
134
135 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
138
139 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
140 let ArgParser::NameValue(nv) = args else {
141 cx.expected_name_value(cx.attr_span, None);
142 return None;
143 };
144
145 Some(AttributeKind::TypeLengthLimit {
146 limit: cx.parse_limit_int(nv)?,
147 attr_span: cx.attr_span,
148 limit_span: nv.value_span,
149 })
150 }
151}
152
153pub(crate) struct PatternComplexityLimitParser;
154
155impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
156 const PATH: &[Symbol] = &[sym::pattern_complexity_limit];
157 const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
158 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
159 const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
160 const TYPE: AttributeType = AttributeType::CrateLevel;
161
162 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
165
166 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
167 let ArgParser::NameValue(nv) = args else {
168 cx.expected_name_value(cx.attr_span, None);
169 return None;
170 };
171
172 Some(AttributeKind::PatternComplexityLimit {
173 limit: cx.parse_limit_int(nv)?,
174 attr_span: cx.attr_span,
175 limit_span: nv.value_span,
176 })
177 }
178}