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, 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)),
376 // allow `#[must_use]` on functions (RFC 1940)
377 (active, fn_must_use, "1.21.0", Some(43302)),
381 (removed, import_shadowing, "1.0.0", None),
382 (removed, managed_boxes, "1.0.0", None),
383 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
384 (removed, negate_unsigned, "1.0.0", Some(29645)),
385 (removed, reflect, "1.0.0", Some(27749)),
386 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
387 (removed, opt_out_copy, "1.0.0", None),
388 (removed, quad_precision_float, "1.0.0", None),
389 (removed, struct_inherit, "1.0.0", None),
390 (removed, test_removed_feature, "1.0.0", None),
391 (removed, visible_private_types, "1.0.0", None),
392 (removed, unsafe_no_drop_flag, "1.0.0", None),
393 // Allows using items which are missing stability attributes
395 (removed, unmarked_api, "1.0.0", None),
396 (removed, pushpop_unsafe, "1.2.0", None),
397 (removed, allocator, "1.0.0", None),
401 (stable_removed, no_stack_check, "1.0.0", None),
405 (accepted, associated_types, "1.0.0", None),
406 // allow overloading augmented assignment operations like `a += b`
407 (accepted, augmented_assignments, "1.8.0", Some(28235)),
408 // allow empty structs and enum variants with braces
409 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
410 (accepted, default_type_params, "1.0.0", None),
411 (accepted, globs, "1.0.0", None),
412 (accepted, if_let, "1.0.0", None),
413 // A temporary feature gate used to enable parser extensions needed
414 // to bootstrap fix for #5723.
415 (accepted, issue_5723_bootstrap, "1.0.0", None),
416 (accepted, macro_rules, "1.0.0", None),
417 // Allows using #![no_std]
418 (accepted, no_std, "1.6.0", None),
419 (accepted, slicing_syntax, "1.0.0", None),
420 (accepted, struct_variant, "1.0.0", None),
421 // These are used to test this portion of the compiler, they don't actually
423 (accepted, test_accepted_feature, "1.0.0", None),
424 (accepted, tuple_indexing, "1.0.0", None),
425 // Allows macros to appear in the type position.
426 (accepted, type_macros, "1.13.0", Some(27245)),
427 (accepted, while_let, "1.0.0", None),
428 // Allows `#[deprecated]` attribute
429 (accepted, deprecated, "1.9.0", Some(29935)),
431 (accepted, question_mark, "1.13.0", Some(31436)),
432 // Allows `..` in tuple (struct) patterns
433 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
434 (accepted, item_like_imports, "1.15.0", Some(35120)),
435 // Allows using `Self` and associated types in struct expressions and patterns.
436 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
437 // elide `'static` lifetimes in `static`s and `const`s
438 (accepted, static_in_const, "1.17.0", Some(35897)),
439 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
440 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
441 // Allows the definition recursive static items.
442 (accepted, static_recursion, "1.17.0", Some(29719)),
443 // pub(restricted) visibilities (RFC 1422)
444 (accepted, pub_restricted, "1.18.0", Some(32409)),
445 // The #![windows_subsystem] attribute
446 (accepted, windows_subsystem, "1.18.0", Some(37499)),
447 // Allows `break {expr}` with a value inside `loop`s.
448 (accepted, loop_break_value, "1.19.0", Some(37339)),
449 // Permits numeric fields in struct expressions and patterns.
450 (accepted, relaxed_adts, "1.19.0", Some(35626)),
451 // Coerces non capturing closures to function pointers
452 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
453 // Allows attributes on struct literal fields.
454 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
455 // Allows the definition of associated constants in `trait` or `impl`
457 (accepted, associated_consts, "1.20.0", Some(29646)),
458 // Usage of the `compile_error!` macro
459 (accepted, compile_error, "1.20.0", Some(40872)),
460 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
461 (accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
464 // If you change this, please modify src/doc/unstable-book as well. You must
465 // move that documentation into the relevant place in the other docs, and
466 // remove the chapter on the flag.
468 #[derive(PartialEq, Copy, Clone, Debug)]
469 pub enum AttributeType {
470 /// Normal, builtin attribute that is consumed
471 /// by the compiler before the unused_attribute check
474 /// Builtin attribute that may not be consumed by the compiler
475 /// before the unused_attribute check. These attributes
476 /// will be ignored by the unused_attribute lint
479 /// Builtin attribute that is only allowed at the crate level
483 pub enum AttributeGate {
484 /// Is gated by a given feature gate, reason
485 /// and function to check if enabled
486 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
488 /// Ungated attribute, can be used on all release channels
493 fn is_deprecated(&self) -> bool {
495 Gated(Stability::Deprecated(_), ..) => true,
501 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
504 // Argument is tracking issue link.
505 Deprecated(&'static str),
509 impl ::std::fmt::Debug for AttributeGate {
510 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
512 Gated(ref stab, name, expl, _) =>
513 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
514 Ungated => write!(fmt, "Ungated")
519 macro_rules! cfg_fn {
520 ($field: ident) => {{
521 fn f(features: &Features) -> bool {
524 f as fn(&Features) -> bool
528 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
529 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
532 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
533 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
536 // Attributes that have a special meaning to rustc or rustdoc
537 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
540 ("warn", Normal, Ungated),
541 ("allow", Normal, Ungated),
542 ("forbid", Normal, Ungated),
543 ("deny", Normal, Ungated),
545 ("macro_reexport", Normal, Ungated),
546 ("macro_use", Normal, Ungated),
547 ("macro_export", Normal, Ungated),
548 ("plugin_registrar", Normal, Ungated),
550 ("cfg", Normal, Ungated),
551 ("cfg_attr", Normal, Ungated),
552 ("main", Normal, Ungated),
553 ("start", Normal, Ungated),
554 ("test", Normal, Ungated),
555 ("bench", Normal, Ungated),
556 ("simd", Normal, Ungated),
557 ("repr", Normal, Ungated),
558 ("path", Normal, Ungated),
559 ("abi", Normal, Ungated),
560 ("automatically_derived", Normal, Ungated),
561 ("no_mangle", Normal, Ungated),
562 ("no_link", Normal, Ungated),
563 ("derive", Normal, Ungated),
564 ("should_panic", Normal, Ungated),
565 ("ignore", Normal, Ungated),
566 ("no_implicit_prelude", Normal, Ungated),
567 ("reexport_test_harness_main", Normal, Ungated),
568 ("link_args", Normal, Gated(Stability::Unstable,
570 "the `link_args` attribute is experimental and not \
571 portable across platforms, it is recommended to \
572 use `#[link(name = \"foo\")] instead",
573 cfg_fn!(link_args))),
574 ("macro_escape", Normal, Ungated),
577 ("structural_match", Whitelisted, Gated(Stability::Unstable,
579 "the semantics of constant patterns is \
581 cfg_fn!(structural_match))),
583 ("plugin", CrateLevel, Gated(Stability::Unstable,
585 "compiler plugins are experimental \
589 ("no_std", CrateLevel, Ungated),
590 ("no_core", CrateLevel, Gated(Stability::Unstable,
592 "no_core is experimental",
594 ("lang", Normal, Gated(Stability::Unstable,
596 "language items are subject to change",
597 cfg_fn!(lang_items))),
598 ("linkage", Whitelisted, Gated(Stability::Unstable,
600 "the `linkage` attribute is experimental \
601 and not portable across platforms",
603 ("thread_local", Whitelisted, Gated(Stability::Unstable,
605 "`#[thread_local]` is an experimental feature, and does \
606 not currently handle destructors. There is no \
607 corresponding `#[task_local]` mapping to the task \
609 cfg_fn!(thread_local))),
611 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
613 "the `#[rustc_on_unimplemented]` attribute \
614 is an experimental feature",
615 cfg_fn!(on_unimplemented))),
616 ("global_allocator", Normal, Gated(Stability::Unstable,
618 "the `#[global_allocator]` attribute is \
619 an experimental feature",
620 cfg_fn!(global_allocator))),
621 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
622 "allocator_internals",
623 "the `#[default_lib_allocator]` \
624 attribute is an experimental feature",
625 cfg_fn!(allocator_internals))),
626 ("needs_allocator", Normal, Gated(Stability::Unstable,
627 "allocator_internals",
628 "the `#[needs_allocator]` \
629 attribute is an experimental \
631 cfg_fn!(allocator_internals))),
632 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
634 "the `#[panic_runtime]` attribute is \
635 an experimental feature",
636 cfg_fn!(panic_runtime))),
637 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
638 "needs_panic_runtime",
639 "the `#[needs_panic_runtime]` \
640 attribute is an experimental \
642 cfg_fn!(needs_panic_runtime))),
643 ("rustc_variance", Normal, Gated(Stability::Unstable,
645 "the `#[rustc_variance]` attribute \
646 is just used for rustc unit tests \
647 and will never be stable",
648 cfg_fn!(rustc_attrs))),
649 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
651 "the `#[rustc_error]` attribute \
652 is just used for rustc unit tests \
653 and will never be stable",
654 cfg_fn!(rustc_attrs))),
655 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
657 "the `#[rustc_if_this_changed]` attribute \
658 is just used for rustc unit tests \
659 and will never be stable",
660 cfg_fn!(rustc_attrs))),
661 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
663 "the `#[rustc_if_this_changed]` attribute \
664 is just used for rustc unit tests \
665 and will never be stable",
666 cfg_fn!(rustc_attrs))),
667 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
669 "the `#[rustc_dirty]` attribute \
670 is just used for rustc unit tests \
671 and will never be stable",
672 cfg_fn!(rustc_attrs))),
673 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
675 "the `#[rustc_clean]` attribute \
676 is just used for rustc unit tests \
677 and will never be stable",
678 cfg_fn!(rustc_attrs))),
679 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
681 "the `#[rustc_metadata_dirty]` attribute \
682 is just used for rustc unit tests \
683 and will never be stable",
684 cfg_fn!(rustc_attrs))),
685 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
687 "the `#[rustc_metadata_clean]` attribute \
688 is just used for rustc unit tests \
689 and will never be stable",
690 cfg_fn!(rustc_attrs))),
691 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
694 is just used for rustc unit tests \
695 and will never be stable",
696 cfg_fn!(rustc_attrs))),
697 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
700 is just used for rustc unit tests \
701 and will never be stable",
702 cfg_fn!(rustc_attrs))),
703 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
705 "internal rustc attributes will never be stable",
706 cfg_fn!(rustc_attrs))),
707 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
709 "internal rustc attributes will never be stable",
710 cfg_fn!(rustc_attrs))),
711 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
713 "the `#[rustc_mir]` attribute \
714 is just used for rustc unit tests \
715 and will never be stable",
716 cfg_fn!(rustc_attrs))),
717 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
719 "the `#[rustc_inherit_overflow_checks]` \
720 attribute is just used to control \
721 overflow checking behavior of several \
722 libcore functions that are inlined \
723 across crates and will never be stable",
724 cfg_fn!(rustc_attrs))),
725 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
727 "the `#[compiler_builtins]` attribute is used to \
728 identify the `compiler_builtins` crate which \
729 contains compiler-rt intrinsics and will never be \
731 cfg_fn!(compiler_builtins))),
732 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
734 "the `#[sanitizer_runtime]` attribute is used to \
735 identify crates that contain the runtime of a \
736 sanitizer and will never be stable",
737 cfg_fn!(sanitizer_runtime))),
738 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
740 "the `#[profiler_runtime]` attribute is used to \
741 identify the `profiler_builtins` crate which \
742 contains the profiler runtime and will never be \
744 cfg_fn!(profiler_runtime))),
746 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
747 "allow_internal_unstable",
748 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
749 cfg_fn!(allow_internal_unstable))),
751 ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
752 "allow_internal_unsafe",
753 EXPLAIN_ALLOW_INTERNAL_UNSAFE,
754 cfg_fn!(allow_internal_unsafe))),
756 ("fundamental", Whitelisted, Gated(Stability::Unstable,
758 "the `#[fundamental]` attribute \
759 is an experimental feature",
760 cfg_fn!(fundamental))),
762 ("proc_macro_derive", Normal, Ungated),
764 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
766 "internal implementation detail",
767 cfg_fn!(rustc_attrs))),
769 // FIXME: #14408 whitelist docs since rustdoc looks at them
770 ("doc", Whitelisted, Ungated),
772 // FIXME: #14406 these are processed in trans, which happens after the
774 ("cold", Whitelisted, Ungated),
775 ("naked", Whitelisted, Gated(Stability::Unstable,
777 "the `#[naked]` attribute \
778 is an experimental feature",
779 cfg_fn!(naked_functions))),
780 ("target_feature", Whitelisted, Gated(
781 Stability::Unstable, "target_feature",
782 "the `#[target_feature]` attribute is an experimental feature",
783 cfg_fn!(target_feature))),
784 ("export_name", Whitelisted, Ungated),
785 ("inline", Whitelisted, Ungated),
786 ("link", Whitelisted, Ungated),
787 ("link_name", Whitelisted, Ungated),
788 ("link_section", Whitelisted, Ungated),
789 ("no_builtins", Whitelisted, Ungated),
790 ("no_mangle", Whitelisted, Ungated),
791 ("no_debug", Whitelisted, Gated(
792 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
794 "the `#[no_debug]` attribute is an experimental feature",
796 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
797 "omit_gdb_pretty_printer_section",
798 "the `#[omit_gdb_pretty_printer_section]` \
799 attribute is just used for the Rust test \
801 cfg_fn!(omit_gdb_pretty_printer_section))),
802 ("unsafe_destructor_blind_to_params",
804 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
805 "dropck_parametricity",
806 "unsafe_destructor_blind_to_params has been replaced by \
807 may_dangle and will be removed in the future",
808 cfg_fn!(dropck_parametricity))),
811 Gated(Stability::Unstable,
813 "may_dangle has unstable semantics and may be removed in the future",
814 cfg_fn!(dropck_eyepatch))),
815 ("unwind", Whitelisted, Gated(Stability::Unstable,
817 "#[unwind] is experimental",
818 cfg_fn!(unwind_attributes))),
819 ("used", Whitelisted, Gated(
820 Stability::Unstable, "used",
821 "the `#[used]` attribute is an experimental feature",
825 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
827 "`#[prelude_import]` is for use by rustc only",
828 cfg_fn!(prelude_import))),
830 // FIXME: #14407 these are only looked at on-demand so we can't
831 // guarantee they'll have already been checked
832 ("rustc_deprecated", Whitelisted, Ungated),
833 ("must_use", Whitelisted, Ungated),
834 ("stable", Whitelisted, Ungated),
835 ("unstable", Whitelisted, Ungated),
836 ("deprecated", Normal, Ungated),
838 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
840 "unboxed_closures are still evolving",
841 cfg_fn!(unboxed_closures))),
843 ("windows_subsystem", Whitelisted, Ungated),
845 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
847 "attribute proc macros are currently unstable",
848 cfg_fn!(proc_macro))),
850 ("proc_macro", Normal, Gated(Stability::Unstable,
852 "function-like proc macros are currently unstable",
853 cfg_fn!(proc_macro))),
855 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
856 "rustc_derive_registrar",
857 "used internally by rustc",
858 cfg_fn!(rustc_attrs))),
860 ("allow_fail", Normal, Gated(Stability::Unstable,
862 "allow_fail attribute is currently unstable",
863 cfg_fn!(allow_fail))),
865 // Crate level attributes
866 ("crate_name", CrateLevel, Ungated),
867 ("crate_type", CrateLevel, Ungated),
868 ("crate_id", CrateLevel, Ungated),
869 ("feature", CrateLevel, Ungated),
870 ("no_start", CrateLevel, Ungated),
871 ("no_main", CrateLevel, Ungated),
872 ("no_builtins", CrateLevel, Ungated),
873 ("recursion_limit", CrateLevel, Ungated),
874 ("type_length_limit", CrateLevel, Ungated),
877 // cfg(...)'s that are feature gated
878 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
879 // (name in cfg, feature, function to check if the feature is enabled)
880 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
881 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
882 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
883 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
886 #[derive(Debug, Eq, PartialEq)]
887 pub struct GatedCfg {
893 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
894 let name = cfg.name().as_str();
896 .position(|info| info.0 == name)
905 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
906 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
907 if !has_feature(features) && !self.span.allows_unstable() {
908 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
909 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
915 features: &'a Features,
916 parse_sess: &'a ParseSess,
917 plugin_attributes: &'a [(String, AttributeType)],
920 macro_rules! gate_feature_fn {
921 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
922 let (cx, has_feature, span,
923 name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
924 let has_feature: bool = has_feature(&$cx.features);
925 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
926 if !has_feature && !span.allows_unstable() {
927 leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
933 macro_rules! gate_feature {
934 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
935 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
936 stringify!($feature), $explain, GateStrength::Hard)
938 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
939 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
940 stringify!($feature), $explain, $level)
944 impl<'a> Context<'a> {
945 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
946 debug!("check_attribute(attr = {:?})", attr);
947 let name = unwrap_or!(attr.name(), return).as_str();
948 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
950 if let Gated(_, name, desc, ref has_feature) = *gateage {
951 gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
953 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
957 for &(ref n, ref ty) in self.plugin_attributes {
958 if attr.path == &**n {
959 // Plugins can't gate attributes, so we don't check for it
960 // unlike the code above; we only use this loop to
961 // short-circuit to avoid the checks below
962 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
966 if name.starts_with("rustc_") {
967 gate_feature!(self, rustc_attrs, attr.span,
968 "unless otherwise specified, attributes \
969 with the prefix `rustc_` \
970 are reserved for internal compiler diagnostics");
971 } else if name.starts_with("derive_") {
972 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
973 } else if !attr::is_known(attr) {
974 // Only run the custom attribute lint during regular
975 // feature gate checking. Macro gating runs
976 // before the plugin attributes are registered
977 // so we skip this then
979 gate_feature!(self, custom_attribute, attr.span,
980 &format!("The attribute `{}` is currently \
981 unknown to the compiler and \
983 added to it in the future",
990 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
991 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
992 cx.check_attribute(attr, true);
995 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
996 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
999 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
1000 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
1002 // FIXME (#28244): enforce that active features have issue numbers
1003 // assert!(issue.is_some())
1006 // search in Accepted, Removed, or Stable Removed features
1007 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
1008 .find(|t| t.0 == feature);
1010 Some(&(_, _, issue)) => issue,
1011 None => panic!("Feature `{}` is not declared anywhere", feature),
1016 pub enum GateIssue {
1018 Library(Option<u32>)
1021 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1022 pub enum GateStrength {
1023 /// A hard error. (Most feature gates should use this.)
1025 /// Only a warning. (Use this only as backwards-compatibility demands.)
1029 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1031 feature_err(sess, feature, span, issue, explain).emit();
1034 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1035 explain: &str) -> DiagnosticBuilder<'a> {
1036 leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
1039 fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1040 explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
1041 let diag = &sess.span_diagnostic;
1043 let issue = match issue {
1044 GateIssue::Language => find_lang_feature_issue(feature),
1045 GateIssue::Library(lib) => lib,
1048 let explanation = if let Some(n) = issue {
1049 format!("{} (see issue #{})", explain, n)
1054 let mut err = match level {
1055 GateStrength::Hard => diag.struct_span_err(span, &explanation),
1056 GateStrength::Soft => diag.struct_span_warn(span, &explanation),
1059 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1060 if sess.unstable_features.is_nightly_build() {
1061 err.help(&format!("add #![feature({})] to the \
1062 crate attributes to enable",
1066 // If we're on stable and only emitting a "soft" warning, add a note to
1067 // clarify that the feature isn't "on" (rather than being on but
1069 if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
1070 err.help("a nightly build of the compiler is required to enable this feature");
1077 const EXPLAIN_BOX_SYNTAX: &'static str =
1078 "box expression syntax is experimental; you can call `Box::new` instead.";
1080 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1081 "attributes on non-item statements and expressions are experimental.";
1083 pub const EXPLAIN_ASM: &'static str =
1084 "inline assembly is not stable enough for use and is subject to change";
1086 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1087 "`global_asm!` is not stable enough for use and is subject to change";
1089 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1090 "`log_syntax!` is not stable enough for use and is subject to change";
1092 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1093 "`concat_idents` is not stable enough for use and is subject to change";
1095 pub const EXPLAIN_TRACE_MACROS: &'static str =
1096 "`trace_macros` is not stable enough for use and is subject to change";
1097 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1098 "allow_internal_unstable side-steps feature gating and stability checks";
1099 pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
1100 "allow_internal_unsafe side-steps the unsafe_code lint";
1102 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1103 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1105 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1106 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1107 Prefer using procedural macro custom derive.";
1109 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1110 "attributes of the form `#[derive_*]` are reserved for the compiler";
1112 pub const EXPLAIN_VIS_MATCHER: &'static str =
1113 ":vis fragment specifier is experimental and subject to change";
1115 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1116 "placement-in expression syntax is experimental and subject to change.";
1118 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1119 "Unsized tuple coercion is not stable enough for use and is subject to change";
1121 struct PostExpansionVisitor<'a> {
1122 context: &'a Context<'a>,
1125 macro_rules! gate_feature_post {
1126 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1127 let (cx, span) = ($cx, $span);
1128 if !span.allows_unstable() {
1129 gate_feature!(cx.context, $feature, span, $explain)
1132 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
1133 let (cx, span) = ($cx, $span);
1134 if !span.allows_unstable() {
1135 gate_feature!(cx.context, $feature, span, $explain, $level)
1140 impl<'a> PostExpansionVisitor<'a> {
1141 fn check_abi(&self, abi: Abi, span: Span) {
1143 Abi::RustIntrinsic => {
1144 gate_feature_post!(&self, intrinsics, span,
1145 "intrinsics are subject to change");
1147 Abi::PlatformIntrinsic => {
1148 gate_feature_post!(&self, platform_intrinsics, span,
1149 "platform intrinsics are experimental and possibly buggy");
1151 Abi::Vectorcall => {
1152 gate_feature_post!(&self, abi_vectorcall, span,
1153 "vectorcall is experimental and subject to change");
1156 gate_feature_post!(&self, abi_thiscall, span,
1157 "thiscall is experimental and subject to change");
1160 gate_feature_post!(&self, unboxed_closures, span,
1161 "rust-call ABI is subject to change");
1164 gate_feature_post!(&self, abi_sysv64, span,
1165 "sysv64 ABI is experimental and subject to change");
1168 gate_feature_post!(&self, abi_ptx, span,
1169 "PTX ABIs are experimental and subject to change");
1171 Abi::Unadjusted => {
1172 gate_feature_post!(&self, abi_unadjusted, span,
1173 "unadjusted ABI is an implementation detail and perma-unstable");
1175 Abi::Msp430Interrupt => {
1176 gate_feature_post!(&self, abi_msp430_interrupt, span,
1177 "msp430-interrupt ABI is experimental and subject to change");
1179 Abi::X86Interrupt => {
1180 gate_feature_post!(&self, abi_x86_interrupt, span,
1181 "x86-interrupt ABI is experimental and subject to change");
1196 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1197 use ast::MetaItemKind::*;
1198 use ast::NestedMetaItemKind::*;
1202 NameValue(ref lit) => !lit.node.is_str(),
1203 List(ref list) => list.iter().any(|li| {
1205 MetaItem(ref mi) => contains_novel_literal(mi),
1212 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1213 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1214 if !attr.span.allows_unstable() {
1215 // check for gated attributes
1216 self.context.check_attribute(attr, false);
1219 if attr.check_name("doc") {
1220 if let Some(content) = attr.meta_item_list() {
1221 if content.len() == 1 && content[0].check_name("cfg") {
1222 gate_feature_post!(&self, doc_cfg, attr.span,
1223 "#[doc(cfg(...))] is experimental"
1229 if self.context.features.proc_macro && attr::is_known(attr) {
1233 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1234 if contains_novel_literal(&meta) {
1235 gate_feature_post!(&self, attr_literals, attr.span,
1236 "non-string literals in attributes, or string \
1237 literals in top-level positions, are experimental");
1241 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1242 if !name.as_str().is_ascii() {
1243 gate_feature_post!(&self, non_ascii_idents, sp,
1244 "non-ascii idents are not fully supported.");
1248 fn visit_item(&mut self, i: &'a ast::Item) {
1250 ast::ItemKind::ExternCrate(_) => {
1251 if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
1252 gate_feature_post!(&self, macro_reexport, attr.span,
1253 "macros reexports are experimental \
1254 and possibly buggy");
1258 ast::ItemKind::ForeignMod(ref foreign_module) => {
1259 self.check_abi(foreign_module.abi, i.span);
1262 ast::ItemKind::Fn(..) => {
1263 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1264 gate_feature_post!(&self, plugin_registrar, i.span,
1265 "compiler plugins are experimental and possibly buggy");
1267 if attr::contains_name(&i.attrs[..], "start") {
1268 gate_feature_post!(&self, start, i.span,
1269 "a #[start] function is an experimental \
1270 feature whose signature may change \
1273 if attr::contains_name(&i.attrs[..], "main") {
1274 gate_feature_post!(&self, main, i.span,
1275 "declaration of a nonstandard #[main] \
1276 function may change over time, for now \
1277 a top-level `fn main()` is required");
1279 if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") {
1280 gate_feature_post!(&self, fn_must_use, attr.span,
1281 "`#[must_use]` on functions is experimental",
1282 GateStrength::Soft);
1286 ast::ItemKind::Struct(..) => {
1287 if let Some(attr) = attr::find_by_name(&i.attrs[..], "simd") {
1288 gate_feature_post!(&self, simd, attr.span,
1289 "SIMD types are experimental and possibly buggy");
1290 self.context.parse_sess.span_diagnostic.span_warn(attr.span,
1291 "the `#[simd]` attribute \
1292 is deprecated, use \
1293 `#[repr(simd)]` instead");
1295 if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
1296 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1297 if item.check_name("simd") {
1298 gate_feature_post!(&self, repr_simd, attr.span,
1299 "SIMD types are experimental and possibly buggy");
1301 if item.check_name("align") {
1302 gate_feature_post!(&self, repr_align, attr.span,
1303 "the struct `#[repr(align(u16))]` attribute \
1310 ast::ItemKind::DefaultImpl(..) => {
1311 gate_feature_post!(&self, optin_builtin_traits,
1313 "default trait implementations are experimental \
1314 and possibly buggy");
1317 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
1318 if polarity == ast::ImplPolarity::Negative {
1319 gate_feature_post!(&self, optin_builtin_traits,
1321 "negative trait bounds are not yet fully implemented; \
1322 use marker types for now");
1325 if let ast::Defaultness::Default = defaultness {
1326 gate_feature_post!(&self, specialization,
1328 "specialization is unstable");
1331 for impl_item in impl_items {
1332 if let ast::ImplItemKind::Method(..) = impl_item.node {
1333 if let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") {
1334 gate_feature_post!(&self, fn_must_use, attr.span,
1335 "`#[must_use]` on methods is experimental",
1336 GateStrength::Soft);
1342 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1343 let msg = "`macro` is experimental";
1344 gate_feature_post!(&self, decl_macro, i.span, msg);
1350 visit::walk_item(self, i);
1353 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1354 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1355 Some(val) => val.as_str().starts_with("llvm."),
1359 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1360 "linking to LLVM intrinsics is experimental");
1363 visit::walk_foreign_item(self, i)
1366 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1368 ast::TyKind::BareFn(ref bare_fn_ty) => {
1369 self.check_abi(bare_fn_ty.abi, ty.span);
1371 ast::TyKind::ImplTrait(..) => {
1372 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1373 "`impl Trait` is experimental");
1375 ast::TyKind::Never => {
1376 gate_feature_post!(&self, never_type, ty.span,
1377 "The `!` type is experimental");
1381 visit::walk_ty(self, ty)
1384 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1385 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1386 if output_ty.node != ast::TyKind::Never {
1387 self.visit_ty(output_ty)
1392 fn visit_expr(&mut self, e: &'a ast::Expr) {
1394 ast::ExprKind::Box(_) => {
1395 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1397 ast::ExprKind::Type(..) => {
1398 gate_feature_post!(&self, type_ascription, e.span,
1399 "type ascription is experimental");
1401 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1402 gate_feature_post!(&self, inclusive_range_syntax,
1404 "inclusive range syntax is experimental");
1406 ast::ExprKind::InPlace(..) => {
1407 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1409 ast::ExprKind::Lit(ref lit) => {
1410 if let ast::LitKind::Int(_, ref ty) = lit.node {
1412 ast::LitIntType::Signed(ast::IntTy::I128) |
1413 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1414 gate_feature_post!(&self, i128_type, e.span,
1415 "128-bit integers are not stable");
1421 ast::ExprKind::Catch(_) => {
1422 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1426 visit::walk_expr(self, e);
1429 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1430 match pattern.node {
1431 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1432 gate_feature_post!(&self, advanced_slice_patterns,
1434 "multiple-element slice matches anywhere \
1435 but at the end of a slice (e.g. \
1436 `[0, ..xs, 0]`) are experimental")
1438 PatKind::Slice(..) => {
1439 gate_feature_post!(&self, slice_patterns,
1441 "slice pattern syntax is experimental");
1443 PatKind::Box(..) => {
1444 gate_feature_post!(&self, box_patterns,
1446 "box pattern syntax is experimental");
1448 PatKind::Range(_, _, RangeEnd::Excluded) => {
1449 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1450 "exclusive range pattern syntax is experimental");
1454 visit::walk_pat(self, pattern)
1457 fn visit_fn(&mut self,
1458 fn_kind: FnKind<'a>,
1459 fn_decl: &'a ast::FnDecl,
1462 // check for const fn declarations
1463 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1465 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1467 // stability of const fn methods are covered in
1468 // visit_trait_item and visit_impl_item below; this is
1469 // because default methods don't pass through this
1473 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1474 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1475 self.check_abi(abi, span);
1479 visit::walk_fn(self, fn_kind, fn_decl, span);
1482 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1484 ast::TraitItemKind::Method(ref sig, ref block) => {
1485 if block.is_none() {
1486 self.check_abi(sig.abi, ti.span);
1488 if sig.constness.node == ast::Constness::Const {
1489 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1492 ast::TraitItemKind::Type(_, Some(_)) => {
1493 gate_feature_post!(&self, associated_type_defaults, ti.span,
1494 "associated type defaults are unstable");
1498 visit::walk_trait_item(self, ti);
1501 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1502 if ii.defaultness == ast::Defaultness::Default {
1503 gate_feature_post!(&self, specialization,
1505 "specialization is unstable");
1509 ast::ImplItemKind::Method(ref sig, _) => {
1510 if sig.constness.node == ast::Constness::Const {
1511 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1516 visit::walk_impl_item(self, ii);
1519 fn visit_generics(&mut self, g: &'a ast::Generics) {
1520 for t in &g.ty_params {
1521 if !t.attrs.is_empty() {
1522 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1523 "attributes on type parameter bindings are experimental");
1526 visit::walk_generics(self, g)
1529 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1530 if !lifetime_def.attrs.is_empty() {
1531 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1532 "attributes on lifetime bindings are experimental");
1534 visit::walk_lifetime_def(self, lifetime_def)
1538 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1539 let mut features = Features::new();
1541 let mut feature_checker = MutexFeatureChecker::default();
1543 for attr in krate_attrs {
1544 if !attr.check_name("feature") {
1548 match attr.meta_item_list() {
1550 span_err!(span_handler, attr.span, E0555,
1551 "malformed feature attribute, expected #![feature(...)]");
1555 let name = if let Some(word) = mi.word() {
1558 span_err!(span_handler, mi.span, E0556,
1559 "malformed feature, expected just one word");
1563 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1564 .find(|& &(n, _, _, _)| name == n) {
1565 set(&mut features, mi.span);
1566 feature_checker.collect(&features, mi.span);
1568 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1569 .find(|& &(n, _, _)| name == n)
1570 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1571 .find(|& &(n, _, _)| name == n)) {
1572 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1574 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1575 .find(|& &(n, _, _)| name == n) {
1576 features.declared_stable_lang_features.push((name, mi.span));
1578 features.declared_lib_features.push((name, mi.span));
1585 feature_checker.check(span_handler);
1590 // A collector for mutually-exclusive features and their flag spans
1592 struct MutexFeatureChecker {
1593 proc_macro: Option<Span>,
1594 custom_attribute: Option<Span>,
1597 impl MutexFeatureChecker {
1598 // If this method turns out to be a hotspot due to branching,
1599 // the branching can be eliminated by modifying `set!()` to set these spans
1600 // only for the features that need to be checked for mutual exclusion.
1601 fn collect(&mut self, features: &Features, span: Span) {
1602 if features.proc_macro {
1603 // If self.proc_macro is None, set to Some(span)
1604 self.proc_macro = self.proc_macro.or(Some(span));
1607 if features.custom_attribute {
1608 self.custom_attribute = self.custom_attribute.or(Some(span));
1612 fn check(self, handler: &Handler) {
1613 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1614 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1615 `#![feature(custom_attribute)] at the same time")
1616 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1624 pub fn check_crate(krate: &ast::Crate,
1626 features: &Features,
1627 plugin_attributes: &[(String, AttributeType)],
1628 unstable: UnstableFeatures) {
1629 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1635 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1638 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1639 pub enum UnstableFeatures {
1640 /// Hard errors for unstable features are active, as on
1641 /// beta/stable channels.
1643 /// Allow features to be activated, as on nightly.
1645 /// Errors are bypassed for bootstrapping. This is required any time
1646 /// during the build that feature-related lints are set to warn or above
1647 /// because the build turns on warnings-as-errors and uses lots of unstable
1648 /// features. As a result, this is always required for building Rust itself.
1652 impl UnstableFeatures {
1653 pub fn from_environment() -> UnstableFeatures {
1654 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1655 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1656 // Whether we should enable unstable features for bootstrapping
1657 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1658 match (disable_unstable_features, bootstrap) {
1659 (_, true) => UnstableFeatures::Cheat,
1660 (true, _) => UnstableFeatures::Disallow,
1661 (false, _) => UnstableFeatures::Allow
1665 pub fn is_nightly_build(&self) -> bool {
1667 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1673 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1674 unstable: UnstableFeatures) {
1675 let allow_features = match unstable {
1676 UnstableFeatures::Allow => true,
1677 UnstableFeatures::Disallow => false,
1678 UnstableFeatures::Cheat => true
1680 if !allow_features {
1681 for attr in &krate.attrs {
1682 if attr.check_name("feature") {
1683 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1684 span_err!(span_handler, attr.span, E0554,
1685 "#![feature] may not be used on the {} release channel",