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 attr::contains_name(&i.attrs[..], "macro_reexport") {
1252 gate_feature_post!(&self, macro_reexport, i.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 attr::contains_name(&i.attrs[..], "must_use") {
1280 gate_feature_post!(&self, fn_must_use, i.span,
1281 "`#[must_use]` on functions is experimental",
1282 GateStrength::Soft);
1286 ast::ItemKind::Struct(..) => {
1287 if attr::contains_name(&i.attrs[..], "simd") {
1288 gate_feature_post!(&self, simd, i.span,
1289 "SIMD types are experimental and possibly buggy");
1290 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1291 "the `#[simd]` attribute \
1292 is deprecated, use \
1293 `#[repr(simd)]` instead");
1295 for attr in &i.attrs {
1296 if attr.path == "repr" {
1297 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1298 if item.check_name("simd") {
1299 gate_feature_post!(&self, repr_simd, i.span,
1300 "SIMD types are experimental \
1301 and possibly buggy");
1304 if item.check_name("align") {
1305 gate_feature_post!(&self, repr_align, i.span,
1306 "the struct `#[repr(align(u16))]` attribute \
1314 ast::ItemKind::DefaultImpl(..) => {
1315 gate_feature_post!(&self, optin_builtin_traits,
1317 "default trait implementations are experimental \
1318 and possibly buggy");
1321 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
1322 if polarity == ast::ImplPolarity::Negative {
1323 gate_feature_post!(&self, optin_builtin_traits,
1325 "negative trait bounds are not yet fully implemented; \
1326 use marker types for now");
1329 if let ast::Defaultness::Default = defaultness {
1330 gate_feature_post!(&self, specialization,
1332 "specialization is unstable");
1335 for impl_item in impl_items {
1336 if let ast::ImplItemKind::Method(..) = impl_item.node {
1337 if attr::contains_name(&impl_item.attrs[..], "must_use") {
1338 gate_feature_post!(&self, fn_must_use, impl_item.span,
1339 "`#[must_use]` on methods is experimental",
1340 GateStrength::Soft);
1346 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1347 let msg = "`macro` is experimental";
1348 gate_feature_post!(&self, decl_macro, i.span, msg);
1354 visit::walk_item(self, i);
1357 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1358 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1359 Some(val) => val.as_str().starts_with("llvm."),
1363 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1364 "linking to LLVM intrinsics is experimental");
1367 visit::walk_foreign_item(self, i)
1370 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1372 ast::TyKind::BareFn(ref bare_fn_ty) => {
1373 self.check_abi(bare_fn_ty.abi, ty.span);
1375 ast::TyKind::ImplTrait(..) => {
1376 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1377 "`impl Trait` is experimental");
1379 ast::TyKind::Never => {
1380 gate_feature_post!(&self, never_type, ty.span,
1381 "The `!` type is experimental");
1385 visit::walk_ty(self, ty)
1388 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1389 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1390 if output_ty.node != ast::TyKind::Never {
1391 self.visit_ty(output_ty)
1396 fn visit_expr(&mut self, e: &'a ast::Expr) {
1398 ast::ExprKind::Box(_) => {
1399 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1401 ast::ExprKind::Type(..) => {
1402 gate_feature_post!(&self, type_ascription, e.span,
1403 "type ascription is experimental");
1405 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1406 gate_feature_post!(&self, inclusive_range_syntax,
1408 "inclusive range syntax is experimental");
1410 ast::ExprKind::InPlace(..) => {
1411 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1413 ast::ExprKind::Lit(ref lit) => {
1414 if let ast::LitKind::Int(_, ref ty) = lit.node {
1416 ast::LitIntType::Signed(ast::IntTy::I128) |
1417 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1418 gate_feature_post!(&self, i128_type, e.span,
1419 "128-bit integers are not stable");
1425 ast::ExprKind::Catch(_) => {
1426 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1430 visit::walk_expr(self, e);
1433 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1434 match pattern.node {
1435 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1436 gate_feature_post!(&self, advanced_slice_patterns,
1438 "multiple-element slice matches anywhere \
1439 but at the end of a slice (e.g. \
1440 `[0, ..xs, 0]`) are experimental")
1442 PatKind::Slice(..) => {
1443 gate_feature_post!(&self, slice_patterns,
1445 "slice pattern syntax is experimental");
1447 PatKind::Box(..) => {
1448 gate_feature_post!(&self, box_patterns,
1450 "box pattern syntax is experimental");
1452 PatKind::Range(_, _, RangeEnd::Excluded) => {
1453 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1454 "exclusive range pattern syntax is experimental");
1458 visit::walk_pat(self, pattern)
1461 fn visit_fn(&mut self,
1462 fn_kind: FnKind<'a>,
1463 fn_decl: &'a ast::FnDecl,
1466 // check for const fn declarations
1467 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1469 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1471 // stability of const fn methods are covered in
1472 // visit_trait_item and visit_impl_item below; this is
1473 // because default methods don't pass through this
1477 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1478 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1479 self.check_abi(abi, span);
1483 visit::walk_fn(self, fn_kind, fn_decl, span);
1486 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1488 ast::TraitItemKind::Method(ref sig, ref block) => {
1489 if block.is_none() {
1490 self.check_abi(sig.abi, ti.span);
1492 if sig.constness.node == ast::Constness::Const {
1493 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1496 ast::TraitItemKind::Type(_, Some(_)) => {
1497 gate_feature_post!(&self, associated_type_defaults, ti.span,
1498 "associated type defaults are unstable");
1502 visit::walk_trait_item(self, ti);
1505 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1506 if ii.defaultness == ast::Defaultness::Default {
1507 gate_feature_post!(&self, specialization,
1509 "specialization is unstable");
1513 ast::ImplItemKind::Method(ref sig, _) => {
1514 if sig.constness.node == ast::Constness::Const {
1515 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1520 visit::walk_impl_item(self, ii);
1523 fn visit_generics(&mut self, g: &'a ast::Generics) {
1524 for t in &g.ty_params {
1525 if !t.attrs.is_empty() {
1526 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1527 "attributes on type parameter bindings are experimental");
1530 visit::walk_generics(self, g)
1533 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1534 if !lifetime_def.attrs.is_empty() {
1535 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1536 "attributes on lifetime bindings are experimental");
1538 visit::walk_lifetime_def(self, lifetime_def)
1542 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1543 let mut features = Features::new();
1545 let mut feature_checker = MutexFeatureChecker::default();
1547 for attr in krate_attrs {
1548 if !attr.check_name("feature") {
1552 match attr.meta_item_list() {
1554 span_err!(span_handler, attr.span, E0555,
1555 "malformed feature attribute, expected #![feature(...)]");
1559 let name = if let Some(word) = mi.word() {
1562 span_err!(span_handler, mi.span, E0556,
1563 "malformed feature, expected just one word");
1567 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1568 .find(|& &(n, _, _, _)| name == n) {
1569 set(&mut features, mi.span);
1570 feature_checker.collect(&features, mi.span);
1572 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1573 .find(|& &(n, _, _)| name == n)
1574 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1575 .find(|& &(n, _, _)| name == n)) {
1576 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1578 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1579 .find(|& &(n, _, _)| name == n) {
1580 features.declared_stable_lang_features.push((name, mi.span));
1582 features.declared_lib_features.push((name, mi.span));
1589 feature_checker.check(span_handler);
1594 // A collector for mutually-exclusive features and their flag spans
1596 struct MutexFeatureChecker {
1597 proc_macro: Option<Span>,
1598 custom_attribute: Option<Span>,
1601 impl MutexFeatureChecker {
1602 // If this method turns out to be a hotspot due to branching,
1603 // the branching can be eliminated by modifying `set!()` to set these spans
1604 // only for the features that need to be checked for mutual exclusion.
1605 fn collect(&mut self, features: &Features, span: Span) {
1606 if features.proc_macro {
1607 // If self.proc_macro is None, set to Some(span)
1608 self.proc_macro = self.proc_macro.or(Some(span));
1611 if features.custom_attribute {
1612 self.custom_attribute = self.custom_attribute.or(Some(span));
1616 fn check(self, handler: &Handler) {
1617 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1618 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1619 `#![feature(custom_attribute)] at the same time")
1620 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1628 pub fn check_crate(krate: &ast::Crate,
1630 features: &Features,
1631 plugin_attributes: &[(String, AttributeType)],
1632 unstable: UnstableFeatures) {
1633 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1639 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1642 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1643 pub enum UnstableFeatures {
1644 /// Hard errors for unstable features are active, as on
1645 /// beta/stable channels.
1647 /// Allow features to be activated, as on nightly.
1649 /// Errors are bypassed for bootstrapping. This is required any time
1650 /// during the build that feature-related lints are set to warn or above
1651 /// because the build turns on warnings-as-errors and uses lots of unstable
1652 /// features. As a result, this is always required for building Rust itself.
1656 impl UnstableFeatures {
1657 pub fn from_environment() -> UnstableFeatures {
1658 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1659 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1660 // Whether we should enable unstable features for bootstrapping
1661 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1662 match (disable_unstable_features, bootstrap) {
1663 (_, true) => UnstableFeatures::Cheat,
1664 (true, _) => UnstableFeatures::Disallow,
1665 (false, _) => UnstableFeatures::Allow
1669 pub fn is_nightly_build(&self) -> bool {
1671 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1677 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1678 unstable: UnstableFeatures) {
1679 let allow_features = match unstable {
1680 UnstableFeatures::Allow => true,
1681 UnstableFeatures::Disallow => false,
1682 UnstableFeatures::Cheat => true
1684 if !allow_features {
1685 for attr in &krate.attrs {
1686 if attr.check_name("feature") {
1687 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1688 span_err!(span_handler, attr.span, E0554,
1689 "#![feature] may not be used on the {} release channel",