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