1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 //! This module implements the gating necessary for preventing certain compiler
14 //! features from being used by default. This module will crawl a pre-expanded
15 //! AST to ensure that there are no features which are used that are not
18 //! Features are enabled in programs via the crate-level attributes of
19 //! `#![feature(...)]` with a comma-separated list of features.
21 //! For the purpose of future feature-tracking, once code for detection of feature
22 //! gate usage is added, *do not remove it again* even once the feature
25 use self::AttributeType::*;
26 use self::AttributeGate::*;
29 use ast::{self, NodeId, PatKind, RangeEnd};
33 use errors::{DiagnosticBuilder, Handler, FatalError};
34 use visit::{self, FnKind, Visitor};
38 use std::ascii::AsciiExt;
43 fn f(features: &mut Features, span: Span) {
44 features.declared_lib_features.push((Symbol::intern("proc_macro"), span));
45 features.proc_macro = true;
47 f as fn(&mut Features, Span)
50 fn f(features: &mut Features, _: Span) {
51 features.$field = true;
53 f as fn(&mut Features, Span)
57 macro_rules! declare_features {
58 ($((active, $feature: ident, $ver: expr, $issue: expr),)+) => {
59 /// Represents active features that are currently being implemented or
60 /// currently being considered for addition/removal.
61 const ACTIVE_FEATURES:
62 &'static [(&'static str, &'static str, Option<u32>, fn(&mut Features, Span))] =
63 &[$((stringify!($feature), $ver, $issue, set!($feature))),+];
65 /// A set of features to be used by later passes.
67 /// #![feature] attrs for stable language features, for error reporting
68 pub declared_stable_lang_features: Vec<(Symbol, Span)>,
69 /// #![feature] attrs for non-language (library) features
70 pub declared_lib_features: Vec<(Symbol, Span)>,
71 $(pub $feature: bool),+
75 pub fn new() -> Features {
77 declared_stable_lang_features: Vec::new(),
78 declared_lib_features: Vec::new(),
85 ($((removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
86 /// Represents unstable features which have since been removed (it was once Active)
87 const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
88 $((stringify!($feature), $ver, $issue)),+
92 ($((stable_removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
93 /// Represents stable features which have since been removed (it was once Accepted)
94 const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
95 $((stringify!($feature), $ver, $issue)),+
99 ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => {
100 /// Those language feature has since been Accepted (it was once Active)
101 const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
102 $((stringify!($feature), $ver, $issue)),+
107 // If you change this, please modify src/doc/unstable-book as well.
109 // Don't ever remove anything from this list; set them to 'Removed'.
111 // The version numbers here correspond to the version in which the current status
112 // was set. This is most important for knowing when a particular feature became
115 // NB: tools/tidy/src/features.rs parses this information directly out of the
116 // source, so take care when modifying it.
119 (active, asm, "1.0.0", Some(29722)),
120 (active, concat_idents, "1.0.0", Some(29599)),
121 (active, link_args, "1.0.0", Some(29596)),
122 (active, log_syntax, "1.0.0", Some(29598)),
123 (active, non_ascii_idents, "1.0.0", Some(28979)),
124 (active, plugin_registrar, "1.0.0", Some(29597)),
125 (active, thread_local, "1.0.0", Some(29594)),
126 (active, trace_macros, "1.0.0", Some(29598)),
128 // rustc internal, for now:
129 (active, intrinsics, "1.0.0", None),
130 (active, lang_items, "1.0.0", None),
132 (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
133 (active, linkage, "1.0.0", Some(29603)),
134 (active, quote, "1.0.0", Some(29601)),
135 (active, simd, "1.0.0", Some(27731)),
139 (active, rustc_diagnostic_macros, "1.0.0", None),
140 (active, rustc_const_unstable, "1.0.0", None),
141 (active, advanced_slice_patterns, "1.0.0", Some(23121)),
142 (active, box_syntax, "1.0.0", Some(27779)),
143 (active, placement_in_syntax, "1.0.0", Some(27779)),
144 (active, unboxed_closures, "1.0.0", Some(29625)),
146 (active, fundamental, "1.0.0", Some(29635)),
147 (active, main, "1.0.0", Some(29634)),
148 (active, needs_allocator, "1.4.0", Some(27389)),
149 (active, on_unimplemented, "1.0.0", Some(29628)),
150 (active, plugin, "1.0.0", Some(29597)),
151 (active, simd_ffi, "1.0.0", Some(27731)),
152 (active, start, "1.0.0", Some(29633)),
153 (active, structural_match, "1.8.0", Some(31434)),
154 (active, panic_runtime, "1.10.0", Some(32837)),
155 (active, needs_panic_runtime, "1.10.0", Some(32837)),
157 // OIBIT specific features
158 (active, optin_builtin_traits, "1.0.0", Some(13231)),
160 // macro reexport needs more discussion and stabilization
161 (active, macro_reexport, "1.0.0", Some(29638)),
163 // Allows use of #[staged_api]
165 (active, staged_api, "1.0.0", None),
167 // Allows using #![no_core]
168 (active, no_core, "1.3.0", Some(29639)),
170 // Allows using `box` in patterns; RFC 469
171 (active, box_patterns, "1.0.0", Some(29641)),
173 // Allows using the unsafe_destructor_blind_to_params attribute;
175 (active, dropck_parametricity, "1.3.0", Some(28498)),
177 // Allows using the may_dangle attribute; RFC 1327
178 (active, dropck_eyepatch, "1.10.0", Some(34761)),
180 // Allows the use of custom attributes; RFC 572
181 (active, custom_attribute, "1.0.0", Some(29642)),
183 // Allows the use of #[derive(Anything)] as sugar for
184 // #[derive_Anything].
185 (active, custom_derive, "1.0.0", Some(29644)),
187 // Allows the use of rustc_* attributes; RFC 572
188 (active, rustc_attrs, "1.0.0", Some(29642)),
190 // Allows the use of #[allow_internal_unstable]. This is an
191 // attribute on macro_rules! and can't use the attribute handling
192 // below (it has to be checked before expansion possibly makes
193 // macros disappear).
196 (active, allow_internal_unstable, "1.0.0", None),
198 // Allows the use of #[allow_internal_unsafe]. This is an
199 // attribute on macro_rules! and can't use the attribute handling
200 // below (it has to be checked before expansion possibly makes
201 // macros disappear).
204 (active, allow_internal_unsafe, "1.0.0", None),
206 // #23121. Array patterns have some hazards yet.
207 (active, slice_patterns, "1.0.0", Some(23121)),
209 // Allows the definition of `const fn` functions.
210 (active, const_fn, "1.2.0", Some(24111)),
212 // Allows indexing into constant arrays.
213 (active, const_indexing, "1.4.0", Some(29947)),
215 // Allows using #[prelude_import] on glob `use` items.
218 (active, prelude_import, "1.2.0", None),
220 // Allows default type parameters to influence type inference.
221 (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
223 // Allows associated type defaults
224 (active, associated_type_defaults, "1.2.0", Some(29661)),
226 // allow `repr(simd)`, and importing the various simd intrinsics
227 (active, repr_simd, "1.4.0", Some(27731)),
229 // Allows cfg(target_feature = "...").
230 (active, cfg_target_feature, "1.4.0", Some(29717)),
232 // allow `extern "platform-intrinsic" { ... }`
233 (active, platform_intrinsics, "1.4.0", Some(27731)),
236 // rust runtime internal
237 (active, unwind_attributes, "1.4.0", None),
239 // allow the use of `#[naked]` on functions.
240 (active, naked_functions, "1.9.0", Some(32408)),
242 // allow `#[no_debug]`
243 (active, no_debug, "1.5.0", Some(29721)),
245 // allow `#[omit_gdb_pretty_printer_section]`
247 (active, omit_gdb_pretty_printer_section, "1.5.0", None),
249 // Allows cfg(target_vendor = "...").
250 (active, cfg_target_vendor, "1.5.0", Some(29718)),
252 // Allow attributes on expressions and non-item statements
253 (active, stmt_expr_attributes, "1.6.0", Some(15701)),
255 // allow using type ascription in expressions
256 (active, type_ascription, "1.6.0", Some(23416)),
258 // Allows cfg(target_thread_local)
259 (active, cfg_target_thread_local, "1.7.0", Some(29594)),
262 (active, abi_vectorcall, "1.7.0", None),
265 (active, inclusive_range_syntax, "1.7.0", Some(28237)),
268 (active, exclusive_range_pattern, "1.11.0", Some(37854)),
270 // impl specialization (RFC 1210)
271 (active, specialization, "1.7.0", Some(31844)),
273 // Allows cfg(target_has_atomic = "...").
274 (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
276 // Allows `impl Trait` in function return types.
277 (active, conservative_impl_trait, "1.12.0", Some(34511)),
280 (active, never_type, "1.13.0", Some(35121)),
282 // Allows all literals in attribute lists and values of key-value pairs.
283 (active, attr_literals, "1.13.0", Some(34981)),
285 // Allows the sysV64 ABI to be specified on all platforms
286 // instead of just the platforms on which it is the C ABI
287 (active, abi_sysv64, "1.13.0", Some(36167)),
289 // Allows untagged unions `union U { ... }`
290 (active, untagged_unions, "1.13.0", Some(32836)),
292 // Used to identify the `compiler_builtins` crate
294 (active, compiler_builtins, "1.13.0", None),
296 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
297 (active, generic_param_attrs, "1.11.0", Some(34761)),
299 // Allows #[link(..., cfg(..))]
300 (active, link_cfg, "1.14.0", Some(37406)),
302 (active, use_extern_macros, "1.15.0", Some(35896)),
304 // Allows #[target_feature(...)]
305 (active, target_feature, "1.15.0", None),
307 // `extern "ptx-*" fn()`
308 (active, abi_ptx, "1.15.0", None),
311 (active, i128_type, "1.16.0", Some(35118)),
313 // The `repr(i128)` annotation for enums
314 (active, repr128, "1.16.0", Some(35118)),
316 // The `unadjusted` ABI. Perma unstable.
317 (active, abi_unadjusted, "1.16.0", None),
319 // Procedural macros 2.0.
320 (active, proc_macro, "1.16.0", Some(38356)),
322 // Declarative macros 2.0 (`macro`).
323 (active, decl_macro, "1.17.0", Some(39412)),
325 // Allows #[link(kind="static-nobundle"...]
326 (active, static_nobundle, "1.16.0", Some(37403)),
328 // `extern "msp430-interrupt" fn()`
329 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
331 // Used to identify crates that contain sanitizer runtimes
333 (active, sanitizer_runtime, "1.17.0", None),
335 // Used to identify crates that contain the profiler runtime
337 (active, profiler_runtime, "1.18.0", None),
339 // `extern "x86-interrupt" fn()`
340 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
343 // Allows the `catch {...}` expression
344 (active, catch_expr, "1.17.0", Some(31436)),
346 // Allows `repr(align(u16))` struct attribute (RFC 1358)
347 (active, repr_align, "1.17.0", Some(33626)),
349 // Used to preserve symbols (see llvm.used)
350 (active, used, "1.18.0", Some(40289)),
352 // Allows module-level inline assembly by way of global_asm!()
353 (active, global_asm, "1.18.0", Some(35119)),
355 // Allows overlapping impls of marker traits
356 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
358 // Allows use of the :vis macro fragment specifier
359 (active, macro_vis_matcher, "1.18.0", Some(41022)),
362 (active, abi_thiscall, "1.19.0", None),
364 // Allows a test to fail without failing the whole suite
365 (active, allow_fail, "1.19.0", Some(42219)),
367 // Allows unsized tuple coercion.
368 (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
371 (active, generators, "1.21.0", None),
374 // global allocators and their internals
375 (active, global_allocator, "1.20.0", None),
376 (active, allocator_internals, "1.20.0", None),
379 (active, doc_cfg, "1.21.0", Some(43781)),
381 // allow `#[must_use]` on functions (RFC 1940)
382 (active, fn_must_use, "1.21.0", Some(43302)),
384 // allow '|' at beginning of match arms (RFC 1925)
385 (active, match_beginning_vert, "1.21.0", Some(44101)),
389 (removed, import_shadowing, "1.0.0", None),
390 (removed, managed_boxes, "1.0.0", None),
391 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
392 (removed, negate_unsigned, "1.0.0", Some(29645)),
393 (removed, reflect, "1.0.0", Some(27749)),
394 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
395 (removed, opt_out_copy, "1.0.0", None),
396 (removed, quad_precision_float, "1.0.0", None),
397 (removed, struct_inherit, "1.0.0", None),
398 (removed, test_removed_feature, "1.0.0", None),
399 (removed, visible_private_types, "1.0.0", None),
400 (removed, unsafe_no_drop_flag, "1.0.0", None),
401 // Allows using items which are missing stability attributes
403 (removed, unmarked_api, "1.0.0", None),
404 (removed, pushpop_unsafe, "1.2.0", None),
405 (removed, allocator, "1.0.0", None),
409 (stable_removed, no_stack_check, "1.0.0", None),
413 (accepted, associated_types, "1.0.0", None),
414 // allow overloading augmented assignment operations like `a += b`
415 (accepted, augmented_assignments, "1.8.0", Some(28235)),
416 // allow empty structs and enum variants with braces
417 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
418 (accepted, default_type_params, "1.0.0", None),
419 (accepted, globs, "1.0.0", None),
420 (accepted, if_let, "1.0.0", None),
421 // A temporary feature gate used to enable parser extensions needed
422 // to bootstrap fix for #5723.
423 (accepted, issue_5723_bootstrap, "1.0.0", None),
424 (accepted, macro_rules, "1.0.0", None),
425 // Allows using #![no_std]
426 (accepted, no_std, "1.6.0", None),
427 (accepted, slicing_syntax, "1.0.0", None),
428 (accepted, struct_variant, "1.0.0", None),
429 // These are used to test this portion of the compiler, they don't actually
431 (accepted, test_accepted_feature, "1.0.0", None),
432 (accepted, tuple_indexing, "1.0.0", None),
433 // Allows macros to appear in the type position.
434 (accepted, type_macros, "1.13.0", Some(27245)),
435 (accepted, while_let, "1.0.0", None),
436 // Allows `#[deprecated]` attribute
437 (accepted, deprecated, "1.9.0", Some(29935)),
439 (accepted, question_mark, "1.13.0", Some(31436)),
440 // Allows `..` in tuple (struct) patterns
441 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
442 (accepted, item_like_imports, "1.15.0", Some(35120)),
443 // Allows using `Self` and associated types in struct expressions and patterns.
444 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
445 // elide `'static` lifetimes in `static`s and `const`s
446 (accepted, static_in_const, "1.17.0", Some(35897)),
447 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
448 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
449 // Allows the definition recursive static items.
450 (accepted, static_recursion, "1.17.0", Some(29719)),
451 // pub(restricted) visibilities (RFC 1422)
452 (accepted, pub_restricted, "1.18.0", Some(32409)),
453 // The #![windows_subsystem] attribute
454 (accepted, windows_subsystem, "1.18.0", Some(37499)),
455 // Allows `break {expr}` with a value inside `loop`s.
456 (accepted, loop_break_value, "1.19.0", Some(37339)),
457 // Permits numeric fields in struct expressions and patterns.
458 (accepted, relaxed_adts, "1.19.0", Some(35626)),
459 // Coerces non capturing closures to function pointers
460 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
461 // Allows attributes on struct literal fields.
462 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
463 // Allows the definition of associated constants in `trait` or `impl`
465 (accepted, associated_consts, "1.20.0", Some(29646)),
466 // Usage of the `compile_error!` macro
467 (accepted, compile_error, "1.20.0", Some(40872)),
468 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
469 (accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
470 // Allow Drop types in constants (RFC 1440)
471 (accepted, drop_types_in_const, "1.22.0", Some(33156)),
474 // If you change this, please modify src/doc/unstable-book as well. You must
475 // move that documentation into the relevant place in the other docs, and
476 // remove the chapter on the flag.
478 #[derive(PartialEq, Copy, Clone, Debug)]
479 pub enum AttributeType {
480 /// Normal, builtin attribute that is consumed
481 /// by the compiler before the unused_attribute check
484 /// Builtin attribute that may not be consumed by the compiler
485 /// before the unused_attribute check. These attributes
486 /// will be ignored by the unused_attribute lint
489 /// Builtin attribute that is only allowed at the crate level
493 pub enum AttributeGate {
494 /// Is gated by a given feature gate, reason
495 /// and function to check if enabled
496 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
498 /// Ungated attribute, can be used on all release channels
503 fn is_deprecated(&self) -> bool {
505 Gated(Stability::Deprecated(_), ..) => true,
511 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
514 // Argument is tracking issue link.
515 Deprecated(&'static str),
519 impl ::std::fmt::Debug for AttributeGate {
520 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
522 Gated(ref stab, name, expl, _) =>
523 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
524 Ungated => write!(fmt, "Ungated")
529 macro_rules! cfg_fn {
530 ($field: ident) => {{
531 fn f(features: &Features) -> bool {
534 f as fn(&Features) -> bool
538 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
539 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
542 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
543 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
546 // Attributes that have a special meaning to rustc or rustdoc
547 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
550 ("warn", Normal, Ungated),
551 ("allow", Normal, Ungated),
552 ("forbid", Normal, Ungated),
553 ("deny", Normal, Ungated),
555 ("macro_reexport", Normal, Ungated),
556 ("macro_use", Normal, Ungated),
557 ("macro_export", Normal, Ungated),
558 ("plugin_registrar", Normal, Ungated),
560 ("cfg", Normal, Ungated),
561 ("cfg_attr", Normal, Ungated),
562 ("main", Normal, Ungated),
563 ("start", Normal, Ungated),
564 ("test", Normal, Ungated),
565 ("bench", Normal, Ungated),
566 ("simd", Normal, Ungated),
567 ("repr", Normal, Ungated),
568 ("path", Normal, Ungated),
569 ("abi", Normal, Ungated),
570 ("automatically_derived", Normal, Ungated),
571 ("no_mangle", Normal, Ungated),
572 ("no_link", Normal, Ungated),
573 ("derive", Normal, Ungated),
574 ("should_panic", Normal, Ungated),
575 ("ignore", Normal, Ungated),
576 ("no_implicit_prelude", Normal, Ungated),
577 ("reexport_test_harness_main", Normal, Ungated),
578 ("link_args", Normal, Gated(Stability::Unstable,
580 "the `link_args` attribute is experimental and not \
581 portable across platforms, it is recommended to \
582 use `#[link(name = \"foo\")] instead",
583 cfg_fn!(link_args))),
584 ("macro_escape", Normal, Ungated),
587 ("structural_match", Whitelisted, Gated(Stability::Unstable,
589 "the semantics of constant patterns is \
591 cfg_fn!(structural_match))),
593 ("plugin", CrateLevel, Gated(Stability::Unstable,
595 "compiler plugins are experimental \
599 ("no_std", CrateLevel, Ungated),
600 ("no_core", CrateLevel, Gated(Stability::Unstable,
602 "no_core is experimental",
604 ("lang", Normal, Gated(Stability::Unstable,
606 "language items are subject to change",
607 cfg_fn!(lang_items))),
608 ("linkage", Whitelisted, Gated(Stability::Unstable,
610 "the `linkage` attribute is experimental \
611 and not portable across platforms",
613 ("thread_local", Whitelisted, Gated(Stability::Unstable,
615 "`#[thread_local]` is an experimental feature, and does \
616 not currently handle destructors. There is no \
617 corresponding `#[task_local]` mapping to the task \
619 cfg_fn!(thread_local))),
621 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
623 "the `#[rustc_on_unimplemented]` attribute \
624 is an experimental feature",
625 cfg_fn!(on_unimplemented))),
626 ("rustc_const_unstable", Normal, Gated(Stability::Unstable,
627 "rustc_const_unstable",
628 "the `#[rustc_const_unstable]` attribute \
629 is an internal feature",
630 cfg_fn!(rustc_const_unstable))),
631 ("global_allocator", Normal, Gated(Stability::Unstable,
633 "the `#[global_allocator]` attribute is \
634 an experimental feature",
635 cfg_fn!(global_allocator))),
636 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
637 "allocator_internals",
638 "the `#[default_lib_allocator]` \
639 attribute is an experimental feature",
640 cfg_fn!(allocator_internals))),
641 ("needs_allocator", Normal, Gated(Stability::Unstable,
642 "allocator_internals",
643 "the `#[needs_allocator]` \
644 attribute is an experimental \
646 cfg_fn!(allocator_internals))),
647 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
649 "the `#[panic_runtime]` attribute is \
650 an experimental feature",
651 cfg_fn!(panic_runtime))),
652 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
653 "needs_panic_runtime",
654 "the `#[needs_panic_runtime]` \
655 attribute is an experimental \
657 cfg_fn!(needs_panic_runtime))),
658 ("rustc_variance", Normal, Gated(Stability::Unstable,
660 "the `#[rustc_variance]` attribute \
661 is just used for rustc unit tests \
662 and will never be stable",
663 cfg_fn!(rustc_attrs))),
664 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
666 "the `#[rustc_error]` attribute \
667 is just used for rustc unit tests \
668 and will never be stable",
669 cfg_fn!(rustc_attrs))),
670 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
672 "the `#[rustc_if_this_changed]` attribute \
673 is just used for rustc unit tests \
674 and will never be stable",
675 cfg_fn!(rustc_attrs))),
676 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
678 "the `#[rustc_if_this_changed]` attribute \
679 is just used for rustc unit tests \
680 and will never be stable",
681 cfg_fn!(rustc_attrs))),
682 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
684 "the `#[rustc_dirty]` attribute \
685 is just used for rustc unit tests \
686 and will never be stable",
687 cfg_fn!(rustc_attrs))),
688 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
690 "the `#[rustc_clean]` attribute \
691 is just used for rustc unit tests \
692 and will never be stable",
693 cfg_fn!(rustc_attrs))),
694 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
696 "the `#[rustc_metadata_dirty]` attribute \
697 is just used for rustc unit tests \
698 and will never be stable",
699 cfg_fn!(rustc_attrs))),
700 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
702 "the `#[rustc_metadata_clean]` attribute \
703 is just used for rustc unit tests \
704 and will never be stable",
705 cfg_fn!(rustc_attrs))),
706 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
709 is just used for rustc unit tests \
710 and will never be stable",
711 cfg_fn!(rustc_attrs))),
712 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
715 is just used for rustc unit tests \
716 and will never be stable",
717 cfg_fn!(rustc_attrs))),
718 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
720 "internal rustc attributes will never be stable",
721 cfg_fn!(rustc_attrs))),
722 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
724 "internal rustc attributes will never be stable",
725 cfg_fn!(rustc_attrs))),
726 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
728 "the `#[rustc_mir]` attribute \
729 is just used for rustc unit tests \
730 and will never be stable",
731 cfg_fn!(rustc_attrs))),
732 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
734 "the `#[rustc_inherit_overflow_checks]` \
735 attribute is just used to control \
736 overflow checking behavior of several \
737 libcore functions that are inlined \
738 across crates and will never be stable",
739 cfg_fn!(rustc_attrs))),
740 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
742 "the `#[compiler_builtins]` attribute is used to \
743 identify the `compiler_builtins` crate which \
744 contains compiler-rt intrinsics and will never be \
746 cfg_fn!(compiler_builtins))),
747 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
749 "the `#[sanitizer_runtime]` attribute is used to \
750 identify crates that contain the runtime of a \
751 sanitizer and will never be stable",
752 cfg_fn!(sanitizer_runtime))),
753 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
755 "the `#[profiler_runtime]` attribute is used to \
756 identify the `profiler_builtins` crate which \
757 contains the profiler runtime and will never be \
759 cfg_fn!(profiler_runtime))),
761 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
762 "allow_internal_unstable",
763 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
764 cfg_fn!(allow_internal_unstable))),
766 ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
767 "allow_internal_unsafe",
768 EXPLAIN_ALLOW_INTERNAL_UNSAFE,
769 cfg_fn!(allow_internal_unsafe))),
771 ("fundamental", Whitelisted, Gated(Stability::Unstable,
773 "the `#[fundamental]` attribute \
774 is an experimental feature",
775 cfg_fn!(fundamental))),
777 ("proc_macro_derive", Normal, Ungated),
779 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
781 "internal implementation detail",
782 cfg_fn!(rustc_attrs))),
784 // FIXME: #14408 whitelist docs since rustdoc looks at them
785 ("doc", Whitelisted, Ungated),
787 // FIXME: #14406 these are processed in trans, which happens after the
789 ("cold", Whitelisted, Ungated),
790 ("naked", Whitelisted, Gated(Stability::Unstable,
792 "the `#[naked]` attribute \
793 is an experimental feature",
794 cfg_fn!(naked_functions))),
795 ("target_feature", Whitelisted, Gated(
796 Stability::Unstable, "target_feature",
797 "the `#[target_feature]` attribute is an experimental feature",
798 cfg_fn!(target_feature))),
799 ("export_name", Whitelisted, Ungated),
800 ("inline", Whitelisted, Ungated),
801 ("link", Whitelisted, Ungated),
802 ("link_name", Whitelisted, Ungated),
803 ("link_section", Whitelisted, Ungated),
804 ("no_builtins", Whitelisted, Ungated),
805 ("no_mangle", Whitelisted, Ungated),
806 ("no_debug", Whitelisted, Gated(
807 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
809 "the `#[no_debug]` attribute is an experimental feature",
811 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
812 "omit_gdb_pretty_printer_section",
813 "the `#[omit_gdb_pretty_printer_section]` \
814 attribute is just used for the Rust test \
816 cfg_fn!(omit_gdb_pretty_printer_section))),
817 ("unsafe_destructor_blind_to_params",
819 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
820 "dropck_parametricity",
821 "unsafe_destructor_blind_to_params has been replaced by \
822 may_dangle and will be removed in the future",
823 cfg_fn!(dropck_parametricity))),
826 Gated(Stability::Unstable,
828 "may_dangle has unstable semantics and may be removed in the future",
829 cfg_fn!(dropck_eyepatch))),
830 ("unwind", Whitelisted, Gated(Stability::Unstable,
832 "#[unwind] is experimental",
833 cfg_fn!(unwind_attributes))),
834 ("used", Whitelisted, Gated(
835 Stability::Unstable, "used",
836 "the `#[used]` attribute is an experimental feature",
840 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
842 "`#[prelude_import]` is for use by rustc only",
843 cfg_fn!(prelude_import))),
845 // FIXME: #14407 these are only looked at on-demand so we can't
846 // guarantee they'll have already been checked
847 ("rustc_deprecated", Whitelisted, Ungated),
848 ("must_use", Whitelisted, Ungated),
849 ("stable", Whitelisted, Ungated),
850 ("unstable", Whitelisted, Ungated),
851 ("deprecated", Normal, Ungated),
853 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
855 "unboxed_closures are still evolving",
856 cfg_fn!(unboxed_closures))),
858 ("windows_subsystem", Whitelisted, Ungated),
860 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
862 "attribute proc macros are currently unstable",
863 cfg_fn!(proc_macro))),
865 ("proc_macro", Normal, Gated(Stability::Unstable,
867 "function-like proc macros are currently unstable",
868 cfg_fn!(proc_macro))),
870 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
871 "rustc_derive_registrar",
872 "used internally by rustc",
873 cfg_fn!(rustc_attrs))),
875 ("allow_fail", Normal, Gated(Stability::Unstable,
877 "allow_fail attribute is currently unstable",
878 cfg_fn!(allow_fail))),
880 // Crate level attributes
881 ("crate_name", CrateLevel, Ungated),
882 ("crate_type", CrateLevel, Ungated),
883 ("crate_id", CrateLevel, Ungated),
884 ("feature", CrateLevel, Ungated),
885 ("no_start", CrateLevel, Ungated),
886 ("no_main", CrateLevel, Ungated),
887 ("no_builtins", CrateLevel, Ungated),
888 ("recursion_limit", CrateLevel, Ungated),
889 ("type_length_limit", CrateLevel, Ungated),
892 // cfg(...)'s that are feature gated
893 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
894 // (name in cfg, feature, function to check if the feature is enabled)
895 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
896 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
897 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
898 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
901 #[derive(Debug, Eq, PartialEq)]
902 pub struct GatedCfg {
908 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
909 let name = cfg.name().as_str();
911 .position(|info| info.0 == name)
920 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
921 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
922 if !has_feature(features) && !self.span.allows_unstable() {
923 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
924 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
930 features: &'a Features,
931 parse_sess: &'a ParseSess,
932 plugin_attributes: &'a [(String, AttributeType)],
935 macro_rules! gate_feature_fn {
936 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
937 let (cx, has_feature, span,
938 name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
939 let has_feature: bool = has_feature(&$cx.features);
940 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
941 if !has_feature && !span.allows_unstable() {
942 leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
948 macro_rules! gate_feature {
949 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
950 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
951 stringify!($feature), $explain, GateStrength::Hard)
953 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
954 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
955 stringify!($feature), $explain, $level)
959 impl<'a> Context<'a> {
960 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
961 debug!("check_attribute(attr = {:?})", attr);
962 let name = unwrap_or!(attr.name(), return).as_str();
963 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
965 if let Gated(_, name, desc, ref has_feature) = *gateage {
966 gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
968 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
972 for &(ref n, ref ty) in self.plugin_attributes {
973 if attr.path == &**n {
974 // Plugins can't gate attributes, so we don't check for it
975 // unlike the code above; we only use this loop to
976 // short-circuit to avoid the checks below
977 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
981 if name.starts_with("rustc_") {
982 gate_feature!(self, rustc_attrs, attr.span,
983 "unless otherwise specified, attributes \
984 with the prefix `rustc_` \
985 are reserved for internal compiler diagnostics");
986 } else if name.starts_with("derive_") {
987 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
988 } else if !attr::is_known(attr) {
989 // Only run the custom attribute lint during regular
990 // feature gate checking. Macro gating runs
991 // before the plugin attributes are registered
992 // so we skip this then
994 gate_feature!(self, custom_attribute, attr.span,
995 &format!("The attribute `{}` is currently \
996 unknown to the compiler and \
998 added to it in the future",
1005 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
1006 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
1007 cx.check_attribute(attr, true);
1010 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
1011 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
1014 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
1015 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
1017 // FIXME (#28244): enforce that active features have issue numbers
1018 // assert!(issue.is_some())
1021 // search in Accepted, Removed, or Stable Removed features
1022 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
1023 .find(|t| t.0 == feature);
1025 Some(&(_, _, issue)) => issue,
1026 None => panic!("Feature `{}` is not declared anywhere", feature),
1031 pub enum GateIssue {
1033 Library(Option<u32>)
1036 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1037 pub enum GateStrength {
1038 /// A hard error. (Most feature gates should use this.)
1040 /// Only a warning. (Use this only as backwards-compatibility demands.)
1044 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1046 feature_err(sess, feature, span, issue, explain).emit();
1049 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1050 explain: &str) -> DiagnosticBuilder<'a> {
1051 leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
1054 fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1055 explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
1056 let diag = &sess.span_diagnostic;
1058 let issue = match issue {
1059 GateIssue::Language => find_lang_feature_issue(feature),
1060 GateIssue::Library(lib) => lib,
1063 let explanation = if let Some(n) = issue {
1064 format!("{} (see issue #{})", explain, n)
1069 let mut err = match level {
1070 GateStrength::Hard => diag.struct_span_err(span, &explanation),
1071 GateStrength::Soft => diag.struct_span_warn(span, &explanation),
1074 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1075 if sess.unstable_features.is_nightly_build() {
1076 err.help(&format!("add #![feature({})] to the \
1077 crate attributes to enable",
1081 // If we're on stable and only emitting a "soft" warning, add a note to
1082 // clarify that the feature isn't "on" (rather than being on but
1084 if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
1085 err.help("a nightly build of the compiler is required to enable this feature");
1092 const EXPLAIN_BOX_SYNTAX: &'static str =
1093 "box expression syntax is experimental; you can call `Box::new` instead.";
1095 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1096 "attributes on non-item statements and expressions are experimental.";
1098 pub const EXPLAIN_ASM: &'static str =
1099 "inline assembly is not stable enough for use and is subject to change";
1101 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1102 "`global_asm!` is not stable enough for use and is subject to change";
1104 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1105 "`log_syntax!` is not stable enough for use and is subject to change";
1107 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1108 "`concat_idents` is not stable enough for use and is subject to change";
1110 pub const EXPLAIN_TRACE_MACROS: &'static str =
1111 "`trace_macros` is not stable enough for use and is subject to change";
1112 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1113 "allow_internal_unstable side-steps feature gating and stability checks";
1114 pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
1115 "allow_internal_unsafe side-steps the unsafe_code lint";
1117 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1118 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1120 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1121 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1122 Prefer using procedural macro custom derive.";
1124 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1125 "attributes of the form `#[derive_*]` are reserved for the compiler";
1127 pub const EXPLAIN_VIS_MATCHER: &'static str =
1128 ":vis fragment specifier is experimental and subject to change";
1130 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1131 "placement-in expression syntax is experimental and subject to change.";
1133 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1134 "Unsized tuple coercion is not stable enough for use and is subject to change";
1136 struct PostExpansionVisitor<'a> {
1137 context: &'a Context<'a>,
1140 macro_rules! gate_feature_post {
1141 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1142 let (cx, span) = ($cx, $span);
1143 if !span.allows_unstable() {
1144 gate_feature!(cx.context, $feature, span, $explain)
1147 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
1148 let (cx, span) = ($cx, $span);
1149 if !span.allows_unstable() {
1150 gate_feature!(cx.context, $feature, span, $explain, $level)
1155 impl<'a> PostExpansionVisitor<'a> {
1156 fn check_abi(&self, abi: Abi, span: Span) {
1158 Abi::RustIntrinsic => {
1159 gate_feature_post!(&self, intrinsics, span,
1160 "intrinsics are subject to change");
1162 Abi::PlatformIntrinsic => {
1163 gate_feature_post!(&self, platform_intrinsics, span,
1164 "platform intrinsics are experimental and possibly buggy");
1166 Abi::Vectorcall => {
1167 gate_feature_post!(&self, abi_vectorcall, span,
1168 "vectorcall is experimental and subject to change");
1171 gate_feature_post!(&self, abi_thiscall, span,
1172 "thiscall is experimental and subject to change");
1175 gate_feature_post!(&self, unboxed_closures, span,
1176 "rust-call ABI is subject to change");
1179 gate_feature_post!(&self, abi_sysv64, span,
1180 "sysv64 ABI is experimental and subject to change");
1183 gate_feature_post!(&self, abi_ptx, span,
1184 "PTX ABIs are experimental and subject to change");
1186 Abi::Unadjusted => {
1187 gate_feature_post!(&self, abi_unadjusted, span,
1188 "unadjusted ABI is an implementation detail and perma-unstable");
1190 Abi::Msp430Interrupt => {
1191 gate_feature_post!(&self, abi_msp430_interrupt, span,
1192 "msp430-interrupt ABI is experimental and subject to change");
1194 Abi::X86Interrupt => {
1195 gate_feature_post!(&self, abi_x86_interrupt, span,
1196 "x86-interrupt ABI is experimental and subject to change");
1211 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1212 use ast::MetaItemKind::*;
1213 use ast::NestedMetaItemKind::*;
1217 NameValue(ref lit) => !lit.node.is_str(),
1218 List(ref list) => list.iter().any(|li| {
1220 MetaItem(ref mi) => contains_novel_literal(mi),
1227 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1228 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1229 if !attr.span.allows_unstable() {
1230 // check for gated attributes
1231 self.context.check_attribute(attr, false);
1234 if attr.check_name("doc") {
1235 if let Some(content) = attr.meta_item_list() {
1236 if content.len() == 1 && content[0].check_name("cfg") {
1237 gate_feature_post!(&self, doc_cfg, attr.span,
1238 "#[doc(cfg(...))] is experimental"
1244 if self.context.features.proc_macro && attr::is_known(attr) {
1248 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1249 if contains_novel_literal(&meta) {
1250 gate_feature_post!(&self, attr_literals, attr.span,
1251 "non-string literals in attributes, or string \
1252 literals in top-level positions, are experimental");
1256 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1257 if !name.as_str().is_ascii() {
1258 gate_feature_post!(&self, non_ascii_idents, sp,
1259 "non-ascii idents are not fully supported.");
1263 fn visit_item(&mut self, i: &'a ast::Item) {
1265 ast::ItemKind::ExternCrate(_) => {
1266 if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
1267 gate_feature_post!(&self, macro_reexport, attr.span,
1268 "macros reexports are experimental \
1269 and possibly buggy");
1273 ast::ItemKind::ForeignMod(ref foreign_module) => {
1274 self.check_abi(foreign_module.abi, i.span);
1277 ast::ItemKind::Fn(..) => {
1278 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1279 gate_feature_post!(&self, plugin_registrar, i.span,
1280 "compiler plugins are experimental and possibly buggy");
1282 if attr::contains_name(&i.attrs[..], "start") {
1283 gate_feature_post!(&self, start, i.span,
1284 "a #[start] function is an experimental \
1285 feature whose signature may change \
1288 if attr::contains_name(&i.attrs[..], "main") {
1289 gate_feature_post!(&self, main, i.span,
1290 "declaration of a nonstandard #[main] \
1291 function may change over time, for now \
1292 a top-level `fn main()` is required");
1294 if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") {
1295 gate_feature_post!(&self, fn_must_use, attr.span,
1296 "`#[must_use]` on functions is experimental",
1297 GateStrength::Soft);
1301 ast::ItemKind::Struct(..) => {
1302 if let Some(attr) = attr::find_by_name(&i.attrs[..], "simd") {
1303 gate_feature_post!(&self, simd, attr.span,
1304 "SIMD types are experimental and possibly buggy");
1305 self.context.parse_sess.span_diagnostic.span_warn(attr.span,
1306 "the `#[simd]` attribute \
1307 is deprecated, use \
1308 `#[repr(simd)]` instead");
1310 if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
1311 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1312 if item.check_name("simd") {
1313 gate_feature_post!(&self, repr_simd, attr.span,
1314 "SIMD types are experimental and possibly buggy");
1316 if item.check_name("align") {
1317 gate_feature_post!(&self, repr_align, attr.span,
1318 "the struct `#[repr(align(u16))]` attribute \
1325 ast::ItemKind::DefaultImpl(..) => {
1326 gate_feature_post!(&self, optin_builtin_traits,
1328 "default trait implementations are experimental \
1329 and possibly buggy");
1332 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
1333 if polarity == ast::ImplPolarity::Negative {
1334 gate_feature_post!(&self, optin_builtin_traits,
1336 "negative trait bounds are not yet fully implemented; \
1337 use marker types for now");
1340 if let ast::Defaultness::Default = defaultness {
1341 gate_feature_post!(&self, specialization,
1343 "specialization is unstable");
1346 for impl_item in impl_items {
1347 if let ast::ImplItemKind::Method(..) = impl_item.node {
1348 if let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") {
1349 gate_feature_post!(&self, fn_must_use, attr.span,
1350 "`#[must_use]` on methods is experimental",
1351 GateStrength::Soft);
1357 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1358 let msg = "`macro` is experimental";
1359 gate_feature_post!(&self, decl_macro, i.span, msg);
1365 visit::walk_item(self, i);
1368 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1369 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1370 Some(val) => val.as_str().starts_with("llvm."),
1374 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1375 "linking to LLVM intrinsics is experimental");
1378 visit::walk_foreign_item(self, i)
1381 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1383 ast::TyKind::BareFn(ref bare_fn_ty) => {
1384 self.check_abi(bare_fn_ty.abi, ty.span);
1386 ast::TyKind::ImplTrait(..) => {
1387 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1388 "`impl Trait` is experimental");
1390 ast::TyKind::Never => {
1391 gate_feature_post!(&self, never_type, ty.span,
1392 "The `!` type is experimental");
1396 visit::walk_ty(self, ty)
1399 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1400 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1401 if output_ty.node != ast::TyKind::Never {
1402 self.visit_ty(output_ty)
1407 fn visit_expr(&mut self, e: &'a ast::Expr) {
1409 ast::ExprKind::Box(_) => {
1410 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1412 ast::ExprKind::Type(..) => {
1413 gate_feature_post!(&self, type_ascription, e.span,
1414 "type ascription is experimental");
1416 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1417 gate_feature_post!(&self, inclusive_range_syntax,
1419 "inclusive range syntax is experimental");
1421 ast::ExprKind::InPlace(..) => {
1422 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1424 ast::ExprKind::Yield(..) => {
1425 gate_feature_post!(&self, generators,
1427 "yield syntax is experimental");
1429 ast::ExprKind::Lit(ref lit) => {
1430 if let ast::LitKind::Int(_, ref ty) = lit.node {
1432 ast::LitIntType::Signed(ast::IntTy::I128) |
1433 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1434 gate_feature_post!(&self, i128_type, e.span,
1435 "128-bit integers are not stable");
1441 ast::ExprKind::Catch(_) => {
1442 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1446 visit::walk_expr(self, e);
1449 fn visit_arm(&mut self, arm: &'a ast::Arm) {
1450 if let Some(span) = arm.beginning_vert {
1451 gate_feature_post!(&self, match_beginning_vert,
1453 "Use of a '|' at the beginning of a match arm is experimental")
1455 visit::walk_arm(self, arm)
1458 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1459 match pattern.node {
1460 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1461 gate_feature_post!(&self, advanced_slice_patterns,
1463 "multiple-element slice matches anywhere \
1464 but at the end of a slice (e.g. \
1465 `[0, ..xs, 0]`) are experimental")
1467 PatKind::Slice(..) => {
1468 gate_feature_post!(&self, slice_patterns,
1470 "slice pattern syntax is experimental");
1472 PatKind::Box(..) => {
1473 gate_feature_post!(&self, box_patterns,
1475 "box pattern syntax is experimental");
1477 PatKind::Range(_, _, RangeEnd::Excluded) => {
1478 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1479 "exclusive range pattern syntax is experimental");
1483 visit::walk_pat(self, pattern)
1486 fn visit_fn(&mut self,
1487 fn_kind: FnKind<'a>,
1488 fn_decl: &'a ast::FnDecl,
1491 // check for const fn declarations
1492 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1494 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1496 // stability of const fn methods are covered in
1497 // visit_trait_item and visit_impl_item below; this is
1498 // because default methods don't pass through this
1502 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1503 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1504 self.check_abi(abi, span);
1508 visit::walk_fn(self, fn_kind, fn_decl, span);
1511 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1513 ast::TraitItemKind::Method(ref sig, ref block) => {
1514 if block.is_none() {
1515 self.check_abi(sig.abi, ti.span);
1517 if sig.constness.node == ast::Constness::Const {
1518 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1521 ast::TraitItemKind::Type(_, Some(_)) => {
1522 gate_feature_post!(&self, associated_type_defaults, ti.span,
1523 "associated type defaults are unstable");
1527 visit::walk_trait_item(self, ti);
1530 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1531 if ii.defaultness == ast::Defaultness::Default {
1532 gate_feature_post!(&self, specialization,
1534 "specialization is unstable");
1538 ast::ImplItemKind::Method(ref sig, _) => {
1539 if sig.constness.node == ast::Constness::Const {
1540 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1545 visit::walk_impl_item(self, ii);
1548 fn visit_generics(&mut self, g: &'a ast::Generics) {
1549 for t in &g.ty_params {
1550 if !t.attrs.is_empty() {
1551 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1552 "attributes on type parameter bindings are experimental");
1555 visit::walk_generics(self, g)
1558 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1559 if !lifetime_def.attrs.is_empty() {
1560 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1561 "attributes on lifetime bindings are experimental");
1563 visit::walk_lifetime_def(self, lifetime_def)
1567 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1568 let mut features = Features::new();
1570 let mut feature_checker = MutexFeatureChecker::default();
1572 for attr in krate_attrs {
1573 if !attr.check_name("feature") {
1577 match attr.meta_item_list() {
1579 span_err!(span_handler, attr.span, E0555,
1580 "malformed feature attribute, expected #![feature(...)]");
1584 let name = if let Some(word) = mi.word() {
1587 span_err!(span_handler, mi.span, E0556,
1588 "malformed feature, expected just one word");
1592 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1593 .find(|& &(n, _, _, _)| name == n) {
1594 set(&mut features, mi.span);
1595 feature_checker.collect(&features, mi.span);
1597 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1598 .find(|& &(n, _, _)| name == n)
1599 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1600 .find(|& &(n, _, _)| name == n)) {
1601 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1603 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1604 .find(|& &(n, _, _)| name == n) {
1605 features.declared_stable_lang_features.push((name, mi.span));
1607 features.declared_lib_features.push((name, mi.span));
1614 feature_checker.check(span_handler);
1619 // A collector for mutually-exclusive features and their flag spans
1621 struct MutexFeatureChecker {
1622 proc_macro: Option<Span>,
1623 custom_attribute: Option<Span>,
1626 impl MutexFeatureChecker {
1627 // If this method turns out to be a hotspot due to branching,
1628 // the branching can be eliminated by modifying `set!()` to set these spans
1629 // only for the features that need to be checked for mutual exclusion.
1630 fn collect(&mut self, features: &Features, span: Span) {
1631 if features.proc_macro {
1632 // If self.proc_macro is None, set to Some(span)
1633 self.proc_macro = self.proc_macro.or(Some(span));
1636 if features.custom_attribute {
1637 self.custom_attribute = self.custom_attribute.or(Some(span));
1641 fn check(self, handler: &Handler) {
1642 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1643 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1644 `#![feature(custom_attribute)] at the same time")
1645 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1653 pub fn check_crate(krate: &ast::Crate,
1655 features: &Features,
1656 plugin_attributes: &[(String, AttributeType)],
1657 unstable: UnstableFeatures) {
1658 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1664 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1667 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1668 pub enum UnstableFeatures {
1669 /// Hard errors for unstable features are active, as on
1670 /// beta/stable channels.
1672 /// Allow features to be activated, as on nightly.
1674 /// Errors are bypassed for bootstrapping. This is required any time
1675 /// during the build that feature-related lints are set to warn or above
1676 /// because the build turns on warnings-as-errors and uses lots of unstable
1677 /// features. As a result, this is always required for building Rust itself.
1681 impl UnstableFeatures {
1682 pub fn from_environment() -> UnstableFeatures {
1683 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1684 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1685 // Whether we should enable unstable features for bootstrapping
1686 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1687 match (disable_unstable_features, bootstrap) {
1688 (_, true) => UnstableFeatures::Cheat,
1689 (true, _) => UnstableFeatures::Disallow,
1690 (false, _) => UnstableFeatures::Allow
1694 pub fn is_nightly_build(&self) -> bool {
1696 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1702 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1703 unstable: UnstableFeatures) {
1704 let allow_features = match unstable {
1705 UnstableFeatures::Allow => true,
1706 UnstableFeatures::Disallow => false,
1707 UnstableFeatures::Cheat => true
1709 if !allow_features {
1710 for attr in &krate.attrs {
1711 if attr.check_name("feature") {
1712 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1713 span_err!(span_handler, attr.span, E0554,
1714 "#![feature] may not be used on the {} release channel",