1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 //! This module implements the gating necessary for preventing certain compiler
14 //! features from being used by default. This module will crawl a pre-expanded
15 //! AST to ensure that there are no features which are used that are not
18 //! Features are enabled in programs via the crate-level attributes of
19 //! `#![feature(...)]` with a comma-separated list of features.
21 //! For the purpose of future feature-tracking, once code for detection of feature
22 //! gate usage is added, *do not remove it again* even once the feature
25 use self::AttributeType::*;
26 use self::AttributeGate::*;
29 use ast::{self, NodeId, PatKind, RangeEnd};
33 use errors::{DiagnosticBuilder, Handler, FatalError};
34 use visit::{self, FnKind, Visitor};
38 use std::ascii::AsciiExt;
43 fn f(features: &mut Features, span: Span) {
44 features.declared_lib_features.push((Symbol::intern("proc_macro"), span));
45 features.proc_macro = true;
47 f as fn(&mut Features, Span)
50 fn f(features: &mut Features, _: Span) {
51 features.$field = true;
53 f as fn(&mut Features, Span)
57 macro_rules! declare_features {
58 ($((active, $feature: ident, $ver: expr, $issue: expr),)+) => {
59 /// Represents active features that are currently being implemented or
60 /// currently being considered for addition/removal.
61 const ACTIVE_FEATURES:
62 &'static [(&'static str, &'static str, Option<u32>, fn(&mut Features, Span))] =
63 &[$((stringify!($feature), $ver, $issue, set!($feature))),+];
65 /// A set of features to be used by later passes.
67 /// #![feature] attrs for stable language features, for error reporting
68 pub declared_stable_lang_features: Vec<(Symbol, Span)>,
69 /// #![feature] attrs for non-language (library) features
70 pub declared_lib_features: Vec<(Symbol, Span)>,
71 $(pub $feature: bool),+
75 pub fn new() -> Features {
77 declared_stable_lang_features: Vec::new(),
78 declared_lib_features: Vec::new(),
85 ($((removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
86 /// Represents unstable features which have since been removed (it was once Active)
87 const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
88 $((stringify!($feature), $ver, $issue)),+
92 ($((stable_removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
93 /// Represents stable features which have since been removed (it was once Accepted)
94 const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
95 $((stringify!($feature), $ver, $issue)),+
99 ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => {
100 /// Those language feature has since been Accepted (it was once Active)
101 const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
102 $((stringify!($feature), $ver, $issue)),+
107 // If you change this, please modify src/doc/unstable-book as well.
109 // Don't ever remove anything from this list; set them to 'Removed'.
111 // The version numbers here correspond to the version in which the current status
112 // was set. This is most important for knowing when a particular feature became
115 // NB: tools/tidy/src/features.rs parses this information directly out of the
116 // source, so take care when modifying it.
119 (active, asm, "1.0.0", Some(29722)),
120 (active, concat_idents, "1.0.0", Some(29599)),
121 (active, link_args, "1.0.0", Some(29596)),
122 (active, log_syntax, "1.0.0", Some(29598)),
123 (active, non_ascii_idents, "1.0.0", Some(28979)),
124 (active, plugin_registrar, "1.0.0", Some(29597)),
125 (active, thread_local, "1.0.0", Some(29594)),
126 (active, trace_macros, "1.0.0", Some(29598)),
128 // rustc internal, for now:
129 (active, intrinsics, "1.0.0", None),
130 (active, lang_items, "1.0.0", None),
132 (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
133 (active, linkage, "1.0.0", Some(29603)),
134 (active, quote, "1.0.0", Some(29601)),
135 (active, simd, "1.0.0", Some(27731)),
139 (active, rustc_diagnostic_macros, "1.0.0", None),
140 (active, rustc_const_unstable, "1.0.0", None),
141 (active, advanced_slice_patterns, "1.0.0", Some(23121)),
142 (active, box_syntax, "1.0.0", Some(27779)),
143 (active, placement_in_syntax, "1.0.0", Some(27779)),
144 (active, unboxed_closures, "1.0.0", Some(29625)),
146 (active, fundamental, "1.0.0", Some(29635)),
147 (active, main, "1.0.0", Some(29634)),
148 (active, needs_allocator, "1.4.0", Some(27389)),
149 (active, on_unimplemented, "1.0.0", Some(29628)),
150 (active, plugin, "1.0.0", Some(29597)),
151 (active, simd_ffi, "1.0.0", Some(27731)),
152 (active, start, "1.0.0", Some(29633)),
153 (active, structural_match, "1.8.0", Some(31434)),
154 (active, panic_runtime, "1.10.0", Some(32837)),
155 (active, needs_panic_runtime, "1.10.0", Some(32837)),
157 // OIBIT specific features
158 (active, optin_builtin_traits, "1.0.0", Some(13231)),
160 // macro reexport needs more discussion and stabilization
161 (active, macro_reexport, "1.0.0", Some(29638)),
163 // Allows use of #[staged_api]
165 (active, staged_api, "1.0.0", None),
167 // Allows using #![no_core]
168 (active, no_core, "1.3.0", Some(29639)),
170 // Allows using `box` in patterns; RFC 469
171 (active, box_patterns, "1.0.0", Some(29641)),
173 // Allows using the unsafe_destructor_blind_to_params attribute;
175 (active, dropck_parametricity, "1.3.0", Some(28498)),
177 // Allows using the may_dangle attribute; RFC 1327
178 (active, dropck_eyepatch, "1.10.0", Some(34761)),
180 // Allows the use of custom attributes; RFC 572
181 (active, custom_attribute, "1.0.0", Some(29642)),
183 // Allows the use of #[derive(Anything)] as sugar for
184 // #[derive_Anything].
185 (active, custom_derive, "1.0.0", Some(29644)),
187 // Allows the use of rustc_* attributes; RFC 572
188 (active, rustc_attrs, "1.0.0", Some(29642)),
190 // Allows the use of #[allow_internal_unstable]. This is an
191 // attribute on macro_rules! and can't use the attribute handling
192 // below (it has to be checked before expansion possibly makes
193 // macros disappear).
196 (active, allow_internal_unstable, "1.0.0", None),
198 // Allows the use of #[allow_internal_unsafe]. This is an
199 // attribute on macro_rules! and can't use the attribute handling
200 // below (it has to be checked before expansion possibly makes
201 // macros disappear).
204 (active, allow_internal_unsafe, "1.0.0", None),
206 // #23121. Array patterns have some hazards yet.
207 (active, slice_patterns, "1.0.0", Some(23121)),
209 // Allows the definition of `const fn` functions.
210 (active, const_fn, "1.2.0", Some(24111)),
212 // Allows indexing into constant arrays.
213 (active, const_indexing, "1.4.0", Some(29947)),
215 // Allows using #[prelude_import] on glob `use` items.
218 (active, prelude_import, "1.2.0", None),
220 // Allows default type parameters to influence type inference.
221 (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
223 // Allows associated type defaults
224 (active, associated_type_defaults, "1.2.0", Some(29661)),
226 // allow `repr(simd)`, and importing the various simd intrinsics
227 (active, repr_simd, "1.4.0", Some(27731)),
229 // Allows cfg(target_feature = "...").
230 (active, cfg_target_feature, "1.4.0", Some(29717)),
232 // allow `extern "platform-intrinsic" { ... }`
233 (active, platform_intrinsics, "1.4.0", Some(27731)),
236 // rust runtime internal
237 (active, unwind_attributes, "1.4.0", None),
239 // allow the use of `#[naked]` on functions.
240 (active, naked_functions, "1.9.0", Some(32408)),
242 // allow `#[no_debug]`
243 (active, no_debug, "1.5.0", Some(29721)),
245 // allow `#[omit_gdb_pretty_printer_section]`
247 (active, omit_gdb_pretty_printer_section, "1.5.0", None),
249 // Allows cfg(target_vendor = "...").
250 (active, cfg_target_vendor, "1.5.0", Some(29718)),
252 // Allow attributes on expressions and non-item statements
253 (active, stmt_expr_attributes, "1.6.0", Some(15701)),
255 // allow using type ascription in expressions
256 (active, type_ascription, "1.6.0", Some(23416)),
258 // Allows cfg(target_thread_local)
259 (active, cfg_target_thread_local, "1.7.0", Some(29594)),
262 (active, abi_vectorcall, "1.7.0", None),
265 (active, inclusive_range_syntax, "1.7.0", Some(28237)),
268 (active, exclusive_range_pattern, "1.11.0", Some(37854)),
270 // impl specialization (RFC 1210)
271 (active, specialization, "1.7.0", Some(31844)),
273 // Allows cfg(target_has_atomic = "...").
274 (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
276 // Allows `impl Trait` in function return types.
277 (active, conservative_impl_trait, "1.12.0", Some(34511)),
280 (active, never_type, "1.13.0", Some(35121)),
282 // Allows all literals in attribute lists and values of key-value pairs.
283 (active, attr_literals, "1.13.0", Some(34981)),
285 // Allows the sysV64 ABI to be specified on all platforms
286 // instead of just the platforms on which it is the C ABI
287 (active, abi_sysv64, "1.13.0", Some(36167)),
289 // Allows untagged unions `union U { ... }`
290 (active, untagged_unions, "1.13.0", Some(32836)),
292 // Used to identify the `compiler_builtins` crate
294 (active, compiler_builtins, "1.13.0", None),
296 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
297 (active, generic_param_attrs, "1.11.0", Some(34761)),
299 // Allows #[link(..., cfg(..))]
300 (active, link_cfg, "1.14.0", Some(37406)),
302 (active, use_extern_macros, "1.15.0", Some(35896)),
304 // Allows #[target_feature(...)]
305 (active, target_feature, "1.15.0", None),
307 // `extern "ptx-*" fn()`
308 (active, abi_ptx, "1.15.0", None),
311 (active, i128_type, "1.16.0", Some(35118)),
313 // The `repr(i128)` annotation for enums
314 (active, repr128, "1.16.0", Some(35118)),
316 // The `unadjusted` ABI. Perma unstable.
317 (active, abi_unadjusted, "1.16.0", None),
319 // Procedural macros 2.0.
320 (active, proc_macro, "1.16.0", Some(38356)),
322 // Declarative macros 2.0 (`macro`).
323 (active, decl_macro, "1.17.0", Some(39412)),
325 // Allows #[link(kind="static-nobundle"...]
326 (active, static_nobundle, "1.16.0", Some(37403)),
328 // `extern "msp430-interrupt" fn()`
329 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
331 // Used to identify crates that contain sanitizer runtimes
333 (active, sanitizer_runtime, "1.17.0", None),
335 // Used to identify crates that contain the profiler runtime
337 (active, profiler_runtime, "1.18.0", None),
339 // `extern "x86-interrupt" fn()`
340 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
343 // Allows the `catch {...}` expression
344 (active, catch_expr, "1.17.0", Some(31436)),
346 // Allows `repr(align(u16))` struct attribute (RFC 1358)
347 (active, repr_align, "1.17.0", Some(33626)),
349 // Used to preserve symbols (see llvm.used)
350 (active, used, "1.18.0", Some(40289)),
352 // Allows module-level inline assembly by way of global_asm!()
353 (active, global_asm, "1.18.0", Some(35119)),
355 // Allows overlapping impls of marker traits
356 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
358 // Allows use of the :vis macro fragment specifier
359 (active, macro_vis_matcher, "1.18.0", Some(41022)),
362 (active, abi_thiscall, "1.19.0", None),
364 // Allows a test to fail without failing the whole suite
365 (active, allow_fail, "1.19.0", Some(42219)),
367 // Allows unsized tuple coercion.
368 (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
371 (active, generators, "1.21.0", None),
374 // global allocators and their internals
375 (active, global_allocator, "1.20.0", None),
376 (active, allocator_internals, "1.20.0", None),
379 (active, doc_cfg, "1.21.0", Some(43781)),
381 (active, doc_masked, "1.21.0", None),
383 // allow `#[must_use]` on functions (RFC 1940)
384 (active, fn_must_use, "1.21.0", Some(43302)),
386 // allow '|' at beginning of match arms (RFC 1925)
387 (active, match_beginning_vert, "1.21.0", Some(44101)),
389 // Copy/Clone closures (RFC 2132)
390 (active, clone_closures, "1.22.0", Some(44490)),
391 (active, copy_closures, "1.22.0", Some(44490)),
393 // allow `'_` placeholder lifetimes
394 (active, underscore_lifetimes, "1.22.0", Some(44524)),
398 (removed, import_shadowing, "1.0.0", None),
399 (removed, managed_boxes, "1.0.0", None),
400 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
401 (removed, negate_unsigned, "1.0.0", Some(29645)),
402 (removed, reflect, "1.0.0", Some(27749)),
403 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
404 (removed, opt_out_copy, "1.0.0", None),
405 (removed, quad_precision_float, "1.0.0", None),
406 (removed, struct_inherit, "1.0.0", None),
407 (removed, test_removed_feature, "1.0.0", None),
408 (removed, visible_private_types, "1.0.0", None),
409 (removed, unsafe_no_drop_flag, "1.0.0", None),
410 // Allows using items which are missing stability attributes
412 (removed, unmarked_api, "1.0.0", None),
413 (removed, pushpop_unsafe, "1.2.0", None),
414 (removed, allocator, "1.0.0", None),
418 (stable_removed, no_stack_check, "1.0.0", None),
422 (accepted, associated_types, "1.0.0", None),
423 // allow overloading augmented assignment operations like `a += b`
424 (accepted, augmented_assignments, "1.8.0", Some(28235)),
425 // allow empty structs and enum variants with braces
426 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
427 (accepted, default_type_params, "1.0.0", None),
428 (accepted, globs, "1.0.0", None),
429 (accepted, if_let, "1.0.0", None),
430 // A temporary feature gate used to enable parser extensions needed
431 // to bootstrap fix for #5723.
432 (accepted, issue_5723_bootstrap, "1.0.0", None),
433 (accepted, macro_rules, "1.0.0", None),
434 // Allows using #![no_std]
435 (accepted, no_std, "1.6.0", None),
436 (accepted, slicing_syntax, "1.0.0", None),
437 (accepted, struct_variant, "1.0.0", None),
438 // These are used to test this portion of the compiler, they don't actually
440 (accepted, test_accepted_feature, "1.0.0", None),
441 (accepted, tuple_indexing, "1.0.0", None),
442 // Allows macros to appear in the type position.
443 (accepted, type_macros, "1.13.0", Some(27245)),
444 (accepted, while_let, "1.0.0", None),
445 // Allows `#[deprecated]` attribute
446 (accepted, deprecated, "1.9.0", Some(29935)),
448 (accepted, question_mark, "1.13.0", Some(31436)),
449 // Allows `..` in tuple (struct) patterns
450 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
451 (accepted, item_like_imports, "1.15.0", Some(35120)),
452 // Allows using `Self` and associated types in struct expressions and patterns.
453 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
454 // elide `'static` lifetimes in `static`s and `const`s
455 (accepted, static_in_const, "1.17.0", Some(35897)),
456 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
457 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
458 // Allows the definition recursive static items.
459 (accepted, static_recursion, "1.17.0", Some(29719)),
460 // pub(restricted) visibilities (RFC 1422)
461 (accepted, pub_restricted, "1.18.0", Some(32409)),
462 // The #![windows_subsystem] attribute
463 (accepted, windows_subsystem, "1.18.0", Some(37499)),
464 // Allows `break {expr}` with a value inside `loop`s.
465 (accepted, loop_break_value, "1.19.0", Some(37339)),
466 // Permits numeric fields in struct expressions and patterns.
467 (accepted, relaxed_adts, "1.19.0", Some(35626)),
468 // Coerces non capturing closures to function pointers
469 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
470 // Allows attributes on struct literal fields.
471 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
472 // Allows the definition of associated constants in `trait` or `impl`
474 (accepted, associated_consts, "1.20.0", Some(29646)),
475 // Usage of the `compile_error!` macro
476 (accepted, compile_error, "1.20.0", Some(40872)),
477 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
478 (accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
479 // Allow Drop types in constants (RFC 1440)
480 (accepted, drop_types_in_const, "1.22.0", Some(33156)),
483 // If you change this, please modify src/doc/unstable-book as well. You must
484 // move that documentation into the relevant place in the other docs, and
485 // remove the chapter on the flag.
487 #[derive(PartialEq, Copy, Clone, Debug)]
488 pub enum AttributeType {
489 /// Normal, builtin attribute that is consumed
490 /// by the compiler before the unused_attribute check
493 /// Builtin attribute that may not be consumed by the compiler
494 /// before the unused_attribute check. These attributes
495 /// will be ignored by the unused_attribute lint
498 /// Builtin attribute that is only allowed at the crate level
502 pub enum AttributeGate {
503 /// Is gated by a given feature gate, reason
504 /// and function to check if enabled
505 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
507 /// Ungated attribute, can be used on all release channels
512 fn is_deprecated(&self) -> bool {
514 Gated(Stability::Deprecated(_), ..) => true,
520 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
523 // Argument is tracking issue link.
524 Deprecated(&'static str),
528 impl ::std::fmt::Debug for AttributeGate {
529 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
531 Gated(ref stab, name, expl, _) =>
532 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
533 Ungated => write!(fmt, "Ungated")
538 macro_rules! cfg_fn {
539 ($field: ident) => {{
540 fn f(features: &Features) -> bool {
543 f as fn(&Features) -> bool
547 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
548 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
551 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
552 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
555 // Attributes that have a special meaning to rustc or rustdoc
556 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
559 ("warn", Normal, Ungated),
560 ("allow", Normal, Ungated),
561 ("forbid", Normal, Ungated),
562 ("deny", Normal, Ungated),
564 ("macro_reexport", Normal, Ungated),
565 ("macro_use", Normal, Ungated),
566 ("macro_export", Normal, Ungated),
567 ("plugin_registrar", Normal, Ungated),
569 ("cfg", Normal, Ungated),
570 ("cfg_attr", Normal, Ungated),
571 ("main", Normal, Ungated),
572 ("start", Normal, Ungated),
573 ("test", Normal, Ungated),
574 ("bench", Normal, Ungated),
575 ("simd", Normal, Ungated),
576 ("repr", Normal, Ungated),
577 ("path", Normal, Ungated),
578 ("abi", Normal, Ungated),
579 ("automatically_derived", Normal, Ungated),
580 ("no_mangle", Normal, Ungated),
581 ("no_link", Normal, Ungated),
582 ("derive", Normal, Ungated),
583 ("should_panic", Normal, Ungated),
584 ("ignore", Normal, Ungated),
585 ("no_implicit_prelude", Normal, Ungated),
586 ("reexport_test_harness_main", Normal, Ungated),
587 ("link_args", Normal, Gated(Stability::Unstable,
589 "the `link_args` attribute is experimental and not \
590 portable across platforms, it is recommended to \
591 use `#[link(name = \"foo\")] instead",
592 cfg_fn!(link_args))),
593 ("macro_escape", Normal, Ungated),
596 ("structural_match", Whitelisted, Gated(Stability::Unstable,
598 "the semantics of constant patterns is \
600 cfg_fn!(structural_match))),
602 ("plugin", CrateLevel, Gated(Stability::Unstable,
604 "compiler plugins are experimental \
608 ("no_std", CrateLevel, Ungated),
609 ("no_core", CrateLevel, Gated(Stability::Unstable,
611 "no_core is experimental",
613 ("lang", Normal, Gated(Stability::Unstable,
615 "language items are subject to change",
616 cfg_fn!(lang_items))),
617 ("linkage", Whitelisted, Gated(Stability::Unstable,
619 "the `linkage` attribute is experimental \
620 and not portable across platforms",
622 ("thread_local", Whitelisted, Gated(Stability::Unstable,
624 "`#[thread_local]` is an experimental feature, and does \
625 not currently handle destructors. There is no \
626 corresponding `#[task_local]` mapping to the task \
628 cfg_fn!(thread_local))),
630 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
632 "the `#[rustc_on_unimplemented]` attribute \
633 is an experimental feature",
634 cfg_fn!(on_unimplemented))),
635 ("rustc_const_unstable", Normal, Gated(Stability::Unstable,
636 "rustc_const_unstable",
637 "the `#[rustc_const_unstable]` attribute \
638 is an internal feature",
639 cfg_fn!(rustc_const_unstable))),
640 ("global_allocator", Normal, Gated(Stability::Unstable,
642 "the `#[global_allocator]` attribute is \
643 an experimental feature",
644 cfg_fn!(global_allocator))),
645 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
646 "allocator_internals",
647 "the `#[default_lib_allocator]` \
648 attribute is an experimental feature",
649 cfg_fn!(allocator_internals))),
650 ("needs_allocator", Normal, Gated(Stability::Unstable,
651 "allocator_internals",
652 "the `#[needs_allocator]` \
653 attribute is an experimental \
655 cfg_fn!(allocator_internals))),
656 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
658 "the `#[panic_runtime]` attribute is \
659 an experimental feature",
660 cfg_fn!(panic_runtime))),
661 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
662 "needs_panic_runtime",
663 "the `#[needs_panic_runtime]` \
664 attribute is an experimental \
666 cfg_fn!(needs_panic_runtime))),
667 ("rustc_variance", Normal, Gated(Stability::Unstable,
669 "the `#[rustc_variance]` attribute \
670 is just used for rustc unit tests \
671 and will never be stable",
672 cfg_fn!(rustc_attrs))),
673 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
675 "the `#[rustc_error]` attribute \
676 is just used for rustc unit tests \
677 and will never be stable",
678 cfg_fn!(rustc_attrs))),
679 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
681 "the `#[rustc_if_this_changed]` attribute \
682 is just used for rustc unit tests \
683 and will never be stable",
684 cfg_fn!(rustc_attrs))),
685 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
687 "the `#[rustc_if_this_changed]` attribute \
688 is just used for rustc unit tests \
689 and will never be stable",
690 cfg_fn!(rustc_attrs))),
691 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
693 "the `#[rustc_dirty]` attribute \
694 is just used for rustc unit tests \
695 and will never be stable",
696 cfg_fn!(rustc_attrs))),
697 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
699 "the `#[rustc_clean]` attribute \
700 is just used for rustc unit tests \
701 and will never be stable",
702 cfg_fn!(rustc_attrs))),
703 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
705 "the `#[rustc_metadata_dirty]` attribute \
706 is just used for rustc unit tests \
707 and will never be stable",
708 cfg_fn!(rustc_attrs))),
709 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
711 "the `#[rustc_metadata_clean]` attribute \
712 is just used for rustc unit tests \
713 and will never be stable",
714 cfg_fn!(rustc_attrs))),
715 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
718 is just used for rustc unit tests \
719 and will never be stable",
720 cfg_fn!(rustc_attrs))),
721 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
724 is just used for rustc unit tests \
725 and will never be stable",
726 cfg_fn!(rustc_attrs))),
727 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
729 "internal rustc attributes will never be stable",
730 cfg_fn!(rustc_attrs))),
731 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
733 "internal rustc attributes will never be stable",
734 cfg_fn!(rustc_attrs))),
735 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
737 "the `#[rustc_mir]` attribute \
738 is just used for rustc unit tests \
739 and will never be stable",
740 cfg_fn!(rustc_attrs))),
741 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
743 "the `#[rustc_inherit_overflow_checks]` \
744 attribute is just used to control \
745 overflow checking behavior of several \
746 libcore functions that are inlined \
747 across crates and will never be stable",
748 cfg_fn!(rustc_attrs))),
749 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
751 "the `#[compiler_builtins]` attribute is used to \
752 identify the `compiler_builtins` crate which \
753 contains compiler-rt intrinsics and will never be \
755 cfg_fn!(compiler_builtins))),
756 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
758 "the `#[sanitizer_runtime]` attribute is used to \
759 identify crates that contain the runtime of a \
760 sanitizer and will never be stable",
761 cfg_fn!(sanitizer_runtime))),
762 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
764 "the `#[profiler_runtime]` attribute is used to \
765 identify the `profiler_builtins` crate which \
766 contains the profiler runtime and will never be \
768 cfg_fn!(profiler_runtime))),
770 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
771 "allow_internal_unstable",
772 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
773 cfg_fn!(allow_internal_unstable))),
775 ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
776 "allow_internal_unsafe",
777 EXPLAIN_ALLOW_INTERNAL_UNSAFE,
778 cfg_fn!(allow_internal_unsafe))),
780 ("fundamental", Whitelisted, Gated(Stability::Unstable,
782 "the `#[fundamental]` attribute \
783 is an experimental feature",
784 cfg_fn!(fundamental))),
786 ("proc_macro_derive", Normal, Ungated),
788 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
790 "internal implementation detail",
791 cfg_fn!(rustc_attrs))),
793 // FIXME: #14408 whitelist docs since rustdoc looks at them
794 ("doc", Whitelisted, Ungated),
796 // FIXME: #14406 these are processed in trans, which happens after the
798 ("cold", Whitelisted, Ungated),
799 ("naked", Whitelisted, Gated(Stability::Unstable,
801 "the `#[naked]` attribute \
802 is an experimental feature",
803 cfg_fn!(naked_functions))),
804 ("target_feature", Whitelisted, Gated(
805 Stability::Unstable, "target_feature",
806 "the `#[target_feature]` attribute is an experimental feature",
807 cfg_fn!(target_feature))),
808 ("export_name", Whitelisted, Ungated),
809 ("inline", Whitelisted, Ungated),
810 ("link", Whitelisted, Ungated),
811 ("link_name", Whitelisted, Ungated),
812 ("link_section", Whitelisted, Ungated),
813 ("no_builtins", Whitelisted, Ungated),
814 ("no_mangle", Whitelisted, Ungated),
815 ("no_debug", Whitelisted, Gated(
816 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
818 "the `#[no_debug]` attribute is an experimental feature",
820 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
821 "omit_gdb_pretty_printer_section",
822 "the `#[omit_gdb_pretty_printer_section]` \
823 attribute is just used for the Rust test \
825 cfg_fn!(omit_gdb_pretty_printer_section))),
826 ("unsafe_destructor_blind_to_params",
828 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
829 "dropck_parametricity",
830 "unsafe_destructor_blind_to_params has been replaced by \
831 may_dangle and will be removed in the future",
832 cfg_fn!(dropck_parametricity))),
835 Gated(Stability::Unstable,
837 "may_dangle has unstable semantics and may be removed in the future",
838 cfg_fn!(dropck_eyepatch))),
839 ("unwind", Whitelisted, Gated(Stability::Unstable,
841 "#[unwind] is experimental",
842 cfg_fn!(unwind_attributes))),
843 ("used", Whitelisted, Gated(
844 Stability::Unstable, "used",
845 "the `#[used]` attribute is an experimental feature",
849 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
851 "`#[prelude_import]` is for use by rustc only",
852 cfg_fn!(prelude_import))),
854 // FIXME: #14407 these are only looked at on-demand so we can't
855 // guarantee they'll have already been checked
856 ("rustc_deprecated", Whitelisted, Ungated),
857 ("must_use", Whitelisted, Ungated),
858 ("stable", Whitelisted, Ungated),
859 ("unstable", Whitelisted, Ungated),
860 ("deprecated", Normal, Ungated),
862 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
864 "unboxed_closures are still evolving",
865 cfg_fn!(unboxed_closures))),
867 ("windows_subsystem", Whitelisted, Ungated),
869 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
871 "attribute proc macros are currently unstable",
872 cfg_fn!(proc_macro))),
874 ("proc_macro", Normal, Gated(Stability::Unstable,
876 "function-like proc macros are currently unstable",
877 cfg_fn!(proc_macro))),
879 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
880 "rustc_derive_registrar",
881 "used internally by rustc",
882 cfg_fn!(rustc_attrs))),
884 ("allow_fail", Normal, Gated(Stability::Unstable,
886 "allow_fail attribute is currently unstable",
887 cfg_fn!(allow_fail))),
889 // Crate level attributes
890 ("crate_name", CrateLevel, Ungated),
891 ("crate_type", CrateLevel, Ungated),
892 ("crate_id", CrateLevel, Ungated),
893 ("feature", CrateLevel, Ungated),
894 ("no_start", CrateLevel, Ungated),
895 ("no_main", CrateLevel, Ungated),
896 ("no_builtins", CrateLevel, Ungated),
897 ("recursion_limit", CrateLevel, Ungated),
898 ("type_length_limit", CrateLevel, Ungated),
901 // cfg(...)'s that are feature gated
902 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
903 // (name in cfg, feature, function to check if the feature is enabled)
904 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
905 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
906 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
907 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
910 #[derive(Debug, Eq, PartialEq)]
911 pub struct GatedCfg {
917 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
918 let name = cfg.name().as_str();
920 .position(|info| info.0 == name)
929 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
930 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
931 if !has_feature(features) && !self.span.allows_unstable() {
932 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
933 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
939 features: &'a Features,
940 parse_sess: &'a ParseSess,
941 plugin_attributes: &'a [(String, AttributeType)],
944 macro_rules! gate_feature_fn {
945 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
946 let (cx, has_feature, span,
947 name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
948 let has_feature: bool = has_feature(&$cx.features);
949 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
950 if !has_feature && !span.allows_unstable() {
951 leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
957 macro_rules! gate_feature {
958 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
959 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
960 stringify!($feature), $explain, GateStrength::Hard)
962 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
963 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
964 stringify!($feature), $explain, $level)
968 impl<'a> Context<'a> {
969 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
970 debug!("check_attribute(attr = {:?})", attr);
971 let name = unwrap_or!(attr.name(), return).as_str();
972 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
974 if let Gated(_, name, desc, ref has_feature) = *gateage {
975 gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
977 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
981 for &(ref n, ref ty) in self.plugin_attributes {
982 if attr.path == &**n {
983 // Plugins can't gate attributes, so we don't check for it
984 // unlike the code above; we only use this loop to
985 // short-circuit to avoid the checks below
986 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
990 if name.starts_with("rustc_") {
991 gate_feature!(self, rustc_attrs, attr.span,
992 "unless otherwise specified, attributes \
993 with the prefix `rustc_` \
994 are reserved for internal compiler diagnostics");
995 } else if name.starts_with("derive_") {
996 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
997 } else if !attr::is_known(attr) {
998 // Only run the custom attribute lint during regular
999 // feature gate checking. Macro gating runs
1000 // before the plugin attributes are registered
1001 // so we skip this then
1003 gate_feature!(self, custom_attribute, attr.span,
1004 &format!("The attribute `{}` is currently \
1005 unknown to the compiler and \
1007 added to it in the future",
1014 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
1015 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
1016 cx.check_attribute(attr, true);
1019 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
1020 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
1023 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
1024 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
1026 // FIXME (#28244): enforce that active features have issue numbers
1027 // assert!(issue.is_some())
1030 // search in Accepted, Removed, or Stable Removed features
1031 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
1032 .find(|t| t.0 == feature);
1034 Some(&(_, _, issue)) => issue,
1035 None => panic!("Feature `{}` is not declared anywhere", feature),
1040 pub enum GateIssue {
1042 Library(Option<u32>)
1045 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1046 pub enum GateStrength {
1047 /// A hard error. (Most feature gates should use this.)
1049 /// Only a warning. (Use this only as backwards-compatibility demands.)
1053 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1055 feature_err(sess, feature, span, issue, explain).emit();
1058 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1059 explain: &str) -> DiagnosticBuilder<'a> {
1060 leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
1063 fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1064 explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
1065 let diag = &sess.span_diagnostic;
1067 let issue = match issue {
1068 GateIssue::Language => find_lang_feature_issue(feature),
1069 GateIssue::Library(lib) => lib,
1072 let explanation = if let Some(n) = issue {
1073 format!("{} (see issue #{})", explain, n)
1078 let mut err = match level {
1079 GateStrength::Hard => diag.struct_span_err(span, &explanation),
1080 GateStrength::Soft => diag.struct_span_warn(span, &explanation),
1083 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1084 if sess.unstable_features.is_nightly_build() {
1085 err.help(&format!("add #![feature({})] to the \
1086 crate attributes to enable",
1090 // If we're on stable and only emitting a "soft" warning, add a note to
1091 // clarify that the feature isn't "on" (rather than being on but
1093 if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
1094 err.help("a nightly build of the compiler is required to enable this feature");
1101 const EXPLAIN_BOX_SYNTAX: &'static str =
1102 "box expression syntax is experimental; you can call `Box::new` instead.";
1104 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1105 "attributes on non-item statements and expressions are experimental.";
1107 pub const EXPLAIN_ASM: &'static str =
1108 "inline assembly is not stable enough for use and is subject to change";
1110 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1111 "`global_asm!` is not stable enough for use and is subject to change";
1113 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1114 "`log_syntax!` is not stable enough for use and is subject to change";
1116 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1117 "`concat_idents` is not stable enough for use and is subject to change";
1119 pub const EXPLAIN_TRACE_MACROS: &'static str =
1120 "`trace_macros` is not stable enough for use and is subject to change";
1121 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1122 "allow_internal_unstable side-steps feature gating and stability checks";
1123 pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
1124 "allow_internal_unsafe side-steps the unsafe_code lint";
1126 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1127 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1129 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1130 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1131 Prefer using procedural macro custom derive.";
1133 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1134 "attributes of the form `#[derive_*]` are reserved for the compiler";
1136 pub const EXPLAIN_VIS_MATCHER: &'static str =
1137 ":vis fragment specifier is experimental and subject to change";
1139 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1140 "placement-in expression syntax is experimental and subject to change.";
1142 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1143 "Unsized tuple coercion is not stable enough for use and is subject to change";
1145 struct PostExpansionVisitor<'a> {
1146 context: &'a Context<'a>,
1149 macro_rules! gate_feature_post {
1150 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1151 let (cx, span) = ($cx, $span);
1152 if !span.allows_unstable() {
1153 gate_feature!(cx.context, $feature, span, $explain)
1156 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
1157 let (cx, span) = ($cx, $span);
1158 if !span.allows_unstable() {
1159 gate_feature!(cx.context, $feature, span, $explain, $level)
1164 impl<'a> PostExpansionVisitor<'a> {
1165 fn check_abi(&self, abi: Abi, span: Span) {
1167 Abi::RustIntrinsic => {
1168 gate_feature_post!(&self, intrinsics, span,
1169 "intrinsics are subject to change");
1171 Abi::PlatformIntrinsic => {
1172 gate_feature_post!(&self, platform_intrinsics, span,
1173 "platform intrinsics are experimental and possibly buggy");
1175 Abi::Vectorcall => {
1176 gate_feature_post!(&self, abi_vectorcall, span,
1177 "vectorcall is experimental and subject to change");
1180 gate_feature_post!(&self, abi_thiscall, span,
1181 "thiscall is experimental and subject to change");
1184 gate_feature_post!(&self, unboxed_closures, span,
1185 "rust-call ABI is subject to change");
1188 gate_feature_post!(&self, abi_sysv64, span,
1189 "sysv64 ABI is experimental and subject to change");
1192 gate_feature_post!(&self, abi_ptx, span,
1193 "PTX ABIs are experimental and subject to change");
1195 Abi::Unadjusted => {
1196 gate_feature_post!(&self, abi_unadjusted, span,
1197 "unadjusted ABI is an implementation detail and perma-unstable");
1199 Abi::Msp430Interrupt => {
1200 gate_feature_post!(&self, abi_msp430_interrupt, span,
1201 "msp430-interrupt ABI is experimental and subject to change");
1203 Abi::X86Interrupt => {
1204 gate_feature_post!(&self, abi_x86_interrupt, span,
1205 "x86-interrupt ABI is experimental and subject to change");
1220 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1221 use ast::MetaItemKind::*;
1222 use ast::NestedMetaItemKind::*;
1226 NameValue(ref lit) => !lit.node.is_str(),
1227 List(ref list) => list.iter().any(|li| {
1229 MetaItem(ref mi) => contains_novel_literal(mi),
1236 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1237 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1238 if !attr.span.allows_unstable() {
1239 // check for gated attributes
1240 self.context.check_attribute(attr, false);
1243 if attr.check_name("doc") {
1244 if let Some(content) = attr.meta_item_list() {
1245 if content.len() == 1 && content[0].check_name("cfg") {
1246 gate_feature_post!(&self, doc_cfg, attr.span,
1247 "#[doc(cfg(...))] is experimental"
1249 } else if content.iter().any(|c| c.check_name("masked")) {
1250 gate_feature_post!(&self, doc_masked, attr.span,
1251 "#[doc(masked)] is experimental"
1257 if self.context.features.proc_macro && attr::is_known(attr) {
1261 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1262 if contains_novel_literal(&meta) {
1263 gate_feature_post!(&self, attr_literals, attr.span,
1264 "non-string literals in attributes, or string \
1265 literals in top-level positions, are experimental");
1269 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1270 if !name.as_str().is_ascii() {
1271 gate_feature_post!(&self, non_ascii_idents, sp,
1272 "non-ascii idents are not fully supported.");
1276 fn visit_item(&mut self, i: &'a ast::Item) {
1278 ast::ItemKind::ExternCrate(_) => {
1279 if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
1280 gate_feature_post!(&self, macro_reexport, attr.span,
1281 "macros reexports are experimental \
1282 and possibly buggy");
1286 ast::ItemKind::ForeignMod(ref foreign_module) => {
1287 self.check_abi(foreign_module.abi, i.span);
1290 ast::ItemKind::Fn(..) => {
1291 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1292 gate_feature_post!(&self, plugin_registrar, i.span,
1293 "compiler plugins are experimental and possibly buggy");
1295 if attr::contains_name(&i.attrs[..], "start") {
1296 gate_feature_post!(&self, start, i.span,
1297 "a #[start] function is an experimental \
1298 feature whose signature may change \
1301 if attr::contains_name(&i.attrs[..], "main") {
1302 gate_feature_post!(&self, main, i.span,
1303 "declaration of a nonstandard #[main] \
1304 function may change over time, for now \
1305 a top-level `fn main()` is required");
1307 if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") {
1308 gate_feature_post!(&self, fn_must_use, attr.span,
1309 "`#[must_use]` on functions is experimental",
1310 GateStrength::Soft);
1314 ast::ItemKind::Struct(..) => {
1315 if let Some(attr) = attr::find_by_name(&i.attrs[..], "simd") {
1316 gate_feature_post!(&self, simd, attr.span,
1317 "SIMD types are experimental and possibly buggy");
1318 self.context.parse_sess.span_diagnostic.span_warn(attr.span,
1319 "the `#[simd]` attribute \
1320 is deprecated, use \
1321 `#[repr(simd)]` instead");
1323 if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
1324 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1325 if item.check_name("simd") {
1326 gate_feature_post!(&self, repr_simd, attr.span,
1327 "SIMD types are experimental and possibly buggy");
1329 if item.check_name("align") {
1330 gate_feature_post!(&self, repr_align, attr.span,
1331 "the struct `#[repr(align(u16))]` attribute \
1338 ast::ItemKind::DefaultImpl(..) => {
1339 gate_feature_post!(&self, optin_builtin_traits,
1341 "default trait implementations are experimental \
1342 and possibly buggy");
1345 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
1346 if polarity == ast::ImplPolarity::Negative {
1347 gate_feature_post!(&self, optin_builtin_traits,
1349 "negative trait bounds are not yet fully implemented; \
1350 use marker types for now");
1353 if let ast::Defaultness::Default = defaultness {
1354 gate_feature_post!(&self, specialization,
1356 "specialization is unstable");
1359 for impl_item in impl_items {
1360 if let ast::ImplItemKind::Method(..) = impl_item.node {
1361 if let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") {
1362 gate_feature_post!(&self, fn_must_use, attr.span,
1363 "`#[must_use]` on methods is experimental",
1364 GateStrength::Soft);
1370 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1371 let msg = "`macro` is experimental";
1372 gate_feature_post!(&self, decl_macro, i.span, msg);
1378 visit::walk_item(self, i);
1381 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1382 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1383 Some(val) => val.as_str().starts_with("llvm."),
1387 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1388 "linking to LLVM intrinsics is experimental");
1391 visit::walk_foreign_item(self, i)
1394 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1396 ast::TyKind::BareFn(ref bare_fn_ty) => {
1397 self.check_abi(bare_fn_ty.abi, ty.span);
1399 ast::TyKind::ImplTrait(..) => {
1400 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1401 "`impl Trait` is experimental");
1403 ast::TyKind::Never => {
1404 gate_feature_post!(&self, never_type, ty.span,
1405 "The `!` type is experimental");
1409 visit::walk_ty(self, ty)
1412 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1413 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1414 if output_ty.node != ast::TyKind::Never {
1415 self.visit_ty(output_ty)
1420 fn visit_expr(&mut self, e: &'a ast::Expr) {
1422 ast::ExprKind::Box(_) => {
1423 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1425 ast::ExprKind::Type(..) => {
1426 gate_feature_post!(&self, type_ascription, e.span,
1427 "type ascription is experimental");
1429 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1430 gate_feature_post!(&self, inclusive_range_syntax,
1432 "inclusive range syntax is experimental");
1434 ast::ExprKind::InPlace(..) => {
1435 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1437 ast::ExprKind::Yield(..) => {
1438 gate_feature_post!(&self, generators,
1440 "yield syntax is experimental");
1442 ast::ExprKind::Lit(ref lit) => {
1443 if let ast::LitKind::Int(_, ref ty) = lit.node {
1445 ast::LitIntType::Signed(ast::IntTy::I128) |
1446 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1447 gate_feature_post!(&self, i128_type, e.span,
1448 "128-bit integers are not stable");
1454 ast::ExprKind::Catch(_) => {
1455 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1459 visit::walk_expr(self, e);
1462 fn visit_arm(&mut self, arm: &'a ast::Arm) {
1463 if let Some(span) = arm.beginning_vert {
1464 gate_feature_post!(&self, match_beginning_vert,
1466 "Use of a '|' at the beginning of a match arm is experimental")
1468 visit::walk_arm(self, arm)
1471 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1472 match pattern.node {
1473 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1474 gate_feature_post!(&self, advanced_slice_patterns,
1476 "multiple-element slice matches anywhere \
1477 but at the end of a slice (e.g. \
1478 `[0, ..xs, 0]`) are experimental")
1480 PatKind::Slice(..) => {
1481 gate_feature_post!(&self, slice_patterns,
1483 "slice pattern syntax is experimental");
1485 PatKind::Box(..) => {
1486 gate_feature_post!(&self, box_patterns,
1488 "box pattern syntax is experimental");
1490 PatKind::Range(_, _, RangeEnd::Excluded) => {
1491 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1492 "exclusive range pattern syntax is experimental");
1496 visit::walk_pat(self, pattern)
1499 fn visit_fn(&mut self,
1500 fn_kind: FnKind<'a>,
1501 fn_decl: &'a ast::FnDecl,
1504 // check for const fn declarations
1505 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1507 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1509 // stability of const fn methods are covered in
1510 // visit_trait_item and visit_impl_item below; this is
1511 // because default methods don't pass through this
1515 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1516 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1517 self.check_abi(abi, span);
1521 visit::walk_fn(self, fn_kind, fn_decl, span);
1524 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1526 ast::TraitItemKind::Method(ref sig, ref block) => {
1527 if block.is_none() {
1528 self.check_abi(sig.abi, ti.span);
1530 if sig.constness.node == ast::Constness::Const {
1531 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1534 ast::TraitItemKind::Type(_, Some(_)) => {
1535 gate_feature_post!(&self, associated_type_defaults, ti.span,
1536 "associated type defaults are unstable");
1540 visit::walk_trait_item(self, ti);
1543 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1544 if ii.defaultness == ast::Defaultness::Default {
1545 gate_feature_post!(&self, specialization,
1547 "specialization is unstable");
1551 ast::ImplItemKind::Method(ref sig, _) => {
1552 if sig.constness.node == ast::Constness::Const {
1553 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1558 visit::walk_impl_item(self, ii);
1561 fn visit_generics(&mut self, g: &'a ast::Generics) {
1562 for t in &g.ty_params {
1563 if !t.attrs.is_empty() {
1564 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1565 "attributes on type parameter bindings are experimental");
1568 visit::walk_generics(self, g)
1571 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1572 if !lifetime_def.attrs.is_empty() {
1573 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1574 "attributes on lifetime bindings are experimental");
1576 visit::walk_lifetime_def(self, lifetime_def)
1579 fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
1580 if lt.ident.name == "'_" {
1581 gate_feature_post!(&self, underscore_lifetimes, lt.span,
1582 "underscore lifetimes are unstable");
1584 visit::walk_lifetime(self, lt)
1588 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1589 let mut features = Features::new();
1591 let mut feature_checker = FeatureChecker::default();
1593 for attr in krate_attrs {
1594 if !attr.check_name("feature") {
1598 match attr.meta_item_list() {
1600 span_err!(span_handler, attr.span, E0555,
1601 "malformed feature attribute, expected #![feature(...)]");
1605 let name = if let Some(word) = mi.word() {
1608 span_err!(span_handler, mi.span, E0556,
1609 "malformed feature, expected just one word");
1613 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1614 .find(|& &(n, _, _, _)| name == n) {
1615 set(&mut features, mi.span);
1616 feature_checker.collect(&features, mi.span);
1618 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1619 .find(|& &(n, _, _)| name == n)
1620 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1621 .find(|& &(n, _, _)| name == n)) {
1622 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1624 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1625 .find(|& &(n, _, _)| name == n) {
1626 features.declared_stable_lang_features.push((name, mi.span));
1628 features.declared_lib_features.push((name, mi.span));
1635 feature_checker.check(span_handler);
1640 /// A collector for mutually exclusive and interdependent features and their flag spans.
1642 struct FeatureChecker {
1643 proc_macro: Option<Span>,
1644 custom_attribute: Option<Span>,
1645 copy_closures: Option<Span>,
1646 clone_closures: Option<Span>,
1649 impl FeatureChecker {
1650 // If this method turns out to be a hotspot due to branching,
1651 // the branching can be eliminated by modifying `set!()` to set these spans
1652 // only for the features that need to be checked for mutual exclusion.
1653 fn collect(&mut self, features: &Features, span: Span) {
1654 if features.proc_macro {
1655 // If self.proc_macro is None, set to Some(span)
1656 self.proc_macro = self.proc_macro.or(Some(span));
1659 if features.custom_attribute {
1660 self.custom_attribute = self.custom_attribute.or(Some(span));
1663 if features.copy_closures {
1664 self.copy_closures = self.copy_closures.or(Some(span));
1667 if features.clone_closures {
1668 self.clone_closures = self.clone_closures.or(Some(span));
1672 fn check(self, handler: &Handler) {
1673 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1674 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1675 `#![feature(custom_attribute)] at the same time")
1676 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1682 if let (Some(span), None) = (self.copy_closures, self.clone_closures) {
1683 handler.struct_span_err(span, "`#![feature(copy_closures)]` can only be used with \
1684 `#![feature(clone_closures)]`")
1685 .span_note(span, "`#![feature(copy_closures)]` declared here")
1693 pub fn check_crate(krate: &ast::Crate,
1695 features: &Features,
1696 plugin_attributes: &[(String, AttributeType)],
1697 unstable: UnstableFeatures) {
1698 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1704 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1707 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1708 pub enum UnstableFeatures {
1709 /// Hard errors for unstable features are active, as on
1710 /// beta/stable channels.
1712 /// Allow features to be activated, as on nightly.
1714 /// Errors are bypassed for bootstrapping. This is required any time
1715 /// during the build that feature-related lints are set to warn or above
1716 /// because the build turns on warnings-as-errors and uses lots of unstable
1717 /// features. As a result, this is always required for building Rust itself.
1721 impl UnstableFeatures {
1722 pub fn from_environment() -> UnstableFeatures {
1723 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1724 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1725 // Whether we should enable unstable features for bootstrapping
1726 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1727 match (disable_unstable_features, bootstrap) {
1728 (_, true) => UnstableFeatures::Cheat,
1729 (true, _) => UnstableFeatures::Disallow,
1730 (false, _) => UnstableFeatures::Allow
1734 pub fn is_nightly_build(&self) -> bool {
1736 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1742 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1743 unstable: UnstableFeatures) {
1744 let allow_features = match unstable {
1745 UnstableFeatures::Allow => true,
1746 UnstableFeatures::Disallow => false,
1747 UnstableFeatures::Cheat => true
1749 if !allow_features {
1750 for attr in &krate.attrs {
1751 if attr.check_name("feature") {
1752 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1753 span_err!(span_handler, attr.span, E0554,
1754 "#![feature] may not be used on the {} release channel",