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),
377 (active, doc_cfg, "1.21.0", Some(43781)),
381 (removed, import_shadowing, "1.0.0", None),
382 (removed, managed_boxes, "1.0.0", None),
383 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
384 (removed, negate_unsigned, "1.0.0", Some(29645)),
385 (removed, reflect, "1.0.0", Some(27749)),
386 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
387 (removed, opt_out_copy, "1.0.0", None),
388 (removed, quad_precision_float, "1.0.0", None),
389 (removed, struct_inherit, "1.0.0", None),
390 (removed, test_removed_feature, "1.0.0", None),
391 (removed, visible_private_types, "1.0.0", None),
392 (removed, unsafe_no_drop_flag, "1.0.0", None),
393 // Allows using items which are missing stability attributes
395 (removed, unmarked_api, "1.0.0", None),
396 (removed, pushpop_unsafe, "1.2.0", None),
397 (removed, allocator, "1.0.0", None),
401 (stable_removed, no_stack_check, "1.0.0", None),
405 (accepted, associated_types, "1.0.0", None),
406 // allow overloading augmented assignment operations like `a += b`
407 (accepted, augmented_assignments, "1.8.0", Some(28235)),
408 // allow empty structs and enum variants with braces
409 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
410 (accepted, default_type_params, "1.0.0", None),
411 (accepted, globs, "1.0.0", None),
412 (accepted, if_let, "1.0.0", None),
413 // A temporary feature gate used to enable parser extensions needed
414 // to bootstrap fix for #5723.
415 (accepted, issue_5723_bootstrap, "1.0.0", None),
416 (accepted, macro_rules, "1.0.0", None),
417 // Allows using #![no_std]
418 (accepted, no_std, "1.6.0", None),
419 (accepted, slicing_syntax, "1.0.0", None),
420 (accepted, struct_variant, "1.0.0", None),
421 // These are used to test this portion of the compiler, they don't actually
423 (accepted, test_accepted_feature, "1.0.0", None),
424 (accepted, tuple_indexing, "1.0.0", None),
425 // Allows macros to appear in the type position.
426 (accepted, type_macros, "1.13.0", Some(27245)),
427 (accepted, while_let, "1.0.0", None),
428 // Allows `#[deprecated]` attribute
429 (accepted, deprecated, "1.9.0", Some(29935)),
431 (accepted, question_mark, "1.13.0", Some(31436)),
432 // Allows `..` in tuple (struct) patterns
433 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
434 (accepted, item_like_imports, "1.15.0", Some(35120)),
435 // Allows using `Self` and associated types in struct expressions and patterns.
436 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
437 // elide `'static` lifetimes in `static`s and `const`s
438 (accepted, static_in_const, "1.17.0", Some(35897)),
439 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
440 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
441 // Allows the definition recursive static items.
442 (accepted, static_recursion, "1.17.0", Some(29719)),
443 // pub(restricted) visibilities (RFC 1422)
444 (accepted, pub_restricted, "1.18.0", Some(32409)),
445 // The #![windows_subsystem] attribute
446 (accepted, windows_subsystem, "1.18.0", Some(37499)),
447 // Allows `break {expr}` with a value inside `loop`s.
448 (accepted, loop_break_value, "1.19.0", Some(37339)),
449 // Permits numeric fields in struct expressions and patterns.
450 (accepted, relaxed_adts, "1.19.0", Some(35626)),
451 // Coerces non capturing closures to function pointers
452 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
453 // Allows attributes on struct literal fields.
454 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
455 // Allows the definition of associated constants in `trait` or `impl`
457 (accepted, associated_consts, "1.20.0", Some(29646)),
458 // Usage of the `compile_error!` macro
459 (accepted, compile_error, "1.20.0", Some(40872)),
462 // If you change this, please modify src/doc/unstable-book as well. You must
463 // move that documentation into the relevant place in the other docs, and
464 // remove the chapter on the flag.
466 #[derive(PartialEq, Copy, Clone, Debug)]
467 pub enum AttributeType {
468 /// Normal, builtin attribute that is consumed
469 /// by the compiler before the unused_attribute check
472 /// Builtin attribute that may not be consumed by the compiler
473 /// before the unused_attribute check. These attributes
474 /// will be ignored by the unused_attribute lint
477 /// Builtin attribute that is only allowed at the crate level
481 pub enum AttributeGate {
482 /// Is gated by a given feature gate, reason
483 /// and function to check if enabled
484 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
486 /// Ungated attribute, can be used on all release channels
491 fn is_deprecated(&self) -> bool {
493 Gated(Stability::Deprecated(_), ..) => true,
499 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
502 // Argument is tracking issue link.
503 Deprecated(&'static str),
507 impl ::std::fmt::Debug for AttributeGate {
508 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
510 Gated(ref stab, name, expl, _) =>
511 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
512 Ungated => write!(fmt, "Ungated")
517 macro_rules! cfg_fn {
518 ($field: ident) => {{
519 fn f(features: &Features) -> bool {
522 f as fn(&Features) -> bool
526 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
527 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
530 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
531 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
534 // Attributes that have a special meaning to rustc or rustdoc
535 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
538 ("warn", Normal, Ungated),
539 ("allow", Normal, Ungated),
540 ("forbid", Normal, Ungated),
541 ("deny", Normal, Ungated),
543 ("macro_reexport", Normal, Ungated),
544 ("macro_use", Normal, Ungated),
545 ("macro_export", Normal, Ungated),
546 ("plugin_registrar", Normal, Ungated),
548 ("cfg", Normal, Ungated),
549 ("cfg_attr", Normal, Ungated),
550 ("main", Normal, Ungated),
551 ("start", Normal, Ungated),
552 ("test", Normal, Ungated),
553 ("bench", Normal, Ungated),
554 ("simd", Normal, Ungated),
555 ("repr", Normal, Ungated),
556 ("path", Normal, Ungated),
557 ("abi", Normal, Ungated),
558 ("automatically_derived", Normal, Ungated),
559 ("no_mangle", Normal, Ungated),
560 ("no_link", Normal, Ungated),
561 ("derive", Normal, Ungated),
562 ("should_panic", Normal, Ungated),
563 ("ignore", Normal, Ungated),
564 ("no_implicit_prelude", Normal, Ungated),
565 ("reexport_test_harness_main", Normal, Ungated),
566 ("link_args", Normal, Gated(Stability::Unstable,
568 "the `link_args` attribute is experimental and not \
569 portable across platforms, it is recommended to \
570 use `#[link(name = \"foo\")] instead",
571 cfg_fn!(link_args))),
572 ("macro_escape", Normal, Ungated),
575 ("structural_match", Whitelisted, Gated(Stability::Unstable,
577 "the semantics of constant patterns is \
579 cfg_fn!(structural_match))),
581 ("plugin", CrateLevel, Gated(Stability::Unstable,
583 "compiler plugins are experimental \
587 ("no_std", CrateLevel, Ungated),
588 ("no_core", CrateLevel, Gated(Stability::Unstable,
590 "no_core is experimental",
592 ("lang", Normal, Gated(Stability::Unstable,
594 "language items are subject to change",
595 cfg_fn!(lang_items))),
596 ("linkage", Whitelisted, Gated(Stability::Unstable,
598 "the `linkage` attribute is experimental \
599 and not portable across platforms",
601 ("thread_local", Whitelisted, Gated(Stability::Unstable,
603 "`#[thread_local]` is an experimental feature, and does \
604 not currently handle destructors. There is no \
605 corresponding `#[task_local]` mapping to the task \
607 cfg_fn!(thread_local))),
609 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
611 "the `#[rustc_on_unimplemented]` attribute \
612 is an experimental feature",
613 cfg_fn!(on_unimplemented))),
614 ("global_allocator", Normal, Gated(Stability::Unstable,
616 "the `#[global_allocator]` attribute is \
617 an experimental feature",
618 cfg_fn!(global_allocator))),
619 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
620 "allocator_internals",
621 "the `#[default_lib_allocator]` \
622 attribute is an experimental feature",
623 cfg_fn!(allocator_internals))),
624 ("needs_allocator", Normal, Gated(Stability::Unstable,
625 "allocator_internals",
626 "the `#[needs_allocator]` \
627 attribute is an experimental \
629 cfg_fn!(allocator_internals))),
630 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
632 "the `#[panic_runtime]` attribute is \
633 an experimental feature",
634 cfg_fn!(panic_runtime))),
635 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
636 "needs_panic_runtime",
637 "the `#[needs_panic_runtime]` \
638 attribute is an experimental \
640 cfg_fn!(needs_panic_runtime))),
641 ("rustc_variance", Normal, Gated(Stability::Unstable,
643 "the `#[rustc_variance]` attribute \
644 is just used for rustc unit tests \
645 and will never be stable",
646 cfg_fn!(rustc_attrs))),
647 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
649 "the `#[rustc_error]` attribute \
650 is just used for rustc unit tests \
651 and will never be stable",
652 cfg_fn!(rustc_attrs))),
653 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
655 "the `#[rustc_if_this_changed]` attribute \
656 is just used for rustc unit tests \
657 and will never be stable",
658 cfg_fn!(rustc_attrs))),
659 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
661 "the `#[rustc_if_this_changed]` attribute \
662 is just used for rustc unit tests \
663 and will never be stable",
664 cfg_fn!(rustc_attrs))),
665 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
667 "the `#[rustc_dirty]` attribute \
668 is just used for rustc unit tests \
669 and will never be stable",
670 cfg_fn!(rustc_attrs))),
671 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
673 "the `#[rustc_clean]` attribute \
674 is just used for rustc unit tests \
675 and will never be stable",
676 cfg_fn!(rustc_attrs))),
677 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
679 "the `#[rustc_metadata_dirty]` attribute \
680 is just used for rustc unit tests \
681 and will never be stable",
682 cfg_fn!(rustc_attrs))),
683 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
685 "the `#[rustc_metadata_clean]` attribute \
686 is just used for rustc unit tests \
687 and will never be stable",
688 cfg_fn!(rustc_attrs))),
689 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
692 is just used for rustc unit tests \
693 and will never be stable",
694 cfg_fn!(rustc_attrs))),
695 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
698 is just used for rustc unit tests \
699 and will never be stable",
700 cfg_fn!(rustc_attrs))),
701 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
703 "internal rustc attributes will never be stable",
704 cfg_fn!(rustc_attrs))),
705 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
707 "internal rustc attributes will never be stable",
708 cfg_fn!(rustc_attrs))),
709 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
711 "the `#[rustc_mir]` attribute \
712 is just used for rustc unit tests \
713 and will never be stable",
714 cfg_fn!(rustc_attrs))),
715 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
717 "the `#[rustc_inherit_overflow_checks]` \
718 attribute is just used to control \
719 overflow checking behavior of several \
720 libcore functions that are inlined \
721 across crates and will never be stable",
722 cfg_fn!(rustc_attrs))),
723 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
725 "the `#[compiler_builtins]` attribute is used to \
726 identify the `compiler_builtins` crate which \
727 contains compiler-rt intrinsics and will never be \
729 cfg_fn!(compiler_builtins))),
730 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
732 "the `#[sanitizer_runtime]` attribute is used to \
733 identify crates that contain the runtime of a \
734 sanitizer and will never be stable",
735 cfg_fn!(sanitizer_runtime))),
736 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
738 "the `#[profiler_runtime]` attribute is used to \
739 identify the `profiler_builtins` crate which \
740 contains the profiler runtime and will never be \
742 cfg_fn!(profiler_runtime))),
744 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
745 "allow_internal_unstable",
746 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
747 cfg_fn!(allow_internal_unstable))),
749 ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
750 "allow_internal_unsafe",
751 EXPLAIN_ALLOW_INTERNAL_UNSAFE,
752 cfg_fn!(allow_internal_unsafe))),
754 ("fundamental", Whitelisted, Gated(Stability::Unstable,
756 "the `#[fundamental]` attribute \
757 is an experimental feature",
758 cfg_fn!(fundamental))),
760 ("proc_macro_derive", Normal, Ungated),
762 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
764 "internal implementation detail",
765 cfg_fn!(rustc_attrs))),
767 // FIXME: #14408 whitelist docs since rustdoc looks at them
768 ("doc", Whitelisted, Ungated),
770 // FIXME: #14406 these are processed in trans, which happens after the
772 ("cold", Whitelisted, Ungated),
773 ("naked", Whitelisted, Gated(Stability::Unstable,
775 "the `#[naked]` attribute \
776 is an experimental feature",
777 cfg_fn!(naked_functions))),
778 ("target_feature", Whitelisted, Gated(
779 Stability::Unstable, "target_feature",
780 "the `#[target_feature]` attribute is an experimental feature",
781 cfg_fn!(target_feature))),
782 ("export_name", Whitelisted, Ungated),
783 ("inline", Whitelisted, Ungated),
784 ("link", Whitelisted, Ungated),
785 ("link_name", Whitelisted, Ungated),
786 ("link_section", Whitelisted, Ungated),
787 ("no_builtins", Whitelisted, Ungated),
788 ("no_mangle", Whitelisted, Ungated),
789 ("no_debug", Whitelisted, Gated(
790 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
792 "the `#[no_debug]` attribute is an experimental feature",
794 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
795 "omit_gdb_pretty_printer_section",
796 "the `#[omit_gdb_pretty_printer_section]` \
797 attribute is just used for the Rust test \
799 cfg_fn!(omit_gdb_pretty_printer_section))),
800 ("unsafe_destructor_blind_to_params",
802 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
803 "dropck_parametricity",
804 "unsafe_destructor_blind_to_params has been replaced by \
805 may_dangle and will be removed in the future",
806 cfg_fn!(dropck_parametricity))),
809 Gated(Stability::Unstable,
811 "may_dangle has unstable semantics and may be removed in the future",
812 cfg_fn!(dropck_eyepatch))),
813 ("unwind", Whitelisted, Gated(Stability::Unstable,
815 "#[unwind] is experimental",
816 cfg_fn!(unwind_attributes))),
817 ("used", Whitelisted, Gated(
818 Stability::Unstable, "used",
819 "the `#[used]` attribute is an experimental feature",
823 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
825 "`#[prelude_import]` is for use by rustc only",
826 cfg_fn!(prelude_import))),
828 // FIXME: #14407 these are only looked at on-demand so we can't
829 // guarantee they'll have already been checked
830 ("rustc_deprecated", Whitelisted, Ungated),
831 ("must_use", Whitelisted, Ungated),
832 ("stable", Whitelisted, Ungated),
833 ("unstable", Whitelisted, Ungated),
834 ("deprecated", Normal, Ungated),
836 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
838 "unboxed_closures are still evolving",
839 cfg_fn!(unboxed_closures))),
841 ("windows_subsystem", Whitelisted, Ungated),
843 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
845 "attribute proc macros are currently unstable",
846 cfg_fn!(proc_macro))),
848 ("proc_macro", Normal, Gated(Stability::Unstable,
850 "function-like proc macros are currently unstable",
851 cfg_fn!(proc_macro))),
853 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
854 "rustc_derive_registrar",
855 "used internally by rustc",
856 cfg_fn!(rustc_attrs))),
858 ("allow_fail", Normal, Gated(Stability::Unstable,
860 "allow_fail attribute is currently unstable",
861 cfg_fn!(allow_fail))),
863 // Crate level attributes
864 ("crate_name", CrateLevel, Ungated),
865 ("crate_type", CrateLevel, Ungated),
866 ("crate_id", CrateLevel, Ungated),
867 ("feature", CrateLevel, Ungated),
868 ("no_start", CrateLevel, Ungated),
869 ("no_main", CrateLevel, Ungated),
870 ("no_builtins", CrateLevel, Ungated),
871 ("recursion_limit", CrateLevel, Ungated),
872 ("type_length_limit", CrateLevel, Ungated),
875 // cfg(...)'s that are feature gated
876 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
877 // (name in cfg, feature, function to check if the feature is enabled)
878 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
879 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
880 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
881 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
884 #[derive(Debug, Eq, PartialEq)]
885 pub struct GatedCfg {
891 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
892 let name = cfg.name().as_str();
894 .position(|info| info.0 == name)
903 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
904 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
905 if !has_feature(features) && !self.span.allows_unstable() {
906 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
907 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
913 features: &'a Features,
914 parse_sess: &'a ParseSess,
915 plugin_attributes: &'a [(String, AttributeType)],
918 macro_rules! gate_feature_fn {
919 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
920 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
921 let has_feature: bool = has_feature(&$cx.features);
922 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
923 if !has_feature && !span.allows_unstable() {
924 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
929 macro_rules! gate_feature {
930 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
931 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
935 impl<'a> Context<'a> {
936 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
937 debug!("check_attribute(attr = {:?})", attr);
938 let name = unwrap_or!(attr.name(), return).as_str();
939 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
941 if let Gated(_, name, desc, ref has_feature) = *gateage {
942 gate_feature_fn!(self, has_feature, attr.span, name, desc);
944 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
948 for &(ref n, ref ty) in self.plugin_attributes {
949 if attr.path == &**n {
950 // Plugins can't gate attributes, so we don't check for it
951 // unlike the code above; we only use this loop to
952 // short-circuit to avoid the checks below
953 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
957 if name.starts_with("rustc_") {
958 gate_feature!(self, rustc_attrs, attr.span,
959 "unless otherwise specified, attributes \
960 with the prefix `rustc_` \
961 are reserved for internal compiler diagnostics");
962 } else if name.starts_with("derive_") {
963 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
964 } else if !attr::is_known(attr) {
965 // Only run the custom attribute lint during regular
966 // feature gate checking. Macro gating runs
967 // before the plugin attributes are registered
968 // so we skip this then
970 gate_feature!(self, custom_attribute, attr.span,
971 &format!("The attribute `{}` is currently \
972 unknown to the compiler and \
974 added to it in the future",
981 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
982 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
983 cx.check_attribute(attr, true);
986 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
987 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
990 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
991 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
993 // FIXME (#28244): enforce that active features have issue numbers
994 // assert!(issue.is_some())
997 // search in Accepted, Removed, or Stable Removed features
998 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
999 .find(|t| t.0 == feature);
1001 Some(&(_, _, issue)) => issue,
1002 None => panic!("Feature `{}` is not declared anywhere", feature),
1007 pub enum GateIssue {
1009 Library(Option<u32>)
1012 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1014 feature_err(sess, feature, span, issue, explain).emit();
1017 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1018 explain: &str) -> DiagnosticBuilder<'a> {
1019 let diag = &sess.span_diagnostic;
1021 let issue = match issue {
1022 GateIssue::Language => find_lang_feature_issue(feature),
1023 GateIssue::Library(lib) => lib,
1026 let mut err = if let Some(n) = issue {
1027 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
1029 diag.struct_span_err(span, explain)
1032 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1033 if sess.unstable_features.is_nightly_build() {
1034 err.help(&format!("add #![feature({})] to the \
1035 crate attributes to enable",
1042 const EXPLAIN_BOX_SYNTAX: &'static str =
1043 "box expression syntax is experimental; you can call `Box::new` instead.";
1045 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1046 "attributes on non-item statements and expressions are experimental.";
1048 pub const EXPLAIN_ASM: &'static str =
1049 "inline assembly is not stable enough for use and is subject to change";
1051 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1052 "`global_asm!` is not stable enough for use and is subject to change";
1054 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1055 "`log_syntax!` is not stable enough for use and is subject to change";
1057 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1058 "`concat_idents` is not stable enough for use and is subject to change";
1060 pub const EXPLAIN_TRACE_MACROS: &'static str =
1061 "`trace_macros` is not stable enough for use and is subject to change";
1062 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1063 "allow_internal_unstable side-steps feature gating and stability checks";
1064 pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
1065 "allow_internal_unsafe side-steps the unsafe_code lint";
1067 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1068 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1070 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1071 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1072 Prefer using procedural macro custom derive.";
1074 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1075 "attributes of the form `#[derive_*]` are reserved for the compiler";
1077 pub const EXPLAIN_VIS_MATCHER: &'static str =
1078 ":vis fragment specifier is experimental and subject to change";
1080 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1081 "placement-in expression syntax is experimental and subject to change.";
1083 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1084 "Unsized tuple coercion is not stable enough for use and is subject to change";
1086 struct PostExpansionVisitor<'a> {
1087 context: &'a Context<'a>,
1090 macro_rules! gate_feature_post {
1091 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1092 let (cx, span) = ($cx, $span);
1093 if !span.allows_unstable() {
1094 gate_feature!(cx.context, $feature, span, $explain)
1099 impl<'a> PostExpansionVisitor<'a> {
1100 fn check_abi(&self, abi: Abi, span: Span) {
1102 Abi::RustIntrinsic => {
1103 gate_feature_post!(&self, intrinsics, span,
1104 "intrinsics are subject to change");
1106 Abi::PlatformIntrinsic => {
1107 gate_feature_post!(&self, platform_intrinsics, span,
1108 "platform intrinsics are experimental and possibly buggy");
1110 Abi::Vectorcall => {
1111 gate_feature_post!(&self, abi_vectorcall, span,
1112 "vectorcall is experimental and subject to change");
1115 gate_feature_post!(&self, abi_thiscall, span,
1116 "thiscall is experimental and subject to change");
1119 gate_feature_post!(&self, unboxed_closures, span,
1120 "rust-call ABI is subject to change");
1123 gate_feature_post!(&self, abi_sysv64, span,
1124 "sysv64 ABI is experimental and subject to change");
1127 gate_feature_post!(&self, abi_ptx, span,
1128 "PTX ABIs are experimental and subject to change");
1130 Abi::Unadjusted => {
1131 gate_feature_post!(&self, abi_unadjusted, span,
1132 "unadjusted ABI is an implementation detail and perma-unstable");
1134 Abi::Msp430Interrupt => {
1135 gate_feature_post!(&self, abi_msp430_interrupt, span,
1136 "msp430-interrupt ABI is experimental and subject to change");
1138 Abi::X86Interrupt => {
1139 gate_feature_post!(&self, abi_x86_interrupt, span,
1140 "x86-interrupt ABI is experimental and subject to change");
1155 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1156 use ast::MetaItemKind::*;
1157 use ast::NestedMetaItemKind::*;
1161 NameValue(ref lit) => !lit.node.is_str(),
1162 List(ref list) => list.iter().any(|li| {
1164 MetaItem(ref mi) => contains_novel_literal(mi),
1171 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1172 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1173 if !attr.span.allows_unstable() {
1174 // check for gated attributes
1175 self.context.check_attribute(attr, false);
1178 if attr.check_name("doc") {
1179 if let Some(content) = attr.meta_item_list() {
1180 if content.len() == 1 && content[0].check_name("cfg") {
1181 gate_feature_post!(&self, doc_cfg, attr.span,
1182 "#[doc(cfg(...))] is experimental"
1188 if self.context.features.proc_macro && attr::is_known(attr) {
1192 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1193 if contains_novel_literal(&meta) {
1194 gate_feature_post!(&self, attr_literals, attr.span,
1195 "non-string literals in attributes, or string \
1196 literals in top-level positions, are experimental");
1200 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1201 if !name.as_str().is_ascii() {
1202 gate_feature_post!(&self, non_ascii_idents, sp,
1203 "non-ascii idents are not fully supported.");
1207 fn visit_item(&mut self, i: &'a ast::Item) {
1209 ast::ItemKind::ExternCrate(_) => {
1210 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1211 gate_feature_post!(&self, macro_reexport, i.span,
1212 "macros reexports are experimental \
1213 and possibly buggy");
1217 ast::ItemKind::ForeignMod(ref foreign_module) => {
1218 self.check_abi(foreign_module.abi, i.span);
1221 ast::ItemKind::Fn(..) => {
1222 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1223 gate_feature_post!(&self, plugin_registrar, i.span,
1224 "compiler plugins are experimental and possibly buggy");
1226 if attr::contains_name(&i.attrs[..], "start") {
1227 gate_feature_post!(&self, start, i.span,
1228 "a #[start] function is an experimental \
1229 feature whose signature may change \
1232 if attr::contains_name(&i.attrs[..], "main") {
1233 gate_feature_post!(&self, main, i.span,
1234 "declaration of a nonstandard #[main] \
1235 function may change over time, for now \
1236 a top-level `fn main()` is required");
1240 ast::ItemKind::Struct(..) => {
1241 if attr::contains_name(&i.attrs[..], "simd") {
1242 gate_feature_post!(&self, simd, i.span,
1243 "SIMD types are experimental and possibly buggy");
1244 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1245 "the `#[simd]` attribute \
1246 is deprecated, use \
1247 `#[repr(simd)]` instead");
1249 for attr in &i.attrs {
1250 if attr.path == "repr" {
1251 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1252 if item.check_name("simd") {
1253 gate_feature_post!(&self, repr_simd, i.span,
1254 "SIMD types are experimental \
1255 and possibly buggy");
1258 if item.check_name("align") {
1259 gate_feature_post!(&self, repr_align, i.span,
1260 "the struct `#[repr(align(u16))]` attribute \
1268 ast::ItemKind::DefaultImpl(..) => {
1269 gate_feature_post!(&self, optin_builtin_traits,
1271 "default trait implementations are experimental \
1272 and possibly buggy");
1275 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1276 if polarity == ast::ImplPolarity::Negative {
1277 gate_feature_post!(&self, optin_builtin_traits,
1279 "negative trait bounds are not yet fully implemented; \
1280 use marker types for now");
1283 if let ast::Defaultness::Default = defaultness {
1284 gate_feature_post!(&self, specialization,
1286 "specialization is unstable");
1290 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1291 let msg = "`macro` is experimental";
1292 gate_feature_post!(&self, decl_macro, i.span, msg);
1298 visit::walk_item(self, i);
1301 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1302 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1303 Some(val) => val.as_str().starts_with("llvm."),
1307 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1308 "linking to LLVM intrinsics is experimental");
1311 visit::walk_foreign_item(self, i)
1314 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1316 ast::TyKind::BareFn(ref bare_fn_ty) => {
1317 self.check_abi(bare_fn_ty.abi, ty.span);
1319 ast::TyKind::ImplTrait(..) => {
1320 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1321 "`impl Trait` is experimental");
1323 ast::TyKind::Never => {
1324 gate_feature_post!(&self, never_type, ty.span,
1325 "The `!` type is experimental");
1329 visit::walk_ty(self, ty)
1332 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1333 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1334 if output_ty.node != ast::TyKind::Never {
1335 self.visit_ty(output_ty)
1340 fn visit_expr(&mut self, e: &'a ast::Expr) {
1342 ast::ExprKind::Box(_) => {
1343 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1345 ast::ExprKind::Type(..) => {
1346 gate_feature_post!(&self, type_ascription, e.span,
1347 "type ascription is experimental");
1349 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1350 gate_feature_post!(&self, inclusive_range_syntax,
1352 "inclusive range syntax is experimental");
1354 ast::ExprKind::InPlace(..) => {
1355 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1357 ast::ExprKind::Lit(ref lit) => {
1358 if let ast::LitKind::Int(_, ref ty) = lit.node {
1360 ast::LitIntType::Signed(ast::IntTy::I128) |
1361 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1362 gate_feature_post!(&self, i128_type, e.span,
1363 "128-bit integers are not stable");
1369 ast::ExprKind::Catch(_) => {
1370 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1374 visit::walk_expr(self, e);
1377 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1378 match pattern.node {
1379 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1380 gate_feature_post!(&self, advanced_slice_patterns,
1382 "multiple-element slice matches anywhere \
1383 but at the end of a slice (e.g. \
1384 `[0, ..xs, 0]`) are experimental")
1386 PatKind::Slice(..) => {
1387 gate_feature_post!(&self, slice_patterns,
1389 "slice pattern syntax is experimental");
1391 PatKind::Box(..) => {
1392 gate_feature_post!(&self, box_patterns,
1394 "box pattern syntax is experimental");
1396 PatKind::Range(_, _, RangeEnd::Excluded) => {
1397 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1398 "exclusive range pattern syntax is experimental");
1402 visit::walk_pat(self, pattern)
1405 fn visit_fn(&mut self,
1406 fn_kind: FnKind<'a>,
1407 fn_decl: &'a ast::FnDecl,
1410 // check for const fn declarations
1411 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1413 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1415 // stability of const fn methods are covered in
1416 // visit_trait_item and visit_impl_item below; this is
1417 // because default methods don't pass through this
1421 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1422 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1423 self.check_abi(abi, span);
1427 visit::walk_fn(self, fn_kind, fn_decl, span);
1430 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1432 ast::TraitItemKind::Method(ref sig, ref block) => {
1433 if block.is_none() {
1434 self.check_abi(sig.abi, ti.span);
1436 if sig.constness.node == ast::Constness::Const {
1437 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1440 ast::TraitItemKind::Type(_, Some(_)) => {
1441 gate_feature_post!(&self, associated_type_defaults, ti.span,
1442 "associated type defaults are unstable");
1446 visit::walk_trait_item(self, ti);
1449 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1450 if ii.defaultness == ast::Defaultness::Default {
1451 gate_feature_post!(&self, specialization,
1453 "specialization is unstable");
1457 ast::ImplItemKind::Method(ref sig, _) => {
1458 if sig.constness.node == ast::Constness::Const {
1459 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1464 visit::walk_impl_item(self, ii);
1467 fn visit_generics(&mut self, g: &'a ast::Generics) {
1468 for t in &g.ty_params {
1469 if !t.attrs.is_empty() {
1470 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1471 "attributes on type parameter bindings are experimental");
1474 visit::walk_generics(self, g)
1477 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1478 if !lifetime_def.attrs.is_empty() {
1479 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1480 "attributes on lifetime bindings are experimental");
1482 visit::walk_lifetime_def(self, lifetime_def)
1486 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1487 let mut features = Features::new();
1489 let mut feature_checker = MutexFeatureChecker::default();
1491 for attr in krate_attrs {
1492 if !attr.check_name("feature") {
1496 match attr.meta_item_list() {
1498 span_err!(span_handler, attr.span, E0555,
1499 "malformed feature attribute, expected #![feature(...)]");
1503 let name = if let Some(word) = mi.word() {
1506 span_err!(span_handler, mi.span, E0556,
1507 "malformed feature, expected just one word");
1511 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1512 .find(|& &(n, _, _, _)| name == n) {
1513 set(&mut features, mi.span);
1514 feature_checker.collect(&features, mi.span);
1516 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1517 .find(|& &(n, _, _)| name == n)
1518 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1519 .find(|& &(n, _, _)| name == n)) {
1520 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1522 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1523 .find(|& &(n, _, _)| name == n) {
1524 features.declared_stable_lang_features.push((name, mi.span));
1526 features.declared_lib_features.push((name, mi.span));
1533 feature_checker.check(span_handler);
1538 // A collector for mutually-exclusive features and their flag spans
1540 struct MutexFeatureChecker {
1541 proc_macro: Option<Span>,
1542 custom_attribute: Option<Span>,
1545 impl MutexFeatureChecker {
1546 // If this method turns out to be a hotspot due to branching,
1547 // the branching can be eliminated by modifying `set!()` to set these spans
1548 // only for the features that need to be checked for mutual exclusion.
1549 fn collect(&mut self, features: &Features, span: Span) {
1550 if features.proc_macro {
1551 // If self.proc_macro is None, set to Some(span)
1552 self.proc_macro = self.proc_macro.or(Some(span));
1555 if features.custom_attribute {
1556 self.custom_attribute = self.custom_attribute.or(Some(span));
1560 fn check(self, handler: &Handler) {
1561 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1562 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1563 `#![feature(custom_attribute)] at the same time")
1564 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1572 pub fn check_crate(krate: &ast::Crate,
1574 features: &Features,
1575 plugin_attributes: &[(String, AttributeType)],
1576 unstable: UnstableFeatures) {
1577 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1581 plugin_attributes: plugin_attributes,
1583 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1586 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1587 pub enum UnstableFeatures {
1588 /// Hard errors for unstable features are active, as on
1589 /// beta/stable channels.
1591 /// Allow features to be activated, as on nightly.
1593 /// Errors are bypassed for bootstrapping. This is required any time
1594 /// during the build that feature-related lints are set to warn or above
1595 /// because the build turns on warnings-as-errors and uses lots of unstable
1596 /// features. As a result, this is always required for building Rust itself.
1600 impl UnstableFeatures {
1601 pub fn from_environment() -> UnstableFeatures {
1602 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1603 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1604 // Whether we should enable unstable features for bootstrapping
1605 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1606 match (disable_unstable_features, bootstrap) {
1607 (_, true) => UnstableFeatures::Cheat,
1608 (true, _) => UnstableFeatures::Disallow,
1609 (false, _) => UnstableFeatures::Allow
1613 pub fn is_nightly_build(&self) -> bool {
1615 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1621 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1622 unstable: UnstableFeatures) {
1623 let allow_features = match unstable {
1624 UnstableFeatures::Allow => true,
1625 UnstableFeatures::Disallow => false,
1626 UnstableFeatures::Cheat => true
1628 if !allow_features {
1629 for attr in &krate.attrs {
1630 if attr.check_name("feature") {
1631 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1632 span_err!(span_handler, attr.span, E0554,
1633 "#![feature] may not be used on the {} release channel",