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: The featureck.py script parses this information directly out of the source
116 // 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, advanced_slice_patterns, "1.0.0", Some(23121)),
141 (active, box_syntax, "1.0.0", Some(27779)),
142 (active, placement_in_syntax, "1.0.0", Some(27779)),
143 (active, unboxed_closures, "1.0.0", Some(29625)),
145 (active, fundamental, "1.0.0", Some(29635)),
146 (active, main, "1.0.0", Some(29634)),
147 (active, needs_allocator, "1.4.0", Some(27389)),
148 (active, on_unimplemented, "1.0.0", Some(29628)),
149 (active, plugin, "1.0.0", Some(29597)),
150 (active, simd_ffi, "1.0.0", Some(27731)),
151 (active, start, "1.0.0", Some(29633)),
152 (active, structural_match, "1.8.0", Some(31434)),
153 (active, panic_runtime, "1.10.0", Some(32837)),
154 (active, needs_panic_runtime, "1.10.0", Some(32837)),
156 // OIBIT specific features
157 (active, optin_builtin_traits, "1.0.0", Some(13231)),
159 // macro reexport needs more discussion and stabilization
160 (active, macro_reexport, "1.0.0", Some(29638)),
162 // Allows use of #[staged_api]
164 (active, staged_api, "1.0.0", None),
166 // Allows using #![no_core]
167 (active, no_core, "1.3.0", Some(29639)),
169 // Allows using `box` in patterns; RFC 469
170 (active, box_patterns, "1.0.0", Some(29641)),
172 // Allows using the unsafe_destructor_blind_to_params attribute;
174 (active, dropck_parametricity, "1.3.0", Some(28498)),
176 // Allows using the may_dangle attribute; RFC 1327
177 (active, dropck_eyepatch, "1.10.0", Some(34761)),
179 // Allows the use of custom attributes; RFC 572
180 (active, custom_attribute, "1.0.0", Some(29642)),
182 // Allows the use of #[derive(Anything)] as sugar for
183 // #[derive_Anything].
184 (active, custom_derive, "1.0.0", Some(29644)),
186 // Allows the use of rustc_* attributes; RFC 572
187 (active, rustc_attrs, "1.0.0", Some(29642)),
189 // Allows the use of #[allow_internal_unstable]. This is an
190 // attribute on macro_rules! and can't use the attribute handling
191 // below (it has to be checked before expansion possibly makes
192 // macros disappear).
195 (active, allow_internal_unstable, "1.0.0", None),
197 // Allows the use of #[allow_internal_unsafe]. This is an
198 // attribute on macro_rules! and can't use the attribute handling
199 // below (it has to be checked before expansion possibly makes
200 // macros disappear).
203 (active, allow_internal_unsafe, "1.0.0", None),
205 // #23121. Array patterns have some hazards yet.
206 (active, slice_patterns, "1.0.0", Some(23121)),
208 // Allows the definition of `const fn` functions.
209 (active, const_fn, "1.2.0", Some(24111)),
211 // Allows indexing into constant arrays.
212 (active, const_indexing, "1.4.0", Some(29947)),
214 // Allows using #[prelude_import] on glob `use` items.
217 (active, prelude_import, "1.2.0", None),
219 // Allows default type parameters to influence type inference.
220 (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
222 // Allows associated type defaults
223 (active, associated_type_defaults, "1.2.0", Some(29661)),
225 // allow `repr(simd)`, and importing the various simd intrinsics
226 (active, repr_simd, "1.4.0", Some(27731)),
228 // Allows cfg(target_feature = "...").
229 (active, cfg_target_feature, "1.4.0", Some(29717)),
231 // allow `extern "platform-intrinsic" { ... }`
232 (active, platform_intrinsics, "1.4.0", Some(27731)),
235 // rust runtime internal
236 (active, unwind_attributes, "1.4.0", None),
238 // allow the use of `#[naked]` on functions.
239 (active, naked_functions, "1.9.0", Some(32408)),
241 // allow `#[no_debug]`
242 (active, no_debug, "1.5.0", Some(29721)),
244 // allow `#[omit_gdb_pretty_printer_section]`
246 (active, omit_gdb_pretty_printer_section, "1.5.0", None),
248 // Allows cfg(target_vendor = "...").
249 (active, cfg_target_vendor, "1.5.0", Some(29718)),
251 // Allow attributes on expressions and non-item statements
252 (active, stmt_expr_attributes, "1.6.0", Some(15701)),
254 // allow using type ascription in expressions
255 (active, type_ascription, "1.6.0", Some(23416)),
257 // Allows cfg(target_thread_local)
258 (active, cfg_target_thread_local, "1.7.0", Some(29594)),
261 (active, abi_vectorcall, "1.7.0", None),
264 (active, inclusive_range_syntax, "1.7.0", Some(28237)),
267 (active, exclusive_range_pattern, "1.11.0", Some(37854)),
269 // impl specialization (RFC 1210)
270 (active, specialization, "1.7.0", Some(31844)),
272 // Allow Drop types in statics/const functions (RFC 1440)
273 (active, drop_types_in_const, "1.9.0", Some(33156)),
275 // Allows cfg(target_has_atomic = "...").
276 (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
278 // Allows `impl Trait` in function return types.
279 (active, conservative_impl_trait, "1.12.0", Some(34511)),
282 (active, never_type, "1.13.0", Some(35121)),
284 // Allows all literals in attribute lists and values of key-value pairs.
285 (active, attr_literals, "1.13.0", Some(34981)),
287 // Allows the sysV64 ABI to be specified on all platforms
288 // instead of just the platforms on which it is the C ABI
289 (active, abi_sysv64, "1.13.0", Some(36167)),
291 // Allows untagged unions `union U { ... }`
292 (active, untagged_unions, "1.13.0", Some(32836)),
294 // Used to identify the `compiler_builtins` crate
296 (active, compiler_builtins, "1.13.0", None),
298 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
299 (active, generic_param_attrs, "1.11.0", Some(34761)),
301 // Allows #[link(..., cfg(..))]
302 (active, link_cfg, "1.14.0", Some(37406)),
304 (active, use_extern_macros, "1.15.0", Some(35896)),
306 // Allows #[target_feature(...)]
307 (active, target_feature, "1.15.0", None),
309 // `extern "ptx-*" fn()`
310 (active, abi_ptx, "1.15.0", None),
313 (active, i128_type, "1.16.0", Some(35118)),
315 // The `unadjusted` ABI. Perma unstable.
316 (active, abi_unadjusted, "1.16.0", None),
318 // Procedural macros 2.0.
319 (active, proc_macro, "1.16.0", Some(38356)),
321 // Declarative macros 2.0 (`macro`).
322 (active, decl_macro, "1.17.0", Some(39412)),
324 // Allows #[link(kind="static-nobundle"...]
325 (active, static_nobundle, "1.16.0", Some(37403)),
327 // `extern "msp430-interrupt" fn()`
328 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
330 // Used to identify crates that contain sanitizer runtimes
332 (active, sanitizer_runtime, "1.17.0", None),
334 // Used to identify crates that contain the profiler runtime
336 (active, profiler_runtime, "1.18.0", None),
338 // `extern "x86-interrupt" fn()`
339 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
342 // Allows the `catch {...}` expression
343 (active, catch_expr, "1.17.0", Some(31436)),
345 // Allows `repr(align(u16))` struct attribute (RFC 1358)
346 (active, repr_align, "1.17.0", Some(33626)),
348 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
349 (active, rvalue_static_promotion, "1.15.1", Some(38865)),
351 // Used to preserve symbols (see llvm.used)
352 (active, used, "1.18.0", Some(40289)),
354 // Allows module-level inline assembly by way of global_asm!()
355 (active, global_asm, "1.18.0", Some(35119)),
357 // Allows overlapping impls of marker traits
358 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
360 // Allows use of the :vis macro fragment specifier
361 (active, macro_vis_matcher, "1.18.0", Some(41022)),
364 (active, abi_thiscall, "1.19.0", None),
366 // Allows a test to fail without failing the whole suite
367 (active, allow_fail, "1.19.0", Some(42219)),
369 // Allows unsized tuple coercion.
370 (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
372 // global allocators and their internals
373 (active, global_allocator, "1.20.0", None),
374 (active, allocator_internals, "1.20.0", None),
378 (removed, import_shadowing, "1.0.0", None),
379 (removed, managed_boxes, "1.0.0", None),
380 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
381 (removed, negate_unsigned, "1.0.0", Some(29645)),
382 (removed, reflect, "1.0.0", Some(27749)),
383 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
384 (removed, opt_out_copy, "1.0.0", None),
385 (removed, quad_precision_float, "1.0.0", None),
386 (removed, struct_inherit, "1.0.0", None),
387 (removed, test_removed_feature, "1.0.0", None),
388 (removed, visible_private_types, "1.0.0", None),
389 (removed, unsafe_no_drop_flag, "1.0.0", None),
390 // Allows using items which are missing stability attributes
392 (removed, unmarked_api, "1.0.0", None),
393 (removed, pushpop_unsafe, "1.2.0", None),
394 (removed, allocator, "1.0.0", None),
398 (stable_removed, no_stack_check, "1.0.0", None),
402 (accepted, associated_types, "1.0.0", None),
403 // allow overloading augmented assignment operations like `a += b`
404 (accepted, augmented_assignments, "1.8.0", Some(28235)),
405 // allow empty structs and enum variants with braces
406 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
407 (accepted, default_type_params, "1.0.0", None),
408 (accepted, globs, "1.0.0", None),
409 (accepted, if_let, "1.0.0", None),
410 // A temporary feature gate used to enable parser extensions needed
411 // to bootstrap fix for #5723.
412 (accepted, issue_5723_bootstrap, "1.0.0", None),
413 (accepted, macro_rules, "1.0.0", None),
414 // Allows using #![no_std]
415 (accepted, no_std, "1.6.0", None),
416 (accepted, slicing_syntax, "1.0.0", None),
417 (accepted, struct_variant, "1.0.0", None),
418 // These are used to test this portion of the compiler, they don't actually
420 (accepted, test_accepted_feature, "1.0.0", None),
421 (accepted, tuple_indexing, "1.0.0", None),
422 // Allows macros to appear in the type position.
423 (accepted, type_macros, "1.13.0", Some(27245)),
424 (accepted, while_let, "1.0.0", None),
425 // Allows `#[deprecated]` attribute
426 (accepted, deprecated, "1.9.0", Some(29935)),
428 (accepted, question_mark, "1.13.0", Some(31436)),
429 // Allows `..` in tuple (struct) patterns
430 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
431 (accepted, item_like_imports, "1.15.0", Some(35120)),
432 // Allows using `Self` and associated types in struct expressions and patterns.
433 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
434 // elide `'static` lifetimes in `static`s and `const`s
435 (accepted, static_in_const, "1.17.0", Some(35897)),
436 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
437 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
438 // Allows the definition recursive static items.
439 (accepted, static_recursion, "1.17.0", Some(29719)),
440 // pub(restricted) visibilities (RFC 1422)
441 (accepted, pub_restricted, "1.18.0", Some(32409)),
442 // The #![windows_subsystem] attribute
443 (accepted, windows_subsystem, "1.18.0", Some(37499)),
444 // Allows `break {expr}` with a value inside `loop`s.
445 (accepted, loop_break_value, "1.19.0", Some(37339)),
446 // Permits numeric fields in struct expressions and patterns.
447 (accepted, relaxed_adts, "1.19.0", Some(35626)),
448 // Coerces non capturing closures to function pointers
449 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
450 // Allows attributes on struct literal fields.
451 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
452 // Allows the definition of associated constants in `trait` or `impl`
454 (accepted, associated_consts, "1.20.0", Some(29646)),
455 // Usage of the `compile_error!` macro
456 (accepted, compile_error, "1.20.0", Some(40872)),
459 // If you change this, please modify src/doc/unstable-book as well. You must
460 // move that documentation into the relevant place in the other docs, and
461 // remove the chapter on the flag.
463 #[derive(PartialEq, Copy, Clone, Debug)]
464 pub enum AttributeType {
465 /// Normal, builtin attribute that is consumed
466 /// by the compiler before the unused_attribute check
469 /// Builtin attribute that may not be consumed by the compiler
470 /// before the unused_attribute check. These attributes
471 /// will be ignored by the unused_attribute lint
474 /// Builtin attribute that is only allowed at the crate level
478 pub enum AttributeGate {
479 /// Is gated by a given feature gate, reason
480 /// and function to check if enabled
481 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
483 /// Ungated attribute, can be used on all release channels
488 fn is_deprecated(&self) -> bool {
490 Gated(Stability::Deprecated(_), ..) => true,
496 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
499 // Argument is tracking issue link.
500 Deprecated(&'static str),
504 impl ::std::fmt::Debug for AttributeGate {
505 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
507 Gated(ref stab, name, expl, _) =>
508 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
509 Ungated => write!(fmt, "Ungated")
514 macro_rules! cfg_fn {
515 ($field: ident) => {{
516 fn f(features: &Features) -> bool {
519 f as fn(&Features) -> bool
523 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
524 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
527 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
528 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
531 // Attributes that have a special meaning to rustc or rustdoc
532 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
535 ("warn", Normal, Ungated),
536 ("allow", Normal, Ungated),
537 ("forbid", Normal, Ungated),
538 ("deny", Normal, Ungated),
540 ("macro_reexport", Normal, Ungated),
541 ("macro_use", Normal, Ungated),
542 ("macro_export", Normal, Ungated),
543 ("plugin_registrar", Normal, Ungated),
545 ("cfg", Normal, Ungated),
546 ("cfg_attr", Normal, Ungated),
547 ("main", Normal, Ungated),
548 ("start", Normal, Ungated),
549 ("test", Normal, Ungated),
550 ("bench", Normal, Ungated),
551 ("simd", Normal, Ungated),
552 ("repr", Normal, Ungated),
553 ("path", Normal, Ungated),
554 ("abi", Normal, Ungated),
555 ("automatically_derived", Normal, Ungated),
556 ("no_mangle", Normal, Ungated),
557 ("no_link", Normal, Ungated),
558 ("derive", Normal, Ungated),
559 ("should_panic", Normal, Ungated),
560 ("ignore", Normal, Ungated),
561 ("no_implicit_prelude", Normal, Ungated),
562 ("reexport_test_harness_main", Normal, Ungated),
563 ("link_args", Normal, Gated(Stability::Unstable,
565 "the `link_args` attribute is experimental and not \
566 portable across platforms, it is recommended to \
567 use `#[link(name = \"foo\")] instead",
568 cfg_fn!(link_args))),
569 ("macro_escape", Normal, Ungated),
572 ("structural_match", Whitelisted, Gated(Stability::Unstable,
574 "the semantics of constant patterns is \
576 cfg_fn!(structural_match))),
578 ("plugin", CrateLevel, Gated(Stability::Unstable,
580 "compiler plugins are experimental \
584 ("no_std", CrateLevel, Ungated),
585 ("no_core", CrateLevel, Gated(Stability::Unstable,
587 "no_core is experimental",
589 ("lang", Normal, Gated(Stability::Unstable,
591 "language items are subject to change",
592 cfg_fn!(lang_items))),
593 ("linkage", Whitelisted, Gated(Stability::Unstable,
595 "the `linkage` attribute is experimental \
596 and not portable across platforms",
598 ("thread_local", Whitelisted, Gated(Stability::Unstable,
600 "`#[thread_local]` is an experimental feature, and does \
601 not currently handle destructors. There is no \
602 corresponding `#[task_local]` mapping to the task \
604 cfg_fn!(thread_local))),
606 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
608 "the `#[rustc_on_unimplemented]` attribute \
609 is an experimental feature",
610 cfg_fn!(on_unimplemented))),
611 ("global_allocator", Normal, Gated(Stability::Unstable,
613 "the `#[global_allocator]` attribute is \
614 an experimental feature",
615 cfg_fn!(global_allocator))),
616 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
617 "allocator_internals",
618 "the `#[default_lib_allocator]` \
619 attribute is an experimental feature",
620 cfg_fn!(allocator_internals))),
621 ("needs_allocator", Normal, Gated(Stability::Unstable,
622 "allocator_internals",
623 "the `#[needs_allocator]` \
624 attribute is an experimental \
626 cfg_fn!(allocator_internals))),
627 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
629 "the `#[panic_runtime]` attribute is \
630 an experimental feature",
631 cfg_fn!(panic_runtime))),
632 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
633 "needs_panic_runtime",
634 "the `#[needs_panic_runtime]` \
635 attribute is an experimental \
637 cfg_fn!(needs_panic_runtime))),
638 ("rustc_variance", Normal, Gated(Stability::Unstable,
640 "the `#[rustc_variance]` attribute \
641 is just used for rustc unit tests \
642 and will never be stable",
643 cfg_fn!(rustc_attrs))),
644 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
646 "the `#[rustc_error]` attribute \
647 is just used for rustc unit tests \
648 and will never be stable",
649 cfg_fn!(rustc_attrs))),
650 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
652 "the `#[rustc_if_this_changed]` attribute \
653 is just used for rustc unit tests \
654 and will never be stable",
655 cfg_fn!(rustc_attrs))),
656 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
658 "the `#[rustc_if_this_changed]` attribute \
659 is just used for rustc unit tests \
660 and will never be stable",
661 cfg_fn!(rustc_attrs))),
662 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
664 "the `#[rustc_dirty]` attribute \
665 is just used for rustc unit tests \
666 and will never be stable",
667 cfg_fn!(rustc_attrs))),
668 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
670 "the `#[rustc_clean]` attribute \
671 is just used for rustc unit tests \
672 and will never be stable",
673 cfg_fn!(rustc_attrs))),
674 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
676 "the `#[rustc_metadata_dirty]` attribute \
677 is just used for rustc unit tests \
678 and will never be stable",
679 cfg_fn!(rustc_attrs))),
680 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
682 "the `#[rustc_metadata_clean]` attribute \
683 is just used for rustc unit tests \
684 and will never be stable",
685 cfg_fn!(rustc_attrs))),
686 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
689 is just used for rustc unit tests \
690 and will never be stable",
691 cfg_fn!(rustc_attrs))),
692 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
695 is just used for rustc unit tests \
696 and will never be stable",
697 cfg_fn!(rustc_attrs))),
698 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
700 "internal rustc attributes will never be stable",
701 cfg_fn!(rustc_attrs))),
702 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
704 "internal rustc attributes will never be stable",
705 cfg_fn!(rustc_attrs))),
706 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
708 "the `#[rustc_mir]` attribute \
709 is just used for rustc unit tests \
710 and will never be stable",
711 cfg_fn!(rustc_attrs))),
712 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
714 "the `#[rustc_inherit_overflow_checks]` \
715 attribute is just used to control \
716 overflow checking behavior of several \
717 libcore functions that are inlined \
718 across crates and will never be stable",
719 cfg_fn!(rustc_attrs))),
720 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
722 "the `#[compiler_builtins]` attribute is used to \
723 identify the `compiler_builtins` crate which \
724 contains compiler-rt intrinsics and will never be \
726 cfg_fn!(compiler_builtins))),
727 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
729 "the `#[sanitizer_runtime]` attribute is used to \
730 identify crates that contain the runtime of a \
731 sanitizer and will never be stable",
732 cfg_fn!(sanitizer_runtime))),
733 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
735 "the `#[profiler_runtime]` attribute is used to \
736 identify the `profiler_builtins` crate which \
737 contains the profiler runtime and will never be \
739 cfg_fn!(profiler_runtime))),
741 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
742 "allow_internal_unstable",
743 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
744 cfg_fn!(allow_internal_unstable))),
746 ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
747 "allow_internal_unsafe",
748 EXPLAIN_ALLOW_INTERNAL_UNSAFE,
749 cfg_fn!(allow_internal_unsafe))),
751 ("fundamental", Whitelisted, Gated(Stability::Unstable,
753 "the `#[fundamental]` attribute \
754 is an experimental feature",
755 cfg_fn!(fundamental))),
757 ("proc_macro_derive", Normal, Ungated),
759 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
761 "internal implementation detail",
762 cfg_fn!(rustc_attrs))),
764 // FIXME: #14408 whitelist docs since rustdoc looks at them
765 ("doc", Whitelisted, Ungated),
767 // FIXME: #14406 these are processed in trans, which happens after the
769 ("cold", Whitelisted, Ungated),
770 ("naked", Whitelisted, Gated(Stability::Unstable,
772 "the `#[naked]` attribute \
773 is an experimental feature",
774 cfg_fn!(naked_functions))),
775 ("target_feature", Whitelisted, Gated(
776 Stability::Unstable, "target_feature",
777 "the `#[target_feature]` attribute is an experimental feature",
778 cfg_fn!(target_feature))),
779 ("export_name", Whitelisted, Ungated),
780 ("inline", Whitelisted, Ungated),
781 ("link", Whitelisted, Ungated),
782 ("link_name", Whitelisted, Ungated),
783 ("link_section", Whitelisted, Ungated),
784 ("no_builtins", Whitelisted, Ungated),
785 ("no_mangle", Whitelisted, Ungated),
786 ("no_debug", Whitelisted, Gated(
787 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
789 "the `#[no_debug]` attribute is an experimental feature",
791 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
792 "omit_gdb_pretty_printer_section",
793 "the `#[omit_gdb_pretty_printer_section]` \
794 attribute is just used for the Rust test \
796 cfg_fn!(omit_gdb_pretty_printer_section))),
797 ("unsafe_destructor_blind_to_params",
799 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
800 "dropck_parametricity",
801 "unsafe_destructor_blind_to_params has been replaced by \
802 may_dangle and will be removed in the future",
803 cfg_fn!(dropck_parametricity))),
806 Gated(Stability::Unstable,
808 "may_dangle has unstable semantics and may be removed in the future",
809 cfg_fn!(dropck_eyepatch))),
810 ("unwind", Whitelisted, Gated(Stability::Unstable,
812 "#[unwind] is experimental",
813 cfg_fn!(unwind_attributes))),
814 ("used", Whitelisted, Gated(
815 Stability::Unstable, "used",
816 "the `#[used]` attribute is an experimental feature",
820 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
822 "`#[prelude_import]` is for use by rustc only",
823 cfg_fn!(prelude_import))),
825 // FIXME: #14407 these are only looked at on-demand so we can't
826 // guarantee they'll have already been checked
827 ("rustc_deprecated", Whitelisted, Ungated),
828 ("must_use", Whitelisted, Ungated),
829 ("stable", Whitelisted, Ungated),
830 ("unstable", Whitelisted, Ungated),
831 ("deprecated", Normal, Ungated),
833 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
835 "unboxed_closures are still evolving",
836 cfg_fn!(unboxed_closures))),
838 ("windows_subsystem", Whitelisted, Ungated),
840 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
842 "attribute proc macros are currently unstable",
843 cfg_fn!(proc_macro))),
845 ("proc_macro", Normal, Gated(Stability::Unstable,
847 "function-like proc macros are currently unstable",
848 cfg_fn!(proc_macro))),
850 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
851 "rustc_derive_registrar",
852 "used internally by rustc",
853 cfg_fn!(rustc_attrs))),
855 ("allow_fail", Normal, Gated(Stability::Unstable,
857 "allow_fail attribute is currently unstable",
858 cfg_fn!(allow_fail))),
860 // Crate level attributes
861 ("crate_name", CrateLevel, Ungated),
862 ("crate_type", CrateLevel, Ungated),
863 ("crate_id", CrateLevel, Ungated),
864 ("feature", CrateLevel, Ungated),
865 ("no_start", CrateLevel, Ungated),
866 ("no_main", CrateLevel, Ungated),
867 ("no_builtins", CrateLevel, Ungated),
868 ("recursion_limit", CrateLevel, Ungated),
869 ("type_length_limit", CrateLevel, Ungated),
872 // cfg(...)'s that are feature gated
873 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
874 // (name in cfg, feature, function to check if the feature is enabled)
875 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
876 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
877 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
878 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
881 #[derive(Debug, Eq, PartialEq)]
882 pub struct GatedCfg {
888 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
889 let name = cfg.name().as_str();
891 .position(|info| info.0 == name)
900 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
901 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
902 if !has_feature(features) && !self.span.allows_unstable() {
903 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
904 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
910 features: &'a Features,
911 parse_sess: &'a ParseSess,
912 plugin_attributes: &'a [(String, AttributeType)],
915 macro_rules! gate_feature_fn {
916 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
917 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
918 let has_feature: bool = has_feature(&$cx.features);
919 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
920 if !has_feature && !span.allows_unstable() {
921 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
926 macro_rules! gate_feature {
927 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
928 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
932 impl<'a> Context<'a> {
933 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
934 debug!("check_attribute(attr = {:?})", attr);
935 let name = unwrap_or!(attr.name(), return).as_str();
936 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
938 if let Gated(_, name, desc, ref has_feature) = *gateage {
939 gate_feature_fn!(self, has_feature, attr.span, name, desc);
941 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
945 for &(ref n, ref ty) in self.plugin_attributes {
946 if attr.path == &**n {
947 // Plugins can't gate attributes, so we don't check for it
948 // unlike the code above; we only use this loop to
949 // short-circuit to avoid the checks below
950 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
954 if name.starts_with("rustc_") {
955 gate_feature!(self, rustc_attrs, attr.span,
956 "unless otherwise specified, attributes \
957 with the prefix `rustc_` \
958 are reserved for internal compiler diagnostics");
959 } else if name.starts_with("derive_") {
960 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
961 } else if !attr::is_known(attr) {
962 // Only run the custom attribute lint during regular
963 // feature gate checking. Macro gating runs
964 // before the plugin attributes are registered
965 // so we skip this then
967 gate_feature!(self, custom_attribute, attr.span,
968 &format!("The attribute `{}` is currently \
969 unknown to the compiler and \
971 added to it in the future",
978 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
979 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
980 cx.check_attribute(attr, true);
983 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
984 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
987 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
988 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
990 // FIXME (#28244): enforce that active features have issue numbers
991 // assert!(issue.is_some())
994 // search in Accepted, Removed, or Stable Removed features
995 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
996 .find(|t| t.0 == feature);
998 Some(&(_, _, issue)) => issue,
999 None => panic!("Feature `{}` is not declared anywhere", feature),
1004 pub enum GateIssue {
1006 Library(Option<u32>)
1009 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1011 feature_err(sess, feature, span, issue, explain).emit();
1014 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1015 explain: &str) -> DiagnosticBuilder<'a> {
1016 let diag = &sess.span_diagnostic;
1018 let issue = match issue {
1019 GateIssue::Language => find_lang_feature_issue(feature),
1020 GateIssue::Library(lib) => lib,
1023 let mut err = if let Some(n) = issue {
1024 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
1026 diag.struct_span_err(span, explain)
1029 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1030 if sess.unstable_features.is_nightly_build() {
1031 err.help(&format!("add #![feature({})] to the \
1032 crate attributes to enable",
1039 const EXPLAIN_BOX_SYNTAX: &'static str =
1040 "box expression syntax is experimental; you can call `Box::new` instead.";
1042 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1043 "attributes on non-item statements and expressions are experimental.";
1045 pub const EXPLAIN_ASM: &'static str =
1046 "inline assembly is not stable enough for use and is subject to change";
1048 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1049 "`global_asm!` is not stable enough for use and is subject to change";
1051 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1052 "`log_syntax!` is not stable enough for use and is subject to change";
1054 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1055 "`concat_idents` is not stable enough for use and is subject to change";
1057 pub const EXPLAIN_TRACE_MACROS: &'static str =
1058 "`trace_macros` is not stable enough for use and is subject to change";
1059 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1060 "allow_internal_unstable side-steps feature gating and stability checks";
1061 pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
1062 "allow_internal_unsafe side-steps the unsafe_code lint";
1064 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1065 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1067 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1068 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1069 Prefer using procedural macro custom derive.";
1071 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1072 "attributes of the form `#[derive_*]` are reserved for the compiler";
1074 pub const EXPLAIN_VIS_MATCHER: &'static str =
1075 ":vis fragment specifier is experimental and subject to change";
1077 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1078 "placement-in expression syntax is experimental and subject to change.";
1080 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1081 "Unsized tuple coercion is not stable enough for use and is subject to change";
1083 struct PostExpansionVisitor<'a> {
1084 context: &'a Context<'a>,
1087 macro_rules! gate_feature_post {
1088 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1089 let (cx, span) = ($cx, $span);
1090 if !span.allows_unstable() {
1091 gate_feature!(cx.context, $feature, span, $explain)
1096 impl<'a> PostExpansionVisitor<'a> {
1097 fn check_abi(&self, abi: Abi, span: Span) {
1099 Abi::RustIntrinsic => {
1100 gate_feature_post!(&self, intrinsics, span,
1101 "intrinsics are subject to change");
1103 Abi::PlatformIntrinsic => {
1104 gate_feature_post!(&self, platform_intrinsics, span,
1105 "platform intrinsics are experimental and possibly buggy");
1107 Abi::Vectorcall => {
1108 gate_feature_post!(&self, abi_vectorcall, span,
1109 "vectorcall is experimental and subject to change");
1112 gate_feature_post!(&self, abi_thiscall, span,
1113 "thiscall is experimental and subject to change");
1116 gate_feature_post!(&self, unboxed_closures, span,
1117 "rust-call ABI is subject to change");
1120 gate_feature_post!(&self, abi_sysv64, span,
1121 "sysv64 ABI is experimental and subject to change");
1124 gate_feature_post!(&self, abi_ptx, span,
1125 "PTX ABIs are experimental and subject to change");
1127 Abi::Unadjusted => {
1128 gate_feature_post!(&self, abi_unadjusted, span,
1129 "unadjusted ABI is an implementation detail and perma-unstable");
1131 Abi::Msp430Interrupt => {
1132 gate_feature_post!(&self, abi_msp430_interrupt, span,
1133 "msp430-interrupt ABI is experimental and subject to change");
1135 Abi::X86Interrupt => {
1136 gate_feature_post!(&self, abi_x86_interrupt, span,
1137 "x86-interrupt ABI is experimental and subject to change");
1152 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1153 use ast::MetaItemKind::*;
1154 use ast::NestedMetaItemKind::*;
1158 NameValue(ref lit) => !lit.node.is_str(),
1159 List(ref list) => list.iter().any(|li| {
1161 MetaItem(ref mi) => contains_novel_literal(mi),
1168 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1169 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1170 if !attr.span.allows_unstable() {
1171 // check for gated attributes
1172 self.context.check_attribute(attr, false);
1175 if self.context.features.proc_macro && attr::is_known(attr) {
1179 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1180 if contains_novel_literal(&meta) {
1181 gate_feature_post!(&self, attr_literals, attr.span,
1182 "non-string literals in attributes, or string \
1183 literals in top-level positions, are experimental");
1187 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1188 if !name.as_str().is_ascii() {
1189 gate_feature_post!(&self, non_ascii_idents, sp,
1190 "non-ascii idents are not fully supported.");
1194 fn visit_item(&mut self, i: &'a ast::Item) {
1196 ast::ItemKind::ExternCrate(_) => {
1197 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1198 gate_feature_post!(&self, macro_reexport, i.span,
1199 "macros reexports are experimental \
1200 and possibly buggy");
1204 ast::ItemKind::ForeignMod(ref foreign_module) => {
1205 self.check_abi(foreign_module.abi, i.span);
1208 ast::ItemKind::Fn(..) => {
1209 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1210 gate_feature_post!(&self, plugin_registrar, i.span,
1211 "compiler plugins are experimental and possibly buggy");
1213 if attr::contains_name(&i.attrs[..], "start") {
1214 gate_feature_post!(&self, start, i.span,
1215 "a #[start] function is an experimental \
1216 feature whose signature may change \
1219 if attr::contains_name(&i.attrs[..], "main") {
1220 gate_feature_post!(&self, main, i.span,
1221 "declaration of a nonstandard #[main] \
1222 function may change over time, for now \
1223 a top-level `fn main()` is required");
1227 ast::ItemKind::Struct(..) => {
1228 if attr::contains_name(&i.attrs[..], "simd") {
1229 gate_feature_post!(&self, simd, i.span,
1230 "SIMD types are experimental and possibly buggy");
1231 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1232 "the `#[simd]` attribute \
1233 is deprecated, use \
1234 `#[repr(simd)]` instead");
1236 for attr in &i.attrs {
1237 if attr.path == "repr" {
1238 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1239 if item.check_name("simd") {
1240 gate_feature_post!(&self, repr_simd, i.span,
1241 "SIMD types are experimental \
1242 and possibly buggy");
1245 if item.check_name("align") {
1246 gate_feature_post!(&self, repr_align, i.span,
1247 "the struct `#[repr(align(u16))]` attribute \
1255 ast::ItemKind::DefaultImpl(..) => {
1256 gate_feature_post!(&self, optin_builtin_traits,
1258 "default trait implementations are experimental \
1259 and possibly buggy");
1262 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1263 if polarity == ast::ImplPolarity::Negative {
1264 gate_feature_post!(&self, optin_builtin_traits,
1266 "negative trait bounds are not yet fully implemented; \
1267 use marker types for now");
1270 if let ast::Defaultness::Default = defaultness {
1271 gate_feature_post!(&self, specialization,
1273 "specialization is unstable");
1277 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1278 let msg = "`macro` is experimental";
1279 gate_feature_post!(&self, decl_macro, i.span, msg);
1285 visit::walk_item(self, i);
1288 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1289 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1290 Some(val) => val.as_str().starts_with("llvm."),
1294 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1295 "linking to LLVM intrinsics is experimental");
1298 visit::walk_foreign_item(self, i)
1301 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1303 ast::TyKind::BareFn(ref bare_fn_ty) => {
1304 self.check_abi(bare_fn_ty.abi, ty.span);
1306 ast::TyKind::ImplTrait(..) => {
1307 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1308 "`impl Trait` is experimental");
1310 ast::TyKind::Never => {
1311 gate_feature_post!(&self, never_type, ty.span,
1312 "The `!` type is experimental");
1316 visit::walk_ty(self, ty)
1319 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1320 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1321 if output_ty.node != ast::TyKind::Never {
1322 self.visit_ty(output_ty)
1327 fn visit_expr(&mut self, e: &'a ast::Expr) {
1329 ast::ExprKind::Box(_) => {
1330 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1332 ast::ExprKind::Type(..) => {
1333 gate_feature_post!(&self, type_ascription, e.span,
1334 "type ascription is experimental");
1336 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1337 gate_feature_post!(&self, inclusive_range_syntax,
1339 "inclusive range syntax is experimental");
1341 ast::ExprKind::InPlace(..) => {
1342 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1344 ast::ExprKind::Lit(ref lit) => {
1345 if let ast::LitKind::Int(_, ref ty) = lit.node {
1347 ast::LitIntType::Signed(ast::IntTy::I128) |
1348 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1349 gate_feature_post!(&self, i128_type, e.span,
1350 "128-bit integers are not stable");
1356 ast::ExprKind::Catch(_) => {
1357 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1361 visit::walk_expr(self, e);
1364 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1365 match pattern.node {
1366 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1367 gate_feature_post!(&self, advanced_slice_patterns,
1369 "multiple-element slice matches anywhere \
1370 but at the end of a slice (e.g. \
1371 `[0, ..xs, 0]`) are experimental")
1373 PatKind::Slice(..) => {
1374 gate_feature_post!(&self, slice_patterns,
1376 "slice pattern syntax is experimental");
1378 PatKind::Box(..) => {
1379 gate_feature_post!(&self, box_patterns,
1381 "box pattern syntax is experimental");
1383 PatKind::Range(_, _, RangeEnd::Excluded) => {
1384 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1385 "exclusive range pattern syntax is experimental");
1389 visit::walk_pat(self, pattern)
1392 fn visit_fn(&mut self,
1393 fn_kind: FnKind<'a>,
1394 fn_decl: &'a ast::FnDecl,
1397 // check for const fn declarations
1398 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1400 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1402 // stability of const fn methods are covered in
1403 // visit_trait_item and visit_impl_item below; this is
1404 // because default methods don't pass through this
1408 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1409 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1410 self.check_abi(abi, span);
1414 visit::walk_fn(self, fn_kind, fn_decl, span);
1417 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1419 ast::TraitItemKind::Method(ref sig, ref block) => {
1420 if block.is_none() {
1421 self.check_abi(sig.abi, ti.span);
1423 if sig.constness.node == ast::Constness::Const {
1424 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1427 ast::TraitItemKind::Type(_, Some(_)) => {
1428 gate_feature_post!(&self, associated_type_defaults, ti.span,
1429 "associated type defaults are unstable");
1433 visit::walk_trait_item(self, ti);
1436 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1437 if ii.defaultness == ast::Defaultness::Default {
1438 gate_feature_post!(&self, specialization,
1440 "specialization is unstable");
1444 ast::ImplItemKind::Method(ref sig, _) => {
1445 if sig.constness.node == ast::Constness::Const {
1446 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1451 visit::walk_impl_item(self, ii);
1454 fn visit_generics(&mut self, g: &'a ast::Generics) {
1455 for t in &g.ty_params {
1456 if !t.attrs.is_empty() {
1457 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1458 "attributes on type parameter bindings are experimental");
1461 visit::walk_generics(self, g)
1464 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1465 if !lifetime_def.attrs.is_empty() {
1466 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1467 "attributes on lifetime bindings are experimental");
1469 visit::walk_lifetime_def(self, lifetime_def)
1473 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1474 let mut features = Features::new();
1476 let mut feature_checker = MutexFeatureChecker::default();
1478 for attr in krate_attrs {
1479 if !attr.check_name("feature") {
1483 match attr.meta_item_list() {
1485 span_err!(span_handler, attr.span, E0555,
1486 "malformed feature attribute, expected #![feature(...)]");
1490 let name = if let Some(word) = mi.word() {
1493 span_err!(span_handler, mi.span, E0556,
1494 "malformed feature, expected just one word");
1498 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1499 .find(|& &(n, _, _, _)| name == n) {
1500 set(&mut features, mi.span);
1501 feature_checker.collect(&features, mi.span);
1503 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1504 .find(|& &(n, _, _)| name == n)
1505 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1506 .find(|& &(n, _, _)| name == n)) {
1507 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1509 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1510 .find(|& &(n, _, _)| name == n) {
1511 features.declared_stable_lang_features.push((name, mi.span));
1513 features.declared_lib_features.push((name, mi.span));
1520 feature_checker.check(span_handler);
1525 // A collector for mutually-exclusive features and their flag spans
1527 struct MutexFeatureChecker {
1528 proc_macro: Option<Span>,
1529 custom_attribute: Option<Span>,
1532 impl MutexFeatureChecker {
1533 // If this method turns out to be a hotspot due to branching,
1534 // the branching can be eliminated by modifying `set!()` to set these spans
1535 // only for the features that need to be checked for mutual exclusion.
1536 fn collect(&mut self, features: &Features, span: Span) {
1537 if features.proc_macro {
1538 // If self.proc_macro is None, set to Some(span)
1539 self.proc_macro = self.proc_macro.or(Some(span));
1542 if features.custom_attribute {
1543 self.custom_attribute = self.custom_attribute.or(Some(span));
1547 fn check(self, handler: &Handler) {
1548 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1549 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1550 `#![feature(custom_attribute)] at the same time")
1551 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1559 pub fn check_crate(krate: &ast::Crate,
1561 features: &Features,
1562 plugin_attributes: &[(String, AttributeType)],
1563 unstable: UnstableFeatures) {
1564 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1568 plugin_attributes: plugin_attributes,
1570 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1573 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1574 pub enum UnstableFeatures {
1575 /// Hard errors for unstable features are active, as on
1576 /// beta/stable channels.
1578 /// Allow features to be activated, as on nightly.
1580 /// Errors are bypassed for bootstrapping. This is required any time
1581 /// during the build that feature-related lints are set to warn or above
1582 /// because the build turns on warnings-as-errors and uses lots of unstable
1583 /// features. As a result, this is always required for building Rust itself.
1587 impl UnstableFeatures {
1588 pub fn from_environment() -> UnstableFeatures {
1589 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1590 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1591 // Whether we should enable unstable features for bootstrapping
1592 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1593 match (disable_unstable_features, bootstrap) {
1594 (_, true) => UnstableFeatures::Cheat,
1595 (true, _) => UnstableFeatures::Disallow,
1596 (false, _) => UnstableFeatures::Allow
1600 pub fn is_nightly_build(&self) -> bool {
1602 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1608 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1609 unstable: UnstableFeatures) {
1610 let allow_features = match unstable {
1611 UnstableFeatures::Allow => true,
1612 UnstableFeatures::Disallow => false,
1613 UnstableFeatures::Cheat => true
1615 if !allow_features {
1616 for attr in &krate.attrs {
1617 if attr.check_name("feature") {
1618 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1619 span_err!(span_handler, attr.span, E0554,
1620 "#![feature] may not be used on the {} release channel",