Skip to main content

rustc_attr_parsing/attributes/
crate_level.rs

1use rustc_hir::attrs::{CrateType, WindowsSubsystemKind};
2use rustc_hir::lints::AttributeLintKind;
3use rustc_session::lint::builtin::UNKNOWN_CRATE_TYPES;
4use rustc_span::Symbol;
5use rustc_span::edit_distance::find_best_match_for_name;
6
7use super::prelude::*;
8
9pub(crate) struct CrateNameParser;
10
11impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
12    const PATH: &[Symbol] = &[sym::crate_name];
13    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
14    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
15    const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
    word: false,
    list: None,
    one_of: &[],
    name_value_str: Some(&["name"]),
    docs: None,
}template!(NameValueStr: "name");
16    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
17
18    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
19        let ArgParser::NameValue(n) = args else {
20            cx.expected_name_value(cx.attr_span, None);
21            return None;
22        };
23
24        let Some(name) = n.value_as_str() else {
25            cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
26            return None;
27        };
28
29        Some(AttributeKind::CrateName { name, name_span: n.value_span, attr_span: cx.attr_span })
30    }
31}
32
33pub(crate) struct CrateTypeParser;
34
35impl<S: Stage> CombineAttributeParser<S> for CrateTypeParser {
36    const PATH: &[Symbol] = &[sym::crate_type];
37    type Item = CrateType;
38    const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::CrateType(items);
39
40    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
41
42    const TEMPLATE: AttributeTemplate =
43        ::rustc_feature::AttributeTemplate {
    word: false,
    list: None,
    one_of: &[],
    name_value_str: Some(&["crate type"]),
    docs: Some("https://doc.rust-lang.org/reference/linkage.html"),
}template!(NameValueStr: "crate type", "https://doc.rust-lang.org/reference/linkage.html");
44
45    fn extend(
46        cx: &mut AcceptContext<'_, '_, S>,
47        args: &ArgParser,
48    ) -> impl IntoIterator<Item = Self::Item> {
49        let ArgParser::NameValue(n) = args else {
50            cx.expected_name_value(cx.attr_span, None);
51            return None;
52        };
53
54        let Some(crate_type) = n.value_as_str() else {
55            cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
56            return None;
57        };
58
59        let Ok(crate_type) = crate_type.try_into() else {
60            // We don't error on invalid `#![crate_type]` when not applied to a crate
61            if cx.shared.target == Target::Crate {
62                let candidate = find_best_match_for_name(
63                    &CrateType::all_stable().iter().map(|(name, _)| *name).collect::<Vec<_>>(),
64                    crate_type,
65                    None,
66                );
67                cx.emit_lint(
68                    UNKNOWN_CRATE_TYPES,
69                    AttributeLintKind::CrateTypeUnknown {
70                        span: n.value_span,
71                        suggested: candidate,
72                    },
73                    n.value_span,
74                );
75            }
76            return None;
77        };
78
79        Some(crate_type)
80    }
81}
82
83pub(crate) struct RecursionLimitParser;
84
85impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
86    const PATH: &[Symbol] = &[sym::recursion_limit];
87    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
88    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
89    const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
    word: false,
    list: None,
    one_of: &[],
    name_value_str: Some(&["N"]),
    docs: Some("https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"),
}template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
90    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
91
92    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
93        let ArgParser::NameValue(nv) = args else {
94            cx.expected_name_value(cx.attr_span, None);
95            return None;
96        };
97
98        Some(AttributeKind::RecursionLimit {
99            limit: cx.parse_limit_int(nv)?,
100            attr_span: cx.attr_span,
101            limit_span: nv.value_span,
102        })
103    }
104}
105
106pub(crate) struct MoveSizeLimitParser;
107
108impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
109    const PATH: &[Symbol] = &[sym::move_size_limit];
110    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
111    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
112    const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
    word: false,
    list: None,
    one_of: &[],
    name_value_str: Some(&["N"]),
    docs: None,
}template!(NameValueStr: "N");
113    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
114
115    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
116        let ArgParser::NameValue(nv) = args else {
117            cx.expected_name_value(cx.attr_span, None);
118            return None;
119        };
120
121        Some(AttributeKind::MoveSizeLimit {
122            limit: cx.parse_limit_int(nv)?,
123            attr_span: cx.attr_span,
124            limit_span: nv.value_span,
125        })
126    }
127}
128
129pub(crate) struct TypeLengthLimitParser;
130
131impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
132    const PATH: &[Symbol] = &[sym::type_length_limit];
133    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
134    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
135    const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
    word: false,
    list: None,
    one_of: &[],
    name_value_str: Some(&["N"]),
    docs: None,
}template!(NameValueStr: "N");
136    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
137
138    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
139        let ArgParser::NameValue(nv) = args else {
140            cx.expected_name_value(cx.attr_span, None);
141            return None;
142        };
143
144        Some(AttributeKind::TypeLengthLimit {
145            limit: cx.parse_limit_int(nv)?,
146            attr_span: cx.attr_span,
147            limit_span: nv.value_span,
148        })
149    }
150}
151
152pub(crate) struct PatternComplexityLimitParser;
153
154impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
155    const PATH: &[Symbol] = &[sym::pattern_complexity_limit];
156    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
157    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
158    const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
    word: false,
    list: None,
    one_of: &[],
    name_value_str: Some(&["N"]),
    docs: None,
}template!(NameValueStr: "N");
159    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
160
161    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
162        let ArgParser::NameValue(nv) = args else {
163            cx.expected_name_value(cx.attr_span, None);
164            return None;
165        };
166
167        Some(AttributeKind::PatternComplexityLimit {
168            limit: cx.parse_limit_int(nv)?,
169            attr_span: cx.attr_span,
170            limit_span: nv.value_span,
171        })
172    }
173}
174
175pub(crate) struct NoCoreParser;
176
177impl<S: Stage> NoArgsAttributeParser<S> for NoCoreParser {
178    const PATH: &[Symbol] = &[sym::no_core];
179    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
180    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
181    const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore;
182}
183
184pub(crate) struct NoStdParser;
185
186impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
187    const PATH: &[Symbol] = &[sym::no_std];
188    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
189    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
190    const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
191}
192
193pub(crate) struct NoMainParser;
194
195impl<S: Stage> NoArgsAttributeParser<S> for NoMainParser {
196    const PATH: &[Symbol] = &[sym::no_main];
197    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
198    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
199    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoMain;
200}
201
202pub(crate) struct RustcCoherenceIsCoreParser;
203
204impl<S: Stage> NoArgsAttributeParser<S> for RustcCoherenceIsCoreParser {
205    const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
206    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
207    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
208    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoherenceIsCore;
209}
210
211pub(crate) struct WindowsSubsystemParser;
212
213impl<S: Stage> SingleAttributeParser<S> for WindowsSubsystemParser {
214    const PATH: &[Symbol] = &[sym::windows_subsystem];
215    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
216    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
217    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
218    const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
    word: false,
    list: None,
    one_of: &[],
    name_value_str: Some(&["windows", "console"]),
    docs: Some("https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute"),
}template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute");
219
220    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
221        let Some(nv) = args.name_value() else {
222            cx.expected_name_value(
223                args.span().unwrap_or(cx.inner_span),
224                Some(sym::windows_subsystem),
225            );
226            return None;
227        };
228
229        let kind = match nv.value_as_str() {
230            Some(sym::console) => WindowsSubsystemKind::Console,
231            Some(sym::windows) => WindowsSubsystemKind::Windows,
232            Some(_) | None => {
233                cx.expected_specific_argument_strings(nv.value_span, &[sym::console, sym::windows]);
234                return None;
235            }
236        };
237
238        Some(AttributeKind::WindowsSubsystem(kind, cx.attr_span))
239    }
240}
241
242pub(crate) struct PanicRuntimeParser;
243
244impl<S: Stage> NoArgsAttributeParser<S> for PanicRuntimeParser {
245    const PATH: &[Symbol] = &[sym::panic_runtime];
246    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
247    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
248    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime;
249}
250
251pub(crate) struct NeedsPanicRuntimeParser;
252
253impl<S: Stage> NoArgsAttributeParser<S> for NeedsPanicRuntimeParser {
254    const PATH: &[Symbol] = &[sym::needs_panic_runtime];
255    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
256    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
257    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime;
258}
259
260pub(crate) struct ProfilerRuntimeParser;
261
262impl<S: Stage> NoArgsAttributeParser<S> for ProfilerRuntimeParser {
263    const PATH: &[Symbol] = &[sym::profiler_runtime];
264    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
265    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
266    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime;
267}
268
269pub(crate) struct NoBuiltinsParser;
270
271impl<S: Stage> NoArgsAttributeParser<S> for NoBuiltinsParser {
272    const PATH: &[Symbol] = &[sym::no_builtins];
273    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
274    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
275    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins;
276}