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 // Used to preserve symbols (see llvm.used)
349 (active, used, "1.18.0", Some(40289)),
351 // Allows module-level inline assembly by way of global_asm!()
352 (active, global_asm, "1.18.0", Some(35119)),
354 // Allows overlapping impls of marker traits
355 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
357 // Allows use of the :vis macro fragment specifier
358 (active, macro_vis_matcher, "1.18.0", Some(41022)),
361 (active, abi_thiscall, "1.19.0", None),
363 // Allows a test to fail without failing the whole suite
364 (active, allow_fail, "1.19.0", Some(42219)),
366 // Allows unsized tuple coercion.
367 (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
369 // global allocators and their internals
370 (active, global_allocator, "1.20.0", None),
371 (active, allocator_internals, "1.20.0", None),
374 (active, doc_cfg, "1.21.0", Some(43781)),
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)),
457 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
458 (accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
461 // If you change this, please modify src/doc/unstable-book as well. You must
462 // move that documentation into the relevant place in the other docs, and
463 // remove the chapter on the flag.
465 #[derive(PartialEq, Copy, Clone, Debug)]
466 pub enum AttributeType {
467 /// Normal, builtin attribute that is consumed
468 /// by the compiler before the unused_attribute check
471 /// Builtin attribute that may not be consumed by the compiler
472 /// before the unused_attribute check. These attributes
473 /// will be ignored by the unused_attribute lint
476 /// Builtin attribute that is only allowed at the crate level
480 pub enum AttributeGate {
481 /// Is gated by a given feature gate, reason
482 /// and function to check if enabled
483 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
485 /// Ungated attribute, can be used on all release channels
490 fn is_deprecated(&self) -> bool {
492 Gated(Stability::Deprecated(_), ..) => true,
498 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
501 // Argument is tracking issue link.
502 Deprecated(&'static str),
506 impl ::std::fmt::Debug for AttributeGate {
507 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
509 Gated(ref stab, name, expl, _) =>
510 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
511 Ungated => write!(fmt, "Ungated")
516 macro_rules! cfg_fn {
517 ($field: ident) => {{
518 fn f(features: &Features) -> bool {
521 f as fn(&Features) -> bool
525 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
526 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
529 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
530 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
533 // Attributes that have a special meaning to rustc or rustdoc
534 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
537 ("warn", Normal, Ungated),
538 ("allow", Normal, Ungated),
539 ("forbid", Normal, Ungated),
540 ("deny", Normal, Ungated),
542 ("macro_reexport", Normal, Ungated),
543 ("macro_use", Normal, Ungated),
544 ("macro_export", Normal, Ungated),
545 ("plugin_registrar", Normal, Ungated),
547 ("cfg", Normal, Ungated),
548 ("cfg_attr", Normal, Ungated),
549 ("main", Normal, Ungated),
550 ("start", Normal, Ungated),
551 ("test", Normal, Ungated),
552 ("bench", Normal, Ungated),
553 ("simd", Normal, Ungated),
554 ("repr", Normal, Ungated),
555 ("path", Normal, Ungated),
556 ("abi", Normal, Ungated),
557 ("automatically_derived", Normal, Ungated),
558 ("no_mangle", Normal, Ungated),
559 ("no_link", Normal, Ungated),
560 ("derive", Normal, Ungated),
561 ("should_panic", Normal, Ungated),
562 ("ignore", Normal, Ungated),
563 ("no_implicit_prelude", Normal, Ungated),
564 ("reexport_test_harness_main", Normal, Ungated),
565 ("link_args", Normal, Gated(Stability::Unstable,
567 "the `link_args` attribute is experimental and not \
568 portable across platforms, it is recommended to \
569 use `#[link(name = \"foo\")] instead",
570 cfg_fn!(link_args))),
571 ("macro_escape", Normal, Ungated),
574 ("structural_match", Whitelisted, Gated(Stability::Unstable,
576 "the semantics of constant patterns is \
578 cfg_fn!(structural_match))),
580 ("plugin", CrateLevel, Gated(Stability::Unstable,
582 "compiler plugins are experimental \
586 ("no_std", CrateLevel, Ungated),
587 ("no_core", CrateLevel, Gated(Stability::Unstable,
589 "no_core is experimental",
591 ("lang", Normal, Gated(Stability::Unstable,
593 "language items are subject to change",
594 cfg_fn!(lang_items))),
595 ("linkage", Whitelisted, Gated(Stability::Unstable,
597 "the `linkage` attribute is experimental \
598 and not portable across platforms",
600 ("thread_local", Whitelisted, Gated(Stability::Unstable,
602 "`#[thread_local]` is an experimental feature, and does \
603 not currently handle destructors. There is no \
604 corresponding `#[task_local]` mapping to the task \
606 cfg_fn!(thread_local))),
608 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
610 "the `#[rustc_on_unimplemented]` attribute \
611 is an experimental feature",
612 cfg_fn!(on_unimplemented))),
613 ("global_allocator", Normal, Gated(Stability::Unstable,
615 "the `#[global_allocator]` attribute is \
616 an experimental feature",
617 cfg_fn!(global_allocator))),
618 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
619 "allocator_internals",
620 "the `#[default_lib_allocator]` \
621 attribute is an experimental feature",
622 cfg_fn!(allocator_internals))),
623 ("needs_allocator", Normal, Gated(Stability::Unstable,
624 "allocator_internals",
625 "the `#[needs_allocator]` \
626 attribute is an experimental \
628 cfg_fn!(allocator_internals))),
629 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
631 "the `#[panic_runtime]` attribute is \
632 an experimental feature",
633 cfg_fn!(panic_runtime))),
634 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
635 "needs_panic_runtime",
636 "the `#[needs_panic_runtime]` \
637 attribute is an experimental \
639 cfg_fn!(needs_panic_runtime))),
640 ("rustc_variance", Normal, Gated(Stability::Unstable,
642 "the `#[rustc_variance]` attribute \
643 is just used for rustc unit tests \
644 and will never be stable",
645 cfg_fn!(rustc_attrs))),
646 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
648 "the `#[rustc_error]` attribute \
649 is just used for rustc unit tests \
650 and will never be stable",
651 cfg_fn!(rustc_attrs))),
652 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
654 "the `#[rustc_if_this_changed]` attribute \
655 is just used for rustc unit tests \
656 and will never be stable",
657 cfg_fn!(rustc_attrs))),
658 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
660 "the `#[rustc_if_this_changed]` attribute \
661 is just used for rustc unit tests \
662 and will never be stable",
663 cfg_fn!(rustc_attrs))),
664 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
666 "the `#[rustc_dirty]` attribute \
667 is just used for rustc unit tests \
668 and will never be stable",
669 cfg_fn!(rustc_attrs))),
670 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
672 "the `#[rustc_clean]` attribute \
673 is just used for rustc unit tests \
674 and will never be stable",
675 cfg_fn!(rustc_attrs))),
676 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
678 "the `#[rustc_metadata_dirty]` attribute \
679 is just used for rustc unit tests \
680 and will never be stable",
681 cfg_fn!(rustc_attrs))),
682 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
684 "the `#[rustc_metadata_clean]` attribute \
685 is just used for rustc unit tests \
686 and will never be stable",
687 cfg_fn!(rustc_attrs))),
688 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
691 is just used for rustc unit tests \
692 and will never be stable",
693 cfg_fn!(rustc_attrs))),
694 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
697 is just used for rustc unit tests \
698 and will never be stable",
699 cfg_fn!(rustc_attrs))),
700 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
702 "internal rustc attributes will never be stable",
703 cfg_fn!(rustc_attrs))),
704 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
706 "internal rustc attributes will never be stable",
707 cfg_fn!(rustc_attrs))),
708 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
710 "the `#[rustc_mir]` attribute \
711 is just used for rustc unit tests \
712 and will never be stable",
713 cfg_fn!(rustc_attrs))),
714 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
716 "the `#[rustc_inherit_overflow_checks]` \
717 attribute is just used to control \
718 overflow checking behavior of several \
719 libcore functions that are inlined \
720 across crates and will never be stable",
721 cfg_fn!(rustc_attrs))),
722 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
724 "the `#[compiler_builtins]` attribute is used to \
725 identify the `compiler_builtins` crate which \
726 contains compiler-rt intrinsics and will never be \
728 cfg_fn!(compiler_builtins))),
729 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
731 "the `#[sanitizer_runtime]` attribute is used to \
732 identify crates that contain the runtime of a \
733 sanitizer and will never be stable",
734 cfg_fn!(sanitizer_runtime))),
735 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
737 "the `#[profiler_runtime]` attribute is used to \
738 identify the `profiler_builtins` crate which \
739 contains the profiler runtime and will never be \
741 cfg_fn!(profiler_runtime))),
743 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
744 "allow_internal_unstable",
745 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
746 cfg_fn!(allow_internal_unstable))),
748 ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
749 "allow_internal_unsafe",
750 EXPLAIN_ALLOW_INTERNAL_UNSAFE,
751 cfg_fn!(allow_internal_unsafe))),
753 ("fundamental", Whitelisted, Gated(Stability::Unstable,
755 "the `#[fundamental]` attribute \
756 is an experimental feature",
757 cfg_fn!(fundamental))),
759 ("proc_macro_derive", Normal, Ungated),
761 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
763 "internal implementation detail",
764 cfg_fn!(rustc_attrs))),
766 // FIXME: #14408 whitelist docs since rustdoc looks at them
767 ("doc", Whitelisted, Ungated),
769 // FIXME: #14406 these are processed in trans, which happens after the
771 ("cold", Whitelisted, Ungated),
772 ("naked", Whitelisted, Gated(Stability::Unstable,
774 "the `#[naked]` attribute \
775 is an experimental feature",
776 cfg_fn!(naked_functions))),
777 ("target_feature", Whitelisted, Gated(
778 Stability::Unstable, "target_feature",
779 "the `#[target_feature]` attribute is an experimental feature",
780 cfg_fn!(target_feature))),
781 ("export_name", Whitelisted, Ungated),
782 ("inline", Whitelisted, Ungated),
783 ("link", Whitelisted, Ungated),
784 ("link_name", Whitelisted, Ungated),
785 ("link_section", Whitelisted, Ungated),
786 ("no_builtins", Whitelisted, Ungated),
787 ("no_mangle", Whitelisted, Ungated),
788 ("no_debug", Whitelisted, Gated(
789 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
791 "the `#[no_debug]` attribute is an experimental feature",
793 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
794 "omit_gdb_pretty_printer_section",
795 "the `#[omit_gdb_pretty_printer_section]` \
796 attribute is just used for the Rust test \
798 cfg_fn!(omit_gdb_pretty_printer_section))),
799 ("unsafe_destructor_blind_to_params",
801 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
802 "dropck_parametricity",
803 "unsafe_destructor_blind_to_params has been replaced by \
804 may_dangle and will be removed in the future",
805 cfg_fn!(dropck_parametricity))),
808 Gated(Stability::Unstable,
810 "may_dangle has unstable semantics and may be removed in the future",
811 cfg_fn!(dropck_eyepatch))),
812 ("unwind", Whitelisted, Gated(Stability::Unstable,
814 "#[unwind] is experimental",
815 cfg_fn!(unwind_attributes))),
816 ("used", Whitelisted, Gated(
817 Stability::Unstable, "used",
818 "the `#[used]` attribute is an experimental feature",
822 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
824 "`#[prelude_import]` is for use by rustc only",
825 cfg_fn!(prelude_import))),
827 // FIXME: #14407 these are only looked at on-demand so we can't
828 // guarantee they'll have already been checked
829 ("rustc_deprecated", Whitelisted, Ungated),
830 ("must_use", Whitelisted, Ungated),
831 ("stable", Whitelisted, Ungated),
832 ("unstable", Whitelisted, Ungated),
833 ("deprecated", Normal, Ungated),
835 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
837 "unboxed_closures are still evolving",
838 cfg_fn!(unboxed_closures))),
840 ("windows_subsystem", Whitelisted, Ungated),
842 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
844 "attribute proc macros are currently unstable",
845 cfg_fn!(proc_macro))),
847 ("proc_macro", Normal, Gated(Stability::Unstable,
849 "function-like proc macros are currently unstable",
850 cfg_fn!(proc_macro))),
852 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
853 "rustc_derive_registrar",
854 "used internally by rustc",
855 cfg_fn!(rustc_attrs))),
857 ("allow_fail", Normal, Gated(Stability::Unstable,
859 "allow_fail attribute is currently unstable",
860 cfg_fn!(allow_fail))),
862 // Crate level attributes
863 ("crate_name", CrateLevel, Ungated),
864 ("crate_type", CrateLevel, Ungated),
865 ("crate_id", CrateLevel, Ungated),
866 ("feature", CrateLevel, Ungated),
867 ("no_start", CrateLevel, Ungated),
868 ("no_main", CrateLevel, Ungated),
869 ("no_builtins", CrateLevel, Ungated),
870 ("recursion_limit", CrateLevel, Ungated),
871 ("type_length_limit", CrateLevel, Ungated),
874 // cfg(...)'s that are feature gated
875 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
876 // (name in cfg, feature, function to check if the feature is enabled)
877 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
878 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
879 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
880 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
883 #[derive(Debug, Eq, PartialEq)]
884 pub struct GatedCfg {
890 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
891 let name = cfg.name().as_str();
893 .position(|info| info.0 == name)
902 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
903 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
904 if !has_feature(features) && !self.span.allows_unstable() {
905 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
906 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
912 features: &'a Features,
913 parse_sess: &'a ParseSess,
914 plugin_attributes: &'a [(String, AttributeType)],
917 macro_rules! gate_feature_fn {
918 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
919 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
920 let has_feature: bool = has_feature(&$cx.features);
921 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
922 if !has_feature && !span.allows_unstable() {
923 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
928 macro_rules! gate_feature {
929 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
930 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
934 impl<'a> Context<'a> {
935 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
936 debug!("check_attribute(attr = {:?})", attr);
937 let name = unwrap_or!(attr.name(), return).as_str();
938 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
940 if let Gated(_, name, desc, ref has_feature) = *gateage {
941 gate_feature_fn!(self, has_feature, attr.span, name, desc);
943 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
947 for &(ref n, ref ty) in self.plugin_attributes {
948 if attr.path == &**n {
949 // Plugins can't gate attributes, so we don't check for it
950 // unlike the code above; we only use this loop to
951 // short-circuit to avoid the checks below
952 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
956 if name.starts_with("rustc_") {
957 gate_feature!(self, rustc_attrs, attr.span,
958 "unless otherwise specified, attributes \
959 with the prefix `rustc_` \
960 are reserved for internal compiler diagnostics");
961 } else if name.starts_with("derive_") {
962 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
963 } else if !attr::is_known(attr) {
964 // Only run the custom attribute lint during regular
965 // feature gate checking. Macro gating runs
966 // before the plugin attributes are registered
967 // so we skip this then
969 gate_feature!(self, custom_attribute, attr.span,
970 &format!("The attribute `{}` is currently \
971 unknown to the compiler and \
973 added to it in the future",
980 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
981 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
982 cx.check_attribute(attr, true);
985 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
986 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
989 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
990 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
992 // FIXME (#28244): enforce that active features have issue numbers
993 // assert!(issue.is_some())
996 // search in Accepted, Removed, or Stable Removed features
997 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
998 .find(|t| t.0 == feature);
1000 Some(&(_, _, issue)) => issue,
1001 None => panic!("Feature `{}` is not declared anywhere", feature),
1006 pub enum GateIssue {
1008 Library(Option<u32>)
1011 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1013 feature_err(sess, feature, span, issue, explain).emit();
1016 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1017 explain: &str) -> DiagnosticBuilder<'a> {
1018 let diag = &sess.span_diagnostic;
1020 let issue = match issue {
1021 GateIssue::Language => find_lang_feature_issue(feature),
1022 GateIssue::Library(lib) => lib,
1025 let mut err = if let Some(n) = issue {
1026 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
1028 diag.struct_span_err(span, explain)
1031 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1032 if sess.unstable_features.is_nightly_build() {
1033 err.help(&format!("add #![feature({})] to the \
1034 crate attributes to enable",
1041 const EXPLAIN_BOX_SYNTAX: &'static str =
1042 "box expression syntax is experimental; you can call `Box::new` instead.";
1044 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1045 "attributes on non-item statements and expressions are experimental.";
1047 pub const EXPLAIN_ASM: &'static str =
1048 "inline assembly is not stable enough for use and is subject to change";
1050 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1051 "`global_asm!` is not stable enough for use and is subject to change";
1053 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1054 "`log_syntax!` is not stable enough for use and is subject to change";
1056 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1057 "`concat_idents` is not stable enough for use and is subject to change";
1059 pub const EXPLAIN_TRACE_MACROS: &'static str =
1060 "`trace_macros` is not stable enough for use and is subject to change";
1061 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1062 "allow_internal_unstable side-steps feature gating and stability checks";
1063 pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
1064 "allow_internal_unsafe side-steps the unsafe_code lint";
1066 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1067 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1069 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1070 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1071 Prefer using procedural macro custom derive.";
1073 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1074 "attributes of the form `#[derive_*]` are reserved for the compiler";
1076 pub const EXPLAIN_VIS_MATCHER: &'static str =
1077 ":vis fragment specifier is experimental and subject to change";
1079 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1080 "placement-in expression syntax is experimental and subject to change.";
1082 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1083 "Unsized tuple coercion is not stable enough for use and is subject to change";
1085 struct PostExpansionVisitor<'a> {
1086 context: &'a Context<'a>,
1089 macro_rules! gate_feature_post {
1090 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1091 let (cx, span) = ($cx, $span);
1092 if !span.allows_unstable() {
1093 gate_feature!(cx.context, $feature, span, $explain)
1098 impl<'a> PostExpansionVisitor<'a> {
1099 fn check_abi(&self, abi: Abi, span: Span) {
1101 Abi::RustIntrinsic => {
1102 gate_feature_post!(&self, intrinsics, span,
1103 "intrinsics are subject to change");
1105 Abi::PlatformIntrinsic => {
1106 gate_feature_post!(&self, platform_intrinsics, span,
1107 "platform intrinsics are experimental and possibly buggy");
1109 Abi::Vectorcall => {
1110 gate_feature_post!(&self, abi_vectorcall, span,
1111 "vectorcall is experimental and subject to change");
1114 gate_feature_post!(&self, abi_thiscall, span,
1115 "thiscall is experimental and subject to change");
1118 gate_feature_post!(&self, unboxed_closures, span,
1119 "rust-call ABI is subject to change");
1122 gate_feature_post!(&self, abi_sysv64, span,
1123 "sysv64 ABI is experimental and subject to change");
1126 gate_feature_post!(&self, abi_ptx, span,
1127 "PTX ABIs are experimental and subject to change");
1129 Abi::Unadjusted => {
1130 gate_feature_post!(&self, abi_unadjusted, span,
1131 "unadjusted ABI is an implementation detail and perma-unstable");
1133 Abi::Msp430Interrupt => {
1134 gate_feature_post!(&self, abi_msp430_interrupt, span,
1135 "msp430-interrupt ABI is experimental and subject to change");
1137 Abi::X86Interrupt => {
1138 gate_feature_post!(&self, abi_x86_interrupt, span,
1139 "x86-interrupt ABI is experimental and subject to change");
1154 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1155 use ast::MetaItemKind::*;
1156 use ast::NestedMetaItemKind::*;
1160 NameValue(ref lit) => !lit.node.is_str(),
1161 List(ref list) => list.iter().any(|li| {
1163 MetaItem(ref mi) => contains_novel_literal(mi),
1170 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1171 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1172 if !attr.span.allows_unstable() {
1173 // check for gated attributes
1174 self.context.check_attribute(attr, false);
1177 if attr.check_name("doc") {
1178 if let Some(content) = attr.meta_item_list() {
1179 if content.len() == 1 && content[0].check_name("cfg") {
1180 gate_feature_post!(&self, doc_cfg, attr.span,
1181 "#[doc(cfg(...))] is experimental"
1187 if self.context.features.proc_macro && attr::is_known(attr) {
1191 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1192 if contains_novel_literal(&meta) {
1193 gate_feature_post!(&self, attr_literals, attr.span,
1194 "non-string literals in attributes, or string \
1195 literals in top-level positions, are experimental");
1199 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1200 if !name.as_str().is_ascii() {
1201 gate_feature_post!(&self, non_ascii_idents, sp,
1202 "non-ascii idents are not fully supported.");
1206 fn visit_item(&mut self, i: &'a ast::Item) {
1208 ast::ItemKind::ExternCrate(_) => {
1209 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1210 gate_feature_post!(&self, macro_reexport, i.span,
1211 "macros reexports are experimental \
1212 and possibly buggy");
1216 ast::ItemKind::ForeignMod(ref foreign_module) => {
1217 self.check_abi(foreign_module.abi, i.span);
1220 ast::ItemKind::Fn(..) => {
1221 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1222 gate_feature_post!(&self, plugin_registrar, i.span,
1223 "compiler plugins are experimental and possibly buggy");
1225 if attr::contains_name(&i.attrs[..], "start") {
1226 gate_feature_post!(&self, start, i.span,
1227 "a #[start] function is an experimental \
1228 feature whose signature may change \
1231 if attr::contains_name(&i.attrs[..], "main") {
1232 gate_feature_post!(&self, main, i.span,
1233 "declaration of a nonstandard #[main] \
1234 function may change over time, for now \
1235 a top-level `fn main()` is required");
1239 ast::ItemKind::Struct(..) => {
1240 if attr::contains_name(&i.attrs[..], "simd") {
1241 gate_feature_post!(&self, simd, i.span,
1242 "SIMD types are experimental and possibly buggy");
1243 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1244 "the `#[simd]` attribute \
1245 is deprecated, use \
1246 `#[repr(simd)]` instead");
1248 for attr in &i.attrs {
1249 if attr.path == "repr" {
1250 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1251 if item.check_name("simd") {
1252 gate_feature_post!(&self, repr_simd, i.span,
1253 "SIMD types are experimental \
1254 and possibly buggy");
1257 if item.check_name("align") {
1258 gate_feature_post!(&self, repr_align, i.span,
1259 "the struct `#[repr(align(u16))]` attribute \
1267 ast::ItemKind::DefaultImpl(..) => {
1268 gate_feature_post!(&self, optin_builtin_traits,
1270 "default trait implementations are experimental \
1271 and possibly buggy");
1274 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1275 if polarity == ast::ImplPolarity::Negative {
1276 gate_feature_post!(&self, optin_builtin_traits,
1278 "negative trait bounds are not yet fully implemented; \
1279 use marker types for now");
1282 if let ast::Defaultness::Default = defaultness {
1283 gate_feature_post!(&self, specialization,
1285 "specialization is unstable");
1289 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1290 let msg = "`macro` is experimental";
1291 gate_feature_post!(&self, decl_macro, i.span, msg);
1297 visit::walk_item(self, i);
1300 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1301 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1302 Some(val) => val.as_str().starts_with("llvm."),
1306 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1307 "linking to LLVM intrinsics is experimental");
1310 visit::walk_foreign_item(self, i)
1313 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1315 ast::TyKind::BareFn(ref bare_fn_ty) => {
1316 self.check_abi(bare_fn_ty.abi, ty.span);
1318 ast::TyKind::ImplTrait(..) => {
1319 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1320 "`impl Trait` is experimental");
1322 ast::TyKind::Never => {
1323 gate_feature_post!(&self, never_type, ty.span,
1324 "The `!` type is experimental");
1328 visit::walk_ty(self, ty)
1331 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1332 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1333 if output_ty.node != ast::TyKind::Never {
1334 self.visit_ty(output_ty)
1339 fn visit_expr(&mut self, e: &'a ast::Expr) {
1341 ast::ExprKind::Box(_) => {
1342 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1344 ast::ExprKind::Type(..) => {
1345 gate_feature_post!(&self, type_ascription, e.span,
1346 "type ascription is experimental");
1348 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1349 gate_feature_post!(&self, inclusive_range_syntax,
1351 "inclusive range syntax is experimental");
1353 ast::ExprKind::InPlace(..) => {
1354 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1356 ast::ExprKind::Lit(ref lit) => {
1357 if let ast::LitKind::Int(_, ref ty) = lit.node {
1359 ast::LitIntType::Signed(ast::IntTy::I128) |
1360 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1361 gate_feature_post!(&self, i128_type, e.span,
1362 "128-bit integers are not stable");
1368 ast::ExprKind::Catch(_) => {
1369 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1373 visit::walk_expr(self, e);
1376 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1377 match pattern.node {
1378 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1379 gate_feature_post!(&self, advanced_slice_patterns,
1381 "multiple-element slice matches anywhere \
1382 but at the end of a slice (e.g. \
1383 `[0, ..xs, 0]`) are experimental")
1385 PatKind::Slice(..) => {
1386 gate_feature_post!(&self, slice_patterns,
1388 "slice pattern syntax is experimental");
1390 PatKind::Box(..) => {
1391 gate_feature_post!(&self, box_patterns,
1393 "box pattern syntax is experimental");
1395 PatKind::Range(_, _, RangeEnd::Excluded) => {
1396 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1397 "exclusive range pattern syntax is experimental");
1401 visit::walk_pat(self, pattern)
1404 fn visit_fn(&mut self,
1405 fn_kind: FnKind<'a>,
1406 fn_decl: &'a ast::FnDecl,
1409 // check for const fn declarations
1410 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1412 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1414 // stability of const fn methods are covered in
1415 // visit_trait_item and visit_impl_item below; this is
1416 // because default methods don't pass through this
1420 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1421 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1422 self.check_abi(abi, span);
1426 visit::walk_fn(self, fn_kind, fn_decl, span);
1429 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1431 ast::TraitItemKind::Method(ref sig, ref block) => {
1432 if block.is_none() {
1433 self.check_abi(sig.abi, ti.span);
1435 if sig.constness.node == ast::Constness::Const {
1436 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1439 ast::TraitItemKind::Type(_, Some(_)) => {
1440 gate_feature_post!(&self, associated_type_defaults, ti.span,
1441 "associated type defaults are unstable");
1445 visit::walk_trait_item(self, ti);
1448 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1449 if ii.defaultness == ast::Defaultness::Default {
1450 gate_feature_post!(&self, specialization,
1452 "specialization is unstable");
1456 ast::ImplItemKind::Method(ref sig, _) => {
1457 if sig.constness.node == ast::Constness::Const {
1458 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1463 visit::walk_impl_item(self, ii);
1466 fn visit_generics(&mut self, g: &'a ast::Generics) {
1467 for t in &g.ty_params {
1468 if !t.attrs.is_empty() {
1469 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1470 "attributes on type parameter bindings are experimental");
1473 visit::walk_generics(self, g)
1476 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1477 if !lifetime_def.attrs.is_empty() {
1478 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1479 "attributes on lifetime bindings are experimental");
1481 visit::walk_lifetime_def(self, lifetime_def)
1485 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1486 let mut features = Features::new();
1488 let mut feature_checker = MutexFeatureChecker::default();
1490 for attr in krate_attrs {
1491 if !attr.check_name("feature") {
1495 match attr.meta_item_list() {
1497 span_err!(span_handler, attr.span, E0555,
1498 "malformed feature attribute, expected #![feature(...)]");
1502 let name = if let Some(word) = mi.word() {
1505 span_err!(span_handler, mi.span, E0556,
1506 "malformed feature, expected just one word");
1510 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1511 .find(|& &(n, _, _, _)| name == n) {
1512 set(&mut features, mi.span);
1513 feature_checker.collect(&features, mi.span);
1515 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1516 .find(|& &(n, _, _)| name == n)
1517 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1518 .find(|& &(n, _, _)| name == n)) {
1519 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1521 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1522 .find(|& &(n, _, _)| name == n) {
1523 features.declared_stable_lang_features.push((name, mi.span));
1525 features.declared_lib_features.push((name, mi.span));
1532 feature_checker.check(span_handler);
1537 // A collector for mutually-exclusive features and their flag spans
1539 struct MutexFeatureChecker {
1540 proc_macro: Option<Span>,
1541 custom_attribute: Option<Span>,
1544 impl MutexFeatureChecker {
1545 // If this method turns out to be a hotspot due to branching,
1546 // the branching can be eliminated by modifying `set!()` to set these spans
1547 // only for the features that need to be checked for mutual exclusion.
1548 fn collect(&mut self, features: &Features, span: Span) {
1549 if features.proc_macro {
1550 // If self.proc_macro is None, set to Some(span)
1551 self.proc_macro = self.proc_macro.or(Some(span));
1554 if features.custom_attribute {
1555 self.custom_attribute = self.custom_attribute.or(Some(span));
1559 fn check(self, handler: &Handler) {
1560 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1561 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1562 `#![feature(custom_attribute)] at the same time")
1563 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1571 pub fn check_crate(krate: &ast::Crate,
1573 features: &Features,
1574 plugin_attributes: &[(String, AttributeType)],
1575 unstable: UnstableFeatures) {
1576 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1582 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1585 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1586 pub enum UnstableFeatures {
1587 /// Hard errors for unstable features are active, as on
1588 /// beta/stable channels.
1590 /// Allow features to be activated, as on nightly.
1592 /// Errors are bypassed for bootstrapping. This is required any time
1593 /// during the build that feature-related lints are set to warn or above
1594 /// because the build turns on warnings-as-errors and uses lots of unstable
1595 /// features. As a result, this is always required for building Rust itself.
1599 impl UnstableFeatures {
1600 pub fn from_environment() -> UnstableFeatures {
1601 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1602 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1603 // Whether we should enable unstable features for bootstrapping
1604 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1605 match (disable_unstable_features, bootstrap) {
1606 (_, true) => UnstableFeatures::Cheat,
1607 (true, _) => UnstableFeatures::Disallow,
1608 (false, _) => UnstableFeatures::Allow
1612 pub fn is_nightly_build(&self) -> bool {
1614 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1620 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1621 unstable: UnstableFeatures) {
1622 let allow_features = match unstable {
1623 UnstableFeatures::Allow => true,
1624 UnstableFeatures::Disallow => false,
1625 UnstableFeatures::Cheat => true
1627 if !allow_features {
1628 for attr in &krate.attrs {
1629 if attr.check_name("feature") {
1630 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1631 span_err!(span_handler, attr.span, E0554,
1632 "#![feature] may not be used on the {} release channel",