]>
Commit | Line | Data |
---|---|---|
e1599b0c XL |
1 | //! Built-in attributes and `cfg` flag gating. |
2 | ||
3c0e092e | 3 | use AttributeDuplicates::*; |
e1599b0c | 4 | use AttributeGate::*; |
dfeec247 | 5 | use AttributeType::*; |
e1599b0c | 6 | |
60c5eb7d | 7 | use crate::{Features, Stability}; |
e1599b0c | 8 | |
dfeec247 XL |
9 | use rustc_data_structures::fx::FxHashMap; |
10 | use rustc_span::symbol::{sym, Symbol}; | |
e1599b0c | 11 | |
923072b8 | 12 | use std::sync::LazyLock; |
1b1a35ee | 13 | |
e1599b0c XL |
14 | type GateFn = fn(&Features) -> bool; |
15 | ||
16 | macro_rules! cfg_fn { | |
17 | ($field: ident) => { | |
dfeec247 XL |
18 | (|features| features.$field) as GateFn |
19 | }; | |
e1599b0c XL |
20 | } |
21 | ||
60c5eb7d XL |
22 | pub type GatedCfg = (Symbol, Symbol, GateFn); |
23 | ||
e1599b0c | 24 | /// `cfg(...)`'s that are feature gated. |
60c5eb7d | 25 | const GATED_CFGS: &[GatedCfg] = &[ |
e1599b0c | 26 | // (name in cfg, feature, function to check if the feature is enabled) |
136023e0 | 27 | (sym::target_abi, sym::cfg_target_abi, cfg_fn!(cfg_target_abi)), |
e1599b0c | 28 | (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), |
1b1a35ee XL |
29 | ( |
30 | sym::target_has_atomic_equal_alignment, | |
5099ac24 FG |
31 | sym::cfg_target_has_atomic_equal_alignment, |
32 | cfg_fn!(cfg_target_has_atomic_equal_alignment), | |
1b1a35ee | 33 | ), |
5099ac24 | 34 | (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), |
60c5eb7d | 35 | (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)), |
f9f354fc | 36 | (sym::version, sym::cfg_version, cfg_fn!(cfg_version)), |
e1599b0c XL |
37 | ]; |
38 | ||
60c5eb7d XL |
39 | /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. |
40 | pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg> { | |
41 | GATED_CFGS.iter().find(|(cfg_sym, ..)| pred(*cfg_sym)) | |
e1599b0c XL |
42 | } |
43 | ||
44 | // If you change this, please modify `src/doc/unstable-book` as well. You must | |
45 | // move that documentation into the relevant place in the other docs, and | |
46 | // remove the chapter on the flag. | |
47 | ||
48 | #[derive(Copy, Clone, PartialEq, Debug)] | |
49 | pub enum AttributeType { | |
50 | /// Normal, builtin attribute that is consumed | |
51 | /// by the compiler before the unused_attribute check | |
52 | Normal, | |
53 | ||
e1599b0c XL |
54 | /// Builtin attribute that is only allowed at the crate level |
55 | CrateLevel, | |
56 | } | |
57 | ||
58 | #[derive(Clone, Copy)] | |
59 | pub enum AttributeGate { | |
60 | /// Is gated by a given feature gate, reason | |
61 | /// and function to check if enabled | |
62 | Gated(Stability, Symbol, &'static str, fn(&Features) -> bool), | |
63 | ||
64 | /// Ungated attribute, can be used on all release channels | |
65 | Ungated, | |
66 | } | |
67 | ||
68 | // fn() is not Debug | |
69 | impl std::fmt::Debug for AttributeGate { | |
70 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
71 | match *self { | |
dfeec247 XL |
72 | Self::Gated(ref stab, name, expl, _) => { |
73 | write!(fmt, "Gated({:?}, {}, {})", stab, name, expl) | |
74 | } | |
75 | Self::Ungated => write!(fmt, "Ungated"), | |
e1599b0c XL |
76 | } |
77 | } | |
78 | } | |
79 | ||
80 | impl AttributeGate { | |
81 | fn is_deprecated(&self) -> bool { | |
29967ef6 | 82 | matches!(*self, Self::Gated(Stability::Deprecated(_, _), ..)) |
e1599b0c XL |
83 | } |
84 | } | |
85 | ||
60c5eb7d XL |
86 | /// A template that the attribute input must match. |
87 | /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now. | |
ba9703b0 | 88 | #[derive(Clone, Copy, Default)] |
60c5eb7d | 89 | pub struct AttributeTemplate { |
3c0e092e | 90 | /// If `true`, the attribute is allowed to be a bare word like `#[test]`. |
60c5eb7d | 91 | pub word: bool, |
3c0e092e | 92 | /// If `Some`, the attribute is allowed to take a list of items like `#[allow(..)]`. |
60c5eb7d | 93 | pub list: Option<&'static str>, |
3c0e092e XL |
94 | /// If `Some`, the attribute is allowed to be a name/value pair where the |
95 | /// value is a string, like `#[must_use = "reason"]`. | |
60c5eb7d XL |
96 | pub name_value_str: Option<&'static str>, |
97 | } | |
98 | ||
3c0e092e XL |
99 | /// How to handle multiple duplicate attributes on the same item. |
100 | #[derive(Clone, Copy, Default)] | |
101 | pub enum AttributeDuplicates { | |
102 | /// Duplicates of this attribute are allowed. | |
103 | /// | |
104 | /// This should only be used with attributes where duplicates have semantic | |
105 | /// meaning, or some kind of "additive" behavior. For example, `#[warn(..)]` | |
106 | /// can be specified multiple times, and it combines all the entries. Or use | |
107 | /// this if there is validation done elsewhere. | |
108 | #[default] | |
109 | DuplicatesOk, | |
110 | /// Duplicates after the first attribute will be an unused_attribute warning. | |
111 | /// | |
112 | /// This is usually used for "word" attributes, where they are used as a | |
113 | /// boolean marker, like `#[used]`. It is not necessarily wrong that there | |
114 | /// are duplicates, but the others should probably be removed. | |
115 | WarnFollowing, | |
116 | /// Same as `WarnFollowing`, but only issues warnings for word-style attributes. | |
117 | /// | |
118 | /// This is only for special cases, for example multiple `#[macro_use]` can | |
119 | /// be warned, but multiple `#[macro_use(...)]` should not because the list | |
120 | /// form has different meaning from the word form. | |
121 | WarnFollowingWordOnly, | |
122 | /// Duplicates after the first attribute will be an error. | |
123 | /// | |
124 | /// This should be used where duplicates would be ignored, but carry extra | |
125 | /// meaning that could cause confusion. For example, `#[stable(since="1.0")] | |
126 | /// #[stable(since="2.0")]`, which version should be used for `stable`? | |
127 | ErrorFollowing, | |
128 | /// Duplicates preceding the last instance of the attribute will be an error. | |
129 | /// | |
130 | /// This is the same as `ErrorFollowing`, except the last attribute is the | |
131 | /// one that is "used". This is typically used in cases like codegen | |
132 | /// attributes which usually only honor the last attribute. | |
133 | ErrorPreceding, | |
134 | /// Duplicates after the first attribute will be an unused_attribute warning | |
135 | /// with a note that this will be an error in the future. | |
136 | /// | |
137 | /// This should be used for attributes that should be `ErrorFollowing`, but | |
138 | /// because older versions of rustc silently accepted (and ignored) the | |
139 | /// attributes, this is used to transition. | |
140 | FutureWarnFollowing, | |
141 | /// Duplicates preceding the last instance of the attribute will be a | |
142 | /// warning, with a note that this will be an error in the future. | |
143 | /// | |
144 | /// This is the same as `FutureWarnFollowing`, except the last attribute is | |
145 | /// the one that is "used". Ideally these can eventually migrate to | |
146 | /// `ErrorPreceding`. | |
147 | FutureWarnPreceding, | |
148 | } | |
149 | ||
04454e1e FG |
150 | /// A conveniece macro to deal with `$($expr)?`. |
151 | macro_rules! or_default { | |
152 | ($default:expr,) => { | |
153 | $default | |
154 | }; | |
155 | ($default:expr, $next:expr) => { | |
156 | $next | |
157 | }; | |
158 | } | |
159 | ||
e1599b0c XL |
160 | /// A convenience macro for constructing attribute templates. |
161 | /// E.g., `template!(Word, List: "description")` means that the attribute | |
162 | /// supports forms `#[attr]` and `#[attr(description)]`. | |
163 | macro_rules! template { | |
164 | (Word) => { template!(@ true, None, None) }; | |
165 | (List: $descr: expr) => { template!(@ false, Some($descr), None) }; | |
166 | (NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) }; | |
167 | (Word, List: $descr: expr) => { template!(@ true, Some($descr), None) }; | |
168 | (Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) }; | |
169 | (List: $descr1: expr, NameValueStr: $descr2: expr) => { | |
170 | template!(@ false, Some($descr1), Some($descr2)) | |
171 | }; | |
172 | (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => { | |
173 | template!(@ true, Some($descr1), Some($descr2)) | |
174 | }; | |
175 | (@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate { | |
176 | word: $word, list: $list, name_value_str: $name_value_str | |
177 | } }; | |
178 | } | |
179 | ||
180 | macro_rules! ungated { | |
04454e1e | 181 | ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)? $(,)?) => { |
3c0e092e XL |
182 | BuiltinAttribute { |
183 | name: sym::$attr, | |
04454e1e | 184 | only_local: or_default!(false, $($only_local)?), |
3c0e092e XL |
185 | type_: $typ, |
186 | template: $tpl, | |
187 | gate: Ungated, | |
188 | duplicates: $duplicates, | |
189 | } | |
e1599b0c XL |
190 | }; |
191 | } | |
192 | ||
193 | macro_rules! gated { | |
04454e1e | 194 | ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $gate:ident, $msg:expr $(,)?) => { |
3c0e092e XL |
195 | BuiltinAttribute { |
196 | name: sym::$attr, | |
04454e1e | 197 | only_local: or_default!(false, $($only_local)?), |
3c0e092e XL |
198 | type_: $typ, |
199 | template: $tpl, | |
200 | duplicates: $duplicates, | |
201 | gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)), | |
202 | } | |
e1599b0c | 203 | }; |
04454e1e | 204 | ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => { |
3c0e092e XL |
205 | BuiltinAttribute { |
206 | name: sym::$attr, | |
04454e1e | 207 | only_local: or_default!(false, $($only_local)?), |
3c0e092e XL |
208 | type_: $typ, |
209 | template: $tpl, | |
210 | duplicates: $duplicates, | |
211 | gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)), | |
212 | } | |
e1599b0c XL |
213 | }; |
214 | } | |
215 | ||
216 | macro_rules! rustc_attr { | |
04454e1e | 217 | (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(, @only_local: $only_local:expr)? $(,)?) => { |
e1599b0c | 218 | rustc_attr!( |
dfeec247 XL |
219 | $attr, |
220 | $typ, | |
221 | $tpl, | |
3c0e092e | 222 | $duplicate, |
04454e1e | 223 | $(@only_local: $only_local,)? |
dfeec247 XL |
224 | concat!( |
225 | "the `#[", | |
226 | stringify!($attr), | |
227 | "]` attribute is just used for rustc unit tests \ | |
e1599b0c XL |
228 | and will never be stable", |
229 | ), | |
230 | ) | |
231 | }; | |
04454e1e | 232 | ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => { |
3c0e092e XL |
233 | BuiltinAttribute { |
234 | name: sym::$attr, | |
04454e1e | 235 | only_local: or_default!(false, $($only_local)?), |
3c0e092e XL |
236 | type_: $typ, |
237 | template: $tpl, | |
238 | duplicates: $duplicates, | |
239 | gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)), | |
240 | } | |
e1599b0c XL |
241 | }; |
242 | } | |
243 | ||
244 | macro_rules! experimental { | |
245 | ($attr:ident) => { | |
246 | concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature") | |
dfeec247 | 247 | }; |
e1599b0c XL |
248 | } |
249 | ||
250 | const IMPL_DETAIL: &str = "internal implementation detail"; | |
60c5eb7d | 251 | const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never be stable"; |
e1599b0c | 252 | |
3c0e092e XL |
253 | pub struct BuiltinAttribute { |
254 | pub name: Symbol, | |
04454e1e FG |
255 | /// Whether this attribute is only used in the local crate. |
256 | /// | |
257 | /// If so, it is not encoded in the crate metadata. | |
258 | pub only_local: bool, | |
3c0e092e XL |
259 | pub type_: AttributeType, |
260 | pub template: AttributeTemplate, | |
261 | pub duplicates: AttributeDuplicates, | |
262 | pub gate: AttributeGate, | |
263 | } | |
e1599b0c XL |
264 | |
265 | /// Attributes that have a special meaning to rustc or rustdoc. | |
dfeec247 | 266 | #[rustfmt::skip] |
e1599b0c XL |
267 | pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ |
268 | // ========================================================================== | |
269 | // Stable attributes: | |
270 | // ========================================================================== | |
271 | ||
74b04a01 | 272 | // Conditional compilation: |
3c0e092e XL |
273 | ungated!(cfg, Normal, template!(List: "predicate"), DuplicatesOk), |
274 | ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), DuplicatesOk), | |
e1599b0c XL |
275 | |
276 | // Testing: | |
3c0e092e | 277 | ungated!(ignore, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing), |
e1599b0c XL |
278 | ungated!( |
279 | should_panic, Normal, | |
f2b60f7d | 280 | template!(Word, List: r#"expected = "reason""#, NameValueStr: "reason"), FutureWarnFollowing, |
e1599b0c XL |
281 | ), |
282 | // FIXME(Centril): This can be used on stable but shouldn't. | |
3c0e092e | 283 | ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name"), ErrorFollowing), |
e1599b0c XL |
284 | |
285 | // Macros: | |
3c0e092e XL |
286 | ungated!(automatically_derived, Normal, template!(Word), WarnFollowing), |
287 | ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ..."), WarnFollowingWordOnly), | |
288 | ungated!(macro_escape, Normal, template!(Word), WarnFollowing), // Deprecated synonym for `macro_use`. | |
289 | ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros"), WarnFollowing), | |
290 | ungated!(proc_macro, Normal, template!(Word), ErrorFollowing), | |
e1599b0c XL |
291 | ungated!( |
292 | proc_macro_derive, Normal, | |
3c0e092e | 293 | template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing, |
e1599b0c | 294 | ), |
3c0e092e | 295 | ungated!(proc_macro_attribute, Normal, template!(Word), ErrorFollowing), |
e1599b0c XL |
296 | |
297 | // Lints: | |
3c0e092e | 298 | ungated!( |
2b03887a FG |
299 | warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), |
300 | DuplicatesOk, @only_local: true, | |
3c0e092e XL |
301 | ), |
302 | ungated!( | |
2b03887a FG |
303 | allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), |
304 | DuplicatesOk, @only_local: true, | |
3c0e092e | 305 | ), |
5e7ed085 FG |
306 | gated!( |
307 | expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk, | |
308 | lint_reasons, experimental!(expect) | |
309 | ), | |
3c0e092e | 310 | ungated!( |
2b03887a FG |
311 | forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), |
312 | DuplicatesOk, @only_local: true, | |
3c0e092e XL |
313 | ), |
314 | ungated!( | |
2b03887a FG |
315 | deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), |
316 | DuplicatesOk, @only_local: true, | |
3c0e092e XL |
317 | ), |
318 | ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing), | |
c295e0f8 | 319 | gated!( |
3c0e092e | 320 | must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, |
04454e1e | 321 | experimental!(must_not_suspend) |
c295e0f8 | 322 | ), |
e1599b0c XL |
323 | ungated!( |
324 | deprecated, Normal, | |
325 | template!( | |
326 | Word, | |
327 | List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, | |
328 | NameValueStr: "reason" | |
329 | ), | |
04454e1e | 330 | ErrorFollowing |
e1599b0c XL |
331 | ), |
332 | ||
333 | // Crate properties: | |
3c0e092e | 334 | ungated!(crate_name, CrateLevel, template!(NameValueStr: "name"), FutureWarnFollowing), |
04454e1e | 335 | ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), DuplicatesOk), |
3c0e092e XL |
336 | // crate_id is deprecated |
337 | ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored"), FutureWarnFollowing), | |
e1599b0c XL |
338 | |
339 | // ABI, linking, symbols, and FFI | |
340 | ungated!( | |
94222f64 | 341 | link, Normal, |
f2b60f7d | 342 | template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated""#), |
3c0e092e | 343 | DuplicatesOk, |
e1599b0c | 344 | ), |
3c0e092e XL |
345 | ungated!(link_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), |
346 | ungated!(no_link, Normal, template!(Word), WarnFollowing), | |
2b03887a | 347 | ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, @only_local: true), |
3c0e092e XL |
348 | ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), |
349 | ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), | |
04454e1e FG |
350 | ungated!(no_mangle, Normal, template!(Word), WarnFollowing, @only_local: true), |
351 | ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, @only_local: true), | |
f2b60f7d | 352 | ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding), |
e1599b0c XL |
353 | |
354 | // Limits: | |
3c0e092e XL |
355 | ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), |
356 | ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), | |
74b04a01 | 357 | gated!( |
3c0e092e XL |
358 | const_eval_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing, |
359 | const_eval_limit, experimental!(const_eval_limit) | |
74b04a01 | 360 | ), |
cdc7bbd5 | 361 | gated!( |
3c0e092e XL |
362 | move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing, |
363 | large_assignments, experimental!(move_size_limit) | |
cdc7bbd5 | 364 | ), |
e1599b0c XL |
365 | |
366 | // Entry point: | |
f2b60f7d | 367 | gated!(unix_sigpipe, Normal, template!(Word, NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)), |
3c0e092e XL |
368 | ungated!(start, Normal, template!(Word), WarnFollowing), |
369 | ungated!(no_start, CrateLevel, template!(Word), WarnFollowing), | |
370 | ungated!(no_main, CrateLevel, template!(Word), WarnFollowing), | |
e1599b0c XL |
371 | |
372 | // Modules, prelude, and resolution: | |
3c0e092e XL |
373 | ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing), |
374 | ungated!(no_std, CrateLevel, template!(Word), WarnFollowing), | |
375 | ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing), | |
376 | ungated!(non_exhaustive, Normal, template!(Word), WarnFollowing), | |
e1599b0c XL |
377 | |
378 | // Runtime | |
3c0e092e | 379 | ungated!( |
5099ac24 | 380 | windows_subsystem, CrateLevel, |
3c0e092e XL |
381 | template!(NameValueStr: "windows|console"), FutureWarnFollowing |
382 | ), | |
383 | ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070 | |
e1599b0c XL |
384 | |
385 | // Code generation: | |
04454e1e FG |
386 | ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, @only_local: true), |
387 | ungated!(cold, Normal, template!(Word), WarnFollowing, @only_local: true), | |
5099ac24 | 388 | ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing), |
2b03887a FG |
389 | ungated!( |
390 | target_feature, Normal, template!(List: r#"enable = "name""#), | |
391 | DuplicatesOk, @only_local: true, | |
392 | ), | |
3c0e092e | 393 | ungated!(track_caller, Normal, template!(Word), WarnFollowing), |
74b04a01 | 394 | gated!( |
94222f64 | 395 | no_sanitize, Normal, |
3c0e092e | 396 | template!(List: "address, memory, thread"), DuplicatesOk, |
74b04a01 XL |
397 | experimental!(no_sanitize) |
398 | ), | |
3c0e092e | 399 | gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)), |
e1599b0c | 400 | |
3c0e092e XL |
401 | ungated!( |
402 | doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk | |
403 | ), | |
e1599b0c XL |
404 | |
405 | // ========================================================================== | |
406 | // Unstable attributes: | |
407 | // ========================================================================== | |
408 | ||
04454e1e FG |
409 | // RFC #3191: #[debugger_visualizer] support |
410 | gated!( | |
923072b8 | 411 | debugger_visualizer, Normal, template!(List: r#"natvis_file = "...", gdb_script_file = "...""#), |
04454e1e FG |
412 | DuplicatesOk, experimental!(debugger_visualizer) |
413 | ), | |
414 | ||
e1599b0c | 415 | // Linking: |
04454e1e | 416 | gated!(naked, Normal, template!(Word), WarnFollowing, @only_local: true, naked_functions, experimental!(naked)), |
e1599b0c XL |
417 | |
418 | // Plugins: | |
3c0e092e XL |
419 | BuiltinAttribute { |
420 | name: sym::plugin, | |
04454e1e | 421 | only_local: false, |
3c0e092e XL |
422 | type_: CrateLevel, |
423 | template: template!(List: "name"), | |
424 | duplicates: DuplicatesOk, | |
425 | gate: Gated( | |
e74abb32 XL |
426 | Stability::Deprecated( |
427 | "https://github.com/rust-lang/rust/pull/64675", | |
428 | Some("may be removed in a future compiler version"), | |
429 | ), | |
430 | sym::plugin, | |
431 | "compiler plugins are deprecated", | |
432 | cfg_fn!(plugin) | |
3c0e092e XL |
433 | ), |
434 | }, | |
e1599b0c XL |
435 | |
436 | // Testing: | |
e1599b0c | 437 | gated!( |
3c0e092e | 438 | test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, custom_test_frameworks, |
e1599b0c XL |
439 | "custom test frameworks are an unstable feature", |
440 | ), | |
e1599b0c | 441 | // RFC #1268 |
e1599b0c | 442 | gated!( |
3c0e092e XL |
443 | marker, Normal, template!(Word), WarnFollowing, marker_trait_attr, experimental!(marker) |
444 | ), | |
445 | gated!( | |
446 | thread_local, Normal, template!(Word), WarnFollowing, | |
e1599b0c XL |
447 | "`#[thread_local]` is an experimental feature, and does not currently handle destructors", |
448 | ), | |
3c0e092e | 449 | gated!(no_core, CrateLevel, template!(Word), WarnFollowing, experimental!(no_core)), |
e1599b0c XL |
450 | // RFC 2412 |
451 | gated!( | |
3c0e092e | 452 | optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute, |
e1599b0c XL |
453 | experimental!(optimize), |
454 | ), | |
29967ef6 | 455 | // RFC 2867 |
3c0e092e XL |
456 | gated!( |
457 | instruction_set, Normal, template!(List: "set"), ErrorPreceding, | |
458 | isa_attribute, experimental!(instruction_set) | |
459 | ), | |
e1599b0c | 460 | |
60c5eb7d | 461 | gated!( |
3c0e092e XL |
462 | ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice) |
463 | ), | |
464 | gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)), | |
465 | gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)), | |
60c5eb7d | 466 | gated!( |
3c0e092e | 467 | register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), DuplicatesOk, |
60c5eb7d XL |
468 | experimental!(register_tool), |
469 | ), | |
e1599b0c | 470 | |
3c0e092e XL |
471 | gated!( |
472 | cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing, | |
473 | experimental!(cmse_nonsecure_entry) | |
474 | ), | |
136023e0 XL |
475 | // RFC 2632 |
476 | gated!( | |
923072b8 | 477 | const_trait, Normal, template!(Word), WarnFollowing, const_trait_impl, |
2b03887a | 478 | "`const_trait` is a temporary placeholder for marking a trait that is suitable for `const` \ |
923072b8 FG |
479 | `impls` and all default bodies as `const`, which may be removed or renamed in the \ |
480 | future." | |
136023e0 | 481 | ), |
5e7ed085 FG |
482 | // lang-team MCP 147 |
483 | gated!( | |
484 | deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing, | |
485 | experimental!(deprecated_safe), | |
486 | ), | |
1b1a35ee | 487 | |
f2b60f7d FG |
488 | // `#[collapse_debuginfo]` |
489 | gated!( | |
490 | collapse_debuginfo, Normal, template!(Word), WarnFollowing, | |
491 | experimental!(collapse_debuginfo) | |
492 | ), | |
493 | ||
e1599b0c XL |
494 | // ========================================================================== |
495 | // Internal attributes: Stability, deprecation, and unsafe: | |
496 | // ========================================================================== | |
497 | ||
2b03887a FG |
498 | ungated!( |
499 | feature, CrateLevel, | |
500 | template!(List: "name1, name2, ..."), DuplicatesOk, @only_local: true, | |
501 | ), | |
3c0e092e XL |
502 | // DuplicatesOk since it has its own validation |
503 | ungated!( | |
2b03887a FG |
504 | stable, Normal, |
505 | template!(List: r#"feature = "name", since = "version""#), DuplicatesOk, @only_local: true, | |
e1599b0c | 506 | ), |
e1599b0c | 507 | ungated!( |
94222f64 | 508 | unstable, Normal, |
3c0e092e | 509 | template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk, |
e1599b0c | 510 | ), |
3c0e092e | 511 | ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk), |
2b03887a FG |
512 | ungated!( |
513 | rustc_const_stable, Normal, | |
514 | template!(List: r#"feature = "name""#), DuplicatesOk, @only_local: true, | |
515 | ), | |
f2b60f7d FG |
516 | ungated!( |
517 | rustc_default_body_unstable, Normal, | |
518 | template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk | |
519 | ), | |
e1599b0c | 520 | gated!( |
3c0e092e | 521 | allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, |
60c5eb7d | 522 | "allow_internal_unstable side-steps feature gating and stability checks", |
e1599b0c | 523 | ), |
29967ef6 | 524 | gated!( |
3c0e092e XL |
525 | rustc_allow_const_fn_unstable, Normal, |
526 | template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, | |
29967ef6 XL |
527 | "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" |
528 | ), | |
e1599b0c | 529 | gated!( |
3c0e092e | 530 | allow_internal_unsafe, Normal, template!(Word), WarnFollowing, |
60c5eb7d | 531 | "allow_internal_unsafe side-steps the unsafe_code lint", |
e1599b0c | 532 | ), |
2b03887a | 533 | ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk), |
064997fb FG |
534 | rustc_attr!(rustc_allowed_through_unstable_modules, Normal, template!(Word), WarnFollowing, |
535 | "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ | |
536 | through unstable paths"), | |
e1599b0c XL |
537 | |
538 | // ========================================================================== | |
539 | // Internal attributes: Type system related: | |
540 | // ========================================================================== | |
541 | ||
3c0e092e | 542 | gated!(fundamental, Normal, template!(Word), WarnFollowing, experimental!(fundamental)), |
e1599b0c | 543 | gated!( |
3c0e092e | 544 | may_dangle, Normal, template!(Word), WarnFollowing, dropck_eyepatch, |
e1599b0c XL |
545 | "`may_dangle` has unstable semantics and may be removed in the future", |
546 | ), | |
547 | ||
548 | // ========================================================================== | |
549 | // Internal attributes: Runtime related: | |
550 | // ========================================================================== | |
551 | ||
3c0e092e | 552 | rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), |
2b03887a | 553 | rustc_attr!(rustc_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), |
064997fb FG |
554 | rustc_attr!(rustc_reallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), |
555 | rustc_attr!(rustc_deallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), | |
556 | rustc_attr!(rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), | |
e1599b0c | 557 | gated!( |
3c0e092e XL |
558 | alloc_error_handler, Normal, template!(Word), WarnFollowing, |
559 | experimental!(alloc_error_handler) | |
560 | ), | |
561 | gated!( | |
562 | default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals, | |
e1599b0c XL |
563 | experimental!(default_lib_allocator), |
564 | ), | |
565 | gated!( | |
3c0e092e | 566 | needs_allocator, Normal, template!(Word), WarnFollowing, allocator_internals, |
e1599b0c XL |
567 | experimental!(needs_allocator), |
568 | ), | |
3c0e092e XL |
569 | gated!(panic_runtime, Normal, template!(Word), WarnFollowing, experimental!(panic_runtime)), |
570 | gated!( | |
571 | needs_panic_runtime, Normal, template!(Word), WarnFollowing, | |
572 | experimental!(needs_panic_runtime) | |
573 | ), | |
e1599b0c | 574 | gated!( |
3c0e092e | 575 | compiler_builtins, Normal, template!(Word), WarnFollowing, |
e1599b0c XL |
576 | "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ |
577 | which contains compiler-rt intrinsics and will never be stable", | |
578 | ), | |
e1599b0c | 579 | gated!( |
3c0e092e | 580 | profiler_runtime, Normal, template!(Word), WarnFollowing, |
e1599b0c XL |
581 | "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ |
582 | which contains the profiler runtime and will never be stable", | |
583 | ), | |
584 | ||
585 | // ========================================================================== | |
586 | // Internal attributes, Linkage: | |
587 | // ========================================================================== | |
588 | ||
589 | gated!( | |
04454e1e | 590 | linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding, @only_local: true, |
e1599b0c XL |
591 | "the `linkage` attribute is experimental and not portable across platforms", |
592 | ), | |
3c0e092e | 593 | rustc_attr!( |
04454e1e | 594 | rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, @only_local: true, INTERNAL_UNSTABLE |
3c0e092e | 595 | ), |
e1599b0c XL |
596 | |
597 | // ========================================================================== | |
598 | // Internal attributes, Macro related: | |
599 | // ========================================================================== | |
600 | ||
136023e0 | 601 | rustc_attr!( |
94222f64 | 602 | rustc_builtin_macro, Normal, |
3c0e092e | 603 | template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing, |
136023e0 XL |
604 | IMPL_DETAIL, |
605 | ), | |
3c0e092e | 606 | rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), |
e1599b0c | 607 | rustc_attr!( |
94222f64 | 608 | rustc_macro_transparency, Normal, |
3c0e092e | 609 | template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing, |
e1599b0c XL |
610 | "used internally for testing macro hygiene", |
611 | ), | |
612 | ||
613 | // ========================================================================== | |
614 | // Internal attributes, Diagnostics related: | |
615 | // ========================================================================== | |
616 | ||
60c5eb7d | 617 | rustc_attr!( |
94222f64 | 618 | rustc_on_unimplemented, Normal, |
e1599b0c XL |
619 | template!( |
620 | List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, | |
621 | NameValueStr: "message" | |
622 | ), | |
3c0e092e | 623 | ErrorFollowing, |
60c5eb7d | 624 | INTERNAL_UNSTABLE |
e1599b0c | 625 | ), |
f035d41b | 626 | // Enumerates "identity-like" conversion methods to suggest on type mismatch. |
3c0e092e XL |
627 | rustc_attr!( |
628 | rustc_conversion_suggestion, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE | |
629 | ), | |
c295e0f8 XL |
630 | // Prevents field reads in the marked trait or method to be considered |
631 | // during dead code analysis. | |
3c0e092e XL |
632 | rustc_attr!( |
633 | rustc_trivial_field_reads, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE | |
634 | ), | |
5099ac24 FG |
635 | // Used by the `rustc::potential_query_instability` lint to warn methods which |
636 | // might not be stable during incremental compilation. | |
637 | rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), | |
923072b8 FG |
638 | // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints |
639 | // to assist in changes to diagnostic APIs. | |
640 | rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), | |
064997fb FG |
641 | // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions` |
642 | // types (as well as any others in future). | |
643 | rustc_attr!(rustc_lint_opt_ty, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), | |
644 | // Used by the `rustc::bad_opt_access` lint on fields | |
645 | // types (as well as any others in future). | |
646 | rustc_attr!(rustc_lint_opt_deny_field_access, Normal, template!(List: "message"), WarnFollowing, INTERNAL_UNSTABLE), | |
e1599b0c XL |
647 | |
648 | // ========================================================================== | |
649 | // Internal attributes, Const related: | |
650 | // ========================================================================== | |
651 | ||
3c0e092e XL |
652 | rustc_attr!(rustc_promotable, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), |
653 | rustc_attr!( | |
654 | rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing, | |
655 | INTERNAL_UNSTABLE | |
656 | ), | |
c295e0f8 | 657 | // Do not const-check this function's body. It will always get replaced during CTFE. |
3c0e092e XL |
658 | rustc_attr!( |
659 | rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE | |
660 | ), | |
e1599b0c XL |
661 | |
662 | // ========================================================================== | |
663 | // Internal attributes, Layout related: | |
664 | // ========================================================================== | |
665 | ||
666 | rustc_attr!( | |
3c0e092e | 667 | rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing, |
e1599b0c | 668 | "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ |
5e7ed085 | 669 | niche optimizations in libcore and libstd and will never be stable", |
e1599b0c XL |
670 | ), |
671 | rustc_attr!( | |
3c0e092e | 672 | rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing, |
e1599b0c | 673 | "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ |
5e7ed085 | 674 | niche optimizations in libcore and libstd and will never be stable", |
e1599b0c XL |
675 | ), |
676 | rustc_attr!( | |
3c0e092e | 677 | rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing, |
e1599b0c | 678 | "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \ |
5e7ed085 | 679 | niche optimizations in libcore and libstd and will never be stable", |
e1599b0c XL |
680 | ), |
681 | ||
682 | // ========================================================================== | |
683 | // Internal attributes, Misc: | |
684 | // ========================================================================== | |
e1599b0c | 685 | gated!( |
04454e1e | 686 | lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, @only_local: true, lang_items, |
e1599b0c XL |
687 | "language items are subject to change", |
688 | ), | |
5099ac24 FG |
689 | rustc_attr!( |
690 | rustc_pass_by_value, Normal, | |
691 | template!(Word), ErrorFollowing, | |
692 | "#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference." | |
693 | ), | |
5e7ed085 | 694 | rustc_attr!( |
04454e1e | 695 | rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, @only_local: true, |
5e7ed085 FG |
696 | "#![rustc_coherence_is_core] allows inherent methods on builtin types, only intended to be used in `core`." |
697 | ), | |
698 | rustc_attr!( | |
04454e1e | 699 | rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true, |
5e7ed085 FG |
700 | "#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl." |
701 | ), | |
04454e1e FG |
702 | rustc_attr!( |
703 | rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing, | |
704 | "#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \ | |
705 | the given type by annotating all impl items with #[rustc_allow_incoherent_impl]." | |
706 | ), | |
923072b8 FG |
707 | rustc_attr!( |
708 | rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing, | |
709 | "#[rustc_box] allows creating boxes \ | |
710 | and it is only intended to be used in `alloc`." | |
711 | ), | |
712 | ||
3c0e092e XL |
713 | BuiltinAttribute { |
714 | name: sym::rustc_diagnostic_item, | |
04454e1e FG |
715 | // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`. |
716 | only_local: false, | |
3c0e092e XL |
717 | type_: Normal, |
718 | template: template!(NameValueStr: "name"), | |
719 | duplicates: ErrorFollowing, | |
720 | gate: Gated( | |
e1599b0c XL |
721 | Stability::Unstable, |
722 | sym::rustc_attrs, | |
723 | "diagnostic items compiler internal support for linting", | |
724 | cfg_fn!(rustc_attrs), | |
725 | ), | |
3c0e092e | 726 | }, |
e1599b0c XL |
727 | gated!( |
728 | // Used in resolve: | |
3c0e092e | 729 | prelude_import, Normal, template!(Word), WarnFollowing, |
e1599b0c XL |
730 | "`#[prelude_import]` is for use by rustc only", |
731 | ), | |
732 | gated!( | |
3c0e092e | 733 | rustc_paren_sugar, Normal, template!(Word), WarnFollowing, unboxed_closures, |
e1599b0c XL |
734 | "unboxed_closures are still evolving", |
735 | ), | |
736 | rustc_attr!( | |
04454e1e | 737 | rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, @only_local: true, |
e1599b0c XL |
738 | "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ |
739 | overflow checking behavior of several libcore functions that are inlined \ | |
740 | across crates and will never be stable", | |
741 | ), | |
3c0e092e XL |
742 | rustc_attr!( |
743 | rustc_reservation_impl, Normal, | |
744 | template!(NameValueStr: "reservation message"), ErrorFollowing, | |
745 | "the `#[rustc_reservation_impl]` attribute is internally used \ | |
746 | for reserving for `for<T> From<!> for T` impl" | |
e74abb32 | 747 | ), |
e1599b0c | 748 | rustc_attr!( |
2b03887a | 749 | rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing, |
e1599b0c XL |
750 | "the `#[rustc_test_marker]` attribute is used internally to track tests", |
751 | ), | |
ba9703b0 | 752 | rustc_attr!( |
3c0e092e | 753 | rustc_unsafe_specialization_marker, Normal, template!(Word), WarnFollowing, |
ba9703b0 XL |
754 | "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" |
755 | ), | |
756 | rustc_attr!( | |
3c0e092e | 757 | rustc_specialization_trait, Normal, template!(Word), WarnFollowing, |
ba9703b0 XL |
758 | "the `#[rustc_specialization_trait]` attribute is used to check specializations" |
759 | ), | |
cdc7bbd5 | 760 | rustc_attr!( |
3c0e092e | 761 | rustc_main, Normal, template!(Word), WarnFollowing, |
cdc7bbd5 XL |
762 | "the `#[rustc_main]` attribute is used internally to specify test entry point function", |
763 | ), | |
764 | rustc_attr!( | |
3c0e092e | 765 | rustc_skip_array_during_method_dispatch, Normal, template!(Word), WarnFollowing, |
cdc7bbd5 XL |
766 | "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \ |
767 | from method dispatch when the receiver is an array, for compatibility in editions < 2021." | |
768 | ), | |
5099ac24 FG |
769 | rustc_attr!( |
770 | rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."), ErrorFollowing, | |
771 | "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ | |
772 | definition of a trait, it's currently in experimental form and should be changed before \ | |
773 | being exposed outside of the std" | |
774 | ), | |
e1599b0c XL |
775 | |
776 | // ========================================================================== | |
777 | // Internal attributes, Testing: | |
778 | // ========================================================================== | |
779 | ||
2b03887a | 780 | rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing), |
3c0e092e XL |
781 | rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing), |
782 | rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing), | |
783 | rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing), | |
784 | rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing), | |
785 | rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing), | |
786 | rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing), | |
787 | rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), | |
60c5eb7d | 788 | rustc_attr!( |
94222f64 | 789 | TEST, rustc_error, Normal, |
3c0e092e XL |
790 | template!(Word, List: "delay_span_bug_from_inside_query"), WarnFollowingWordOnly |
791 | ), | |
792 | rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word), WarnFollowing), | |
793 | rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing), | |
794 | rustc_attr!( | |
795 | TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk | |
796 | ), | |
797 | rustc_attr!( | |
798 | TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode"), DuplicatesOk | |
60c5eb7d | 799 | ), |
e1599b0c | 800 | rustc_attr!( |
94222f64 | 801 | TEST, rustc_clean, Normal, |
e1599b0c | 802 | template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), |
3c0e092e | 803 | DuplicatesOk, |
e1599b0c XL |
804 | ), |
805 | rustc_attr!( | |
94222f64 | 806 | TEST, rustc_partition_reused, Normal, |
3c0e092e | 807 | template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, |
e1599b0c XL |
808 | ), |
809 | rustc_attr!( | |
94222f64 | 810 | TEST, rustc_partition_codegened, Normal, |
3c0e092e | 811 | template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, |
e1599b0c XL |
812 | ), |
813 | rustc_attr!( | |
94222f64 | 814 | TEST, rustc_expected_cgu_reuse, Normal, |
3c0e092e XL |
815 | template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk, |
816 | ), | |
817 | rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word), WarnFollowing), | |
818 | rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing), | |
819 | rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing), | |
820 | rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk), | |
821 | rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing), | |
822 | rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing), | |
823 | rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing), | |
824 | rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word), WarnFollowing), | |
825 | rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/), DuplicatesOk), | |
e1599b0c | 826 | gated!( |
3c0e092e | 827 | omit_gdb_pretty_printer_section, Normal, template!(Word), WarnFollowing, |
e1599b0c XL |
828 | "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite", |
829 | ), | |
830 | ]; | |
831 | ||
832 | pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> { | |
3c0e092e | 833 | BUILTIN_ATTRIBUTES.iter().filter(|attr| attr.gate.is_deprecated()).collect() |
e1599b0c XL |
834 | } |
835 | ||
60c5eb7d | 836 | pub fn is_builtin_attr_name(name: Symbol) -> bool { |
e1599b0c XL |
837 | BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() |
838 | } | |
839 | ||
2b03887a FG |
840 | /// Whether this builtin attribute is only used in the local crate. |
841 | /// If so, it is not encoded in the crate metadata. | |
04454e1e FG |
842 | pub fn is_builtin_only_local(name: Symbol) -> bool { |
843 | BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local) | |
844 | } | |
845 | ||
f2b60f7d FG |
846 | pub fn is_valid_for_get_attr(name: Symbol) -> bool { |
847 | BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| match attr.duplicates { | |
848 | WarnFollowing | ErrorFollowing | ErrorPreceding | FutureWarnFollowing | |
849 | | FutureWarnPreceding => true, | |
850 | DuplicatesOk | WarnFollowingWordOnly => false, | |
851 | }) | |
852 | } | |
853 | ||
923072b8 FG |
854 | pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> = |
855 | LazyLock::new(|| { | |
e1599b0c XL |
856 | let mut map = FxHashMap::default(); |
857 | for attr in BUILTIN_ATTRIBUTES.iter() { | |
3c0e092e XL |
858 | if map.insert(attr.name, attr).is_some() { |
859 | panic!("duplicate builtin attribute `{}`", attr.name); | |
e1599b0c XL |
860 | } |
861 | } | |
862 | map | |
1b1a35ee | 863 | }); |