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)),
370 (active, generators, "1.21.0", None),
373 // global allocators and their internals
374 (active, global_allocator, "1.20.0", None),
375 (active, allocator_internals, "1.20.0", None),
378 (active, doc_cfg, "1.21.0", Some(43781)),
380 // allow `#[must_use]` on functions (RFC 1940)
381 (active, fn_must_use, "1.21.0", Some(43302)),
385 (removed, import_shadowing, "1.0.0", None),
386 (removed, managed_boxes, "1.0.0", None),
387 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
388 (removed, negate_unsigned, "1.0.0", Some(29645)),
389 (removed, reflect, "1.0.0", Some(27749)),
390 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
391 (removed, opt_out_copy, "1.0.0", None),
392 (removed, quad_precision_float, "1.0.0", None),
393 (removed, struct_inherit, "1.0.0", None),
394 (removed, test_removed_feature, "1.0.0", None),
395 (removed, visible_private_types, "1.0.0", None),
396 (removed, unsafe_no_drop_flag, "1.0.0", None),
397 // Allows using items which are missing stability attributes
399 (removed, unmarked_api, "1.0.0", None),
400 (removed, pushpop_unsafe, "1.2.0", None),
401 (removed, allocator, "1.0.0", None),
405 (stable_removed, no_stack_check, "1.0.0", None),
409 (accepted, associated_types, "1.0.0", None),
410 // allow overloading augmented assignment operations like `a += b`
411 (accepted, augmented_assignments, "1.8.0", Some(28235)),
412 // allow empty structs and enum variants with braces
413 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
414 (accepted, default_type_params, "1.0.0", None),
415 (accepted, globs, "1.0.0", None),
416 (accepted, if_let, "1.0.0", None),
417 // A temporary feature gate used to enable parser extensions needed
418 // to bootstrap fix for #5723.
419 (accepted, issue_5723_bootstrap, "1.0.0", None),
420 (accepted, macro_rules, "1.0.0", None),
421 // Allows using #![no_std]
422 (accepted, no_std, "1.6.0", None),
423 (accepted, slicing_syntax, "1.0.0", None),
424 (accepted, struct_variant, "1.0.0", None),
425 // These are used to test this portion of the compiler, they don't actually
427 (accepted, test_accepted_feature, "1.0.0", None),
428 (accepted, tuple_indexing, "1.0.0", None),
429 // Allows macros to appear in the type position.
430 (accepted, type_macros, "1.13.0", Some(27245)),
431 (accepted, while_let, "1.0.0", None),
432 // Allows `#[deprecated]` attribute
433 (accepted, deprecated, "1.9.0", Some(29935)),
435 (accepted, question_mark, "1.13.0", Some(31436)),
436 // Allows `..` in tuple (struct) patterns
437 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
438 (accepted, item_like_imports, "1.15.0", Some(35120)),
439 // Allows using `Self` and associated types in struct expressions and patterns.
440 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
441 // elide `'static` lifetimes in `static`s and `const`s
442 (accepted, static_in_const, "1.17.0", Some(35897)),
443 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
444 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
445 // Allows the definition recursive static items.
446 (accepted, static_recursion, "1.17.0", Some(29719)),
447 // pub(restricted) visibilities (RFC 1422)
448 (accepted, pub_restricted, "1.18.0", Some(32409)),
449 // The #![windows_subsystem] attribute
450 (accepted, windows_subsystem, "1.18.0", Some(37499)),
451 // Allows `break {expr}` with a value inside `loop`s.
452 (accepted, loop_break_value, "1.19.0", Some(37339)),
453 // Permits numeric fields in struct expressions and patterns.
454 (accepted, relaxed_adts, "1.19.0", Some(35626)),
455 // Coerces non capturing closures to function pointers
456 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
457 // Allows attributes on struct literal fields.
458 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
459 // Allows the definition of associated constants in `trait` or `impl`
461 (accepted, associated_consts, "1.20.0", Some(29646)),
462 // Usage of the `compile_error!` macro
463 (accepted, compile_error, "1.20.0", Some(40872)),
464 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
465 (accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
468 // If you change this, please modify src/doc/unstable-book as well. You must
469 // move that documentation into the relevant place in the other docs, and
470 // remove the chapter on the flag.
472 #[derive(PartialEq, Copy, Clone, Debug)]
473 pub enum AttributeType {
474 /// Normal, builtin attribute that is consumed
475 /// by the compiler before the unused_attribute check
478 /// Builtin attribute that may not be consumed by the compiler
479 /// before the unused_attribute check. These attributes
480 /// will be ignored by the unused_attribute lint
483 /// Builtin attribute that is only allowed at the crate level
487 pub enum AttributeGate {
488 /// Is gated by a given feature gate, reason
489 /// and function to check if enabled
490 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
492 /// Ungated attribute, can be used on all release channels
497 fn is_deprecated(&self) -> bool {
499 Gated(Stability::Deprecated(_), ..) => true,
505 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
508 // Argument is tracking issue link.
509 Deprecated(&'static str),
513 impl ::std::fmt::Debug for AttributeGate {
514 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
516 Gated(ref stab, name, expl, _) =>
517 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
518 Ungated => write!(fmt, "Ungated")
523 macro_rules! cfg_fn {
524 ($field: ident) => {{
525 fn f(features: &Features) -> bool {
528 f as fn(&Features) -> bool
532 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
533 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
536 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
537 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
540 // Attributes that have a special meaning to rustc or rustdoc
541 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
544 ("warn", Normal, Ungated),
545 ("allow", Normal, Ungated),
546 ("forbid", Normal, Ungated),
547 ("deny", Normal, Ungated),
549 ("macro_reexport", Normal, Ungated),
550 ("macro_use", Normal, Ungated),
551 ("macro_export", Normal, Ungated),
552 ("plugin_registrar", Normal, Ungated),
554 ("cfg", Normal, Ungated),
555 ("cfg_attr", Normal, Ungated),
556 ("main", Normal, Ungated),
557 ("start", Normal, Ungated),
558 ("test", Normal, Ungated),
559 ("bench", Normal, Ungated),
560 ("simd", Normal, Ungated),
561 ("repr", Normal, Ungated),
562 ("path", Normal, Ungated),
563 ("abi", Normal, Ungated),
564 ("automatically_derived", Normal, Ungated),
565 ("no_mangle", Normal, Ungated),
566 ("no_link", Normal, Ungated),
567 ("derive", Normal, Ungated),
568 ("should_panic", Normal, Ungated),
569 ("ignore", Normal, Ungated),
570 ("no_implicit_prelude", Normal, Ungated),
571 ("reexport_test_harness_main", Normal, Ungated),
572 ("link_args", Normal, Gated(Stability::Unstable,
574 "the `link_args` attribute is experimental and not \
575 portable across platforms, it is recommended to \
576 use `#[link(name = \"foo\")] instead",
577 cfg_fn!(link_args))),
578 ("macro_escape", Normal, Ungated),
581 ("structural_match", Whitelisted, Gated(Stability::Unstable,
583 "the semantics of constant patterns is \
585 cfg_fn!(structural_match))),
587 ("plugin", CrateLevel, Gated(Stability::Unstable,
589 "compiler plugins are experimental \
593 ("no_std", CrateLevel, Ungated),
594 ("no_core", CrateLevel, Gated(Stability::Unstable,
596 "no_core is experimental",
598 ("lang", Normal, Gated(Stability::Unstable,
600 "language items are subject to change",
601 cfg_fn!(lang_items))),
602 ("linkage", Whitelisted, Gated(Stability::Unstable,
604 "the `linkage` attribute is experimental \
605 and not portable across platforms",
607 ("thread_local", Whitelisted, Gated(Stability::Unstable,
609 "`#[thread_local]` is an experimental feature, and does \
610 not currently handle destructors. There is no \
611 corresponding `#[task_local]` mapping to the task \
613 cfg_fn!(thread_local))),
615 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
617 "the `#[rustc_on_unimplemented]` attribute \
618 is an experimental feature",
619 cfg_fn!(on_unimplemented))),
620 ("global_allocator", Normal, Gated(Stability::Unstable,
622 "the `#[global_allocator]` attribute is \
623 an experimental feature",
624 cfg_fn!(global_allocator))),
625 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
626 "allocator_internals",
627 "the `#[default_lib_allocator]` \
628 attribute is an experimental feature",
629 cfg_fn!(allocator_internals))),
630 ("needs_allocator", Normal, Gated(Stability::Unstable,
631 "allocator_internals",
632 "the `#[needs_allocator]` \
633 attribute is an experimental \
635 cfg_fn!(allocator_internals))),
636 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
638 "the `#[panic_runtime]` attribute is \
639 an experimental feature",
640 cfg_fn!(panic_runtime))),
641 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
642 "needs_panic_runtime",
643 "the `#[needs_panic_runtime]` \
644 attribute is an experimental \
646 cfg_fn!(needs_panic_runtime))),
647 ("rustc_variance", Normal, Gated(Stability::Unstable,
649 "the `#[rustc_variance]` attribute \
650 is just used for rustc unit tests \
651 and will never be stable",
652 cfg_fn!(rustc_attrs))),
653 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
655 "the `#[rustc_error]` attribute \
656 is just used for rustc unit tests \
657 and will never be stable",
658 cfg_fn!(rustc_attrs))),
659 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
661 "the `#[rustc_if_this_changed]` attribute \
662 is just used for rustc unit tests \
663 and will never be stable",
664 cfg_fn!(rustc_attrs))),
665 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
667 "the `#[rustc_if_this_changed]` attribute \
668 is just used for rustc unit tests \
669 and will never be stable",
670 cfg_fn!(rustc_attrs))),
671 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
673 "the `#[rustc_dirty]` attribute \
674 is just used for rustc unit tests \
675 and will never be stable",
676 cfg_fn!(rustc_attrs))),
677 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
679 "the `#[rustc_clean]` attribute \
680 is just used for rustc unit tests \
681 and will never be stable",
682 cfg_fn!(rustc_attrs))),
683 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
685 "the `#[rustc_metadata_dirty]` attribute \
686 is just used for rustc unit tests \
687 and will never be stable",
688 cfg_fn!(rustc_attrs))),
689 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
691 "the `#[rustc_metadata_clean]` attribute \
692 is just used for rustc unit tests \
693 and will never be stable",
694 cfg_fn!(rustc_attrs))),
695 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
698 is just used for rustc unit tests \
699 and will never be stable",
700 cfg_fn!(rustc_attrs))),
701 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
704 is just used for rustc unit tests \
705 and will never be stable",
706 cfg_fn!(rustc_attrs))),
707 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
709 "internal rustc attributes will never be stable",
710 cfg_fn!(rustc_attrs))),
711 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
713 "internal rustc attributes will never be stable",
714 cfg_fn!(rustc_attrs))),
715 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
717 "the `#[rustc_mir]` attribute \
718 is just used for rustc unit tests \
719 and will never be stable",
720 cfg_fn!(rustc_attrs))),
721 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
723 "the `#[rustc_inherit_overflow_checks]` \
724 attribute is just used to control \
725 overflow checking behavior of several \
726 libcore functions that are inlined \
727 across crates and will never be stable",
728 cfg_fn!(rustc_attrs))),
729 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
731 "the `#[compiler_builtins]` attribute is used to \
732 identify the `compiler_builtins` crate which \
733 contains compiler-rt intrinsics and will never be \
735 cfg_fn!(compiler_builtins))),
736 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
738 "the `#[sanitizer_runtime]` attribute is used to \
739 identify crates that contain the runtime of a \
740 sanitizer and will never be stable",
741 cfg_fn!(sanitizer_runtime))),
742 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
744 "the `#[profiler_runtime]` attribute is used to \
745 identify the `profiler_builtins` crate which \
746 contains the profiler runtime and will never be \
748 cfg_fn!(profiler_runtime))),
750 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
751 "allow_internal_unstable",
752 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
753 cfg_fn!(allow_internal_unstable))),
755 ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
756 "allow_internal_unsafe",
757 EXPLAIN_ALLOW_INTERNAL_UNSAFE,
758 cfg_fn!(allow_internal_unsafe))),
760 ("fundamental", Whitelisted, Gated(Stability::Unstable,
762 "the `#[fundamental]` attribute \
763 is an experimental feature",
764 cfg_fn!(fundamental))),
766 ("proc_macro_derive", Normal, Ungated),
768 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
770 "internal implementation detail",
771 cfg_fn!(rustc_attrs))),
773 // FIXME: #14408 whitelist docs since rustdoc looks at them
774 ("doc", Whitelisted, Ungated),
776 // FIXME: #14406 these are processed in trans, which happens after the
778 ("cold", Whitelisted, Ungated),
779 ("naked", Whitelisted, Gated(Stability::Unstable,
781 "the `#[naked]` attribute \
782 is an experimental feature",
783 cfg_fn!(naked_functions))),
784 ("target_feature", Whitelisted, Gated(
785 Stability::Unstable, "target_feature",
786 "the `#[target_feature]` attribute is an experimental feature",
787 cfg_fn!(target_feature))),
788 ("export_name", Whitelisted, Ungated),
789 ("inline", Whitelisted, Ungated),
790 ("link", Whitelisted, Ungated),
791 ("link_name", Whitelisted, Ungated),
792 ("link_section", Whitelisted, Ungated),
793 ("no_builtins", Whitelisted, Ungated),
794 ("no_mangle", Whitelisted, Ungated),
795 ("no_debug", Whitelisted, Gated(
796 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
798 "the `#[no_debug]` attribute is an experimental feature",
800 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
801 "omit_gdb_pretty_printer_section",
802 "the `#[omit_gdb_pretty_printer_section]` \
803 attribute is just used for the Rust test \
805 cfg_fn!(omit_gdb_pretty_printer_section))),
806 ("unsafe_destructor_blind_to_params",
808 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
809 "dropck_parametricity",
810 "unsafe_destructor_blind_to_params has been replaced by \
811 may_dangle and will be removed in the future",
812 cfg_fn!(dropck_parametricity))),
815 Gated(Stability::Unstable,
817 "may_dangle has unstable semantics and may be removed in the future",
818 cfg_fn!(dropck_eyepatch))),
819 ("unwind", Whitelisted, Gated(Stability::Unstable,
821 "#[unwind] is experimental",
822 cfg_fn!(unwind_attributes))),
823 ("used", Whitelisted, Gated(
824 Stability::Unstable, "used",
825 "the `#[used]` attribute is an experimental feature",
829 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
831 "`#[prelude_import]` is for use by rustc only",
832 cfg_fn!(prelude_import))),
834 // FIXME: #14407 these are only looked at on-demand so we can't
835 // guarantee they'll have already been checked
836 ("rustc_deprecated", Whitelisted, Ungated),
837 ("must_use", Whitelisted, Ungated),
838 ("stable", Whitelisted, Ungated),
839 ("unstable", Whitelisted, Ungated),
840 ("deprecated", Normal, Ungated),
842 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
844 "unboxed_closures are still evolving",
845 cfg_fn!(unboxed_closures))),
847 ("windows_subsystem", Whitelisted, Ungated),
849 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
851 "attribute proc macros are currently unstable",
852 cfg_fn!(proc_macro))),
854 ("proc_macro", Normal, Gated(Stability::Unstable,
856 "function-like proc macros are currently unstable",
857 cfg_fn!(proc_macro))),
859 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
860 "rustc_derive_registrar",
861 "used internally by rustc",
862 cfg_fn!(rustc_attrs))),
864 ("allow_fail", Normal, Gated(Stability::Unstable,
866 "allow_fail attribute is currently unstable",
867 cfg_fn!(allow_fail))),
869 // Crate level attributes
870 ("crate_name", CrateLevel, Ungated),
871 ("crate_type", CrateLevel, Ungated),
872 ("crate_id", CrateLevel, Ungated),
873 ("feature", CrateLevel, Ungated),
874 ("no_start", CrateLevel, Ungated),
875 ("no_main", CrateLevel, Ungated),
876 ("no_builtins", CrateLevel, Ungated),
877 ("recursion_limit", CrateLevel, Ungated),
878 ("type_length_limit", CrateLevel, Ungated),
881 // cfg(...)'s that are feature gated
882 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
883 // (name in cfg, feature, function to check if the feature is enabled)
884 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
885 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
886 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
887 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
890 #[derive(Debug, Eq, PartialEq)]
891 pub struct GatedCfg {
897 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
898 let name = cfg.name().as_str();
900 .position(|info| info.0 == name)
909 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
910 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
911 if !has_feature(features) && !self.span.allows_unstable() {
912 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
913 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
919 features: &'a Features,
920 parse_sess: &'a ParseSess,
921 plugin_attributes: &'a [(String, AttributeType)],
924 macro_rules! gate_feature_fn {
925 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
926 let (cx, has_feature, span,
927 name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
928 let has_feature: bool = has_feature(&$cx.features);
929 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
930 if !has_feature && !span.allows_unstable() {
931 leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
937 macro_rules! gate_feature {
938 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
939 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
940 stringify!($feature), $explain, GateStrength::Hard)
942 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
943 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
944 stringify!($feature), $explain, $level)
948 impl<'a> Context<'a> {
949 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
950 debug!("check_attribute(attr = {:?})", attr);
951 let name = unwrap_or!(attr.name(), return).as_str();
952 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
954 if let Gated(_, name, desc, ref has_feature) = *gateage {
955 gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
957 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
961 for &(ref n, ref ty) in self.plugin_attributes {
962 if attr.path == &**n {
963 // Plugins can't gate attributes, so we don't check for it
964 // unlike the code above; we only use this loop to
965 // short-circuit to avoid the checks below
966 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
970 if name.starts_with("rustc_") {
971 gate_feature!(self, rustc_attrs, attr.span,
972 "unless otherwise specified, attributes \
973 with the prefix `rustc_` \
974 are reserved for internal compiler diagnostics");
975 } else if name.starts_with("derive_") {
976 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
977 } else if !attr::is_known(attr) {
978 // Only run the custom attribute lint during regular
979 // feature gate checking. Macro gating runs
980 // before the plugin attributes are registered
981 // so we skip this then
983 gate_feature!(self, custom_attribute, attr.span,
984 &format!("The attribute `{}` is currently \
985 unknown to the compiler and \
987 added to it in the future",
994 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
995 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
996 cx.check_attribute(attr, true);
999 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
1000 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
1003 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
1004 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
1006 // FIXME (#28244): enforce that active features have issue numbers
1007 // assert!(issue.is_some())
1010 // search in Accepted, Removed, or Stable Removed features
1011 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
1012 .find(|t| t.0 == feature);
1014 Some(&(_, _, issue)) => issue,
1015 None => panic!("Feature `{}` is not declared anywhere", feature),
1020 pub enum GateIssue {
1022 Library(Option<u32>)
1025 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1026 pub enum GateStrength {
1027 /// A hard error. (Most feature gates should use this.)
1029 /// Only a warning. (Use this only as backwards-compatibility demands.)
1033 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1035 feature_err(sess, feature, span, issue, explain).emit();
1038 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1039 explain: &str) -> DiagnosticBuilder<'a> {
1040 leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
1043 fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1044 explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
1045 let diag = &sess.span_diagnostic;
1047 let issue = match issue {
1048 GateIssue::Language => find_lang_feature_issue(feature),
1049 GateIssue::Library(lib) => lib,
1052 let explanation = if let Some(n) = issue {
1053 format!("{} (see issue #{})", explain, n)
1058 let mut err = match level {
1059 GateStrength::Hard => diag.struct_span_err(span, &explanation),
1060 GateStrength::Soft => diag.struct_span_warn(span, &explanation),
1063 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1064 if sess.unstable_features.is_nightly_build() {
1065 err.help(&format!("add #![feature({})] to the \
1066 crate attributes to enable",
1070 // If we're on stable and only emitting a "soft" warning, add a note to
1071 // clarify that the feature isn't "on" (rather than being on but
1073 if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
1074 err.help("a nightly build of the compiler is required to enable this feature");
1081 const EXPLAIN_BOX_SYNTAX: &'static str =
1082 "box expression syntax is experimental; you can call `Box::new` instead.";
1084 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1085 "attributes on non-item statements and expressions are experimental.";
1087 pub const EXPLAIN_ASM: &'static str =
1088 "inline assembly is not stable enough for use and is subject to change";
1090 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1091 "`global_asm!` is not stable enough for use and is subject to change";
1093 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1094 "`log_syntax!` is not stable enough for use and is subject to change";
1096 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1097 "`concat_idents` is not stable enough for use and is subject to change";
1099 pub const EXPLAIN_TRACE_MACROS: &'static str =
1100 "`trace_macros` is not stable enough for use and is subject to change";
1101 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1102 "allow_internal_unstable side-steps feature gating and stability checks";
1103 pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
1104 "allow_internal_unsafe side-steps the unsafe_code lint";
1106 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1107 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1109 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1110 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1111 Prefer using procedural macro custom derive.";
1113 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1114 "attributes of the form `#[derive_*]` are reserved for the compiler";
1116 pub const EXPLAIN_VIS_MATCHER: &'static str =
1117 ":vis fragment specifier is experimental and subject to change";
1119 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1120 "placement-in expression syntax is experimental and subject to change.";
1122 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1123 "Unsized tuple coercion is not stable enough for use and is subject to change";
1125 struct PostExpansionVisitor<'a> {
1126 context: &'a Context<'a>,
1129 macro_rules! gate_feature_post {
1130 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1131 let (cx, span) = ($cx, $span);
1132 if !span.allows_unstable() {
1133 gate_feature!(cx.context, $feature, span, $explain)
1136 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
1137 let (cx, span) = ($cx, $span);
1138 if !span.allows_unstable() {
1139 gate_feature!(cx.context, $feature, span, $explain, $level)
1144 impl<'a> PostExpansionVisitor<'a> {
1145 fn check_abi(&self, abi: Abi, span: Span) {
1147 Abi::RustIntrinsic => {
1148 gate_feature_post!(&self, intrinsics, span,
1149 "intrinsics are subject to change");
1151 Abi::PlatformIntrinsic => {
1152 gate_feature_post!(&self, platform_intrinsics, span,
1153 "platform intrinsics are experimental and possibly buggy");
1155 Abi::Vectorcall => {
1156 gate_feature_post!(&self, abi_vectorcall, span,
1157 "vectorcall is experimental and subject to change");
1160 gate_feature_post!(&self, abi_thiscall, span,
1161 "thiscall is experimental and subject to change");
1164 gate_feature_post!(&self, unboxed_closures, span,
1165 "rust-call ABI is subject to change");
1168 gate_feature_post!(&self, abi_sysv64, span,
1169 "sysv64 ABI is experimental and subject to change");
1172 gate_feature_post!(&self, abi_ptx, span,
1173 "PTX ABIs are experimental and subject to change");
1175 Abi::Unadjusted => {
1176 gate_feature_post!(&self, abi_unadjusted, span,
1177 "unadjusted ABI is an implementation detail and perma-unstable");
1179 Abi::Msp430Interrupt => {
1180 gate_feature_post!(&self, abi_msp430_interrupt, span,
1181 "msp430-interrupt ABI is experimental and subject to change");
1183 Abi::X86Interrupt => {
1184 gate_feature_post!(&self, abi_x86_interrupt, span,
1185 "x86-interrupt ABI is experimental and subject to change");
1200 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1201 use ast::MetaItemKind::*;
1202 use ast::NestedMetaItemKind::*;
1206 NameValue(ref lit) => !lit.node.is_str(),
1207 List(ref list) => list.iter().any(|li| {
1209 MetaItem(ref mi) => contains_novel_literal(mi),
1216 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1217 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1218 if !attr.span.allows_unstable() {
1219 // check for gated attributes
1220 self.context.check_attribute(attr, false);
1223 if attr.check_name("doc") {
1224 if let Some(content) = attr.meta_item_list() {
1225 if content.len() == 1 && content[0].check_name("cfg") {
1226 gate_feature_post!(&self, doc_cfg, attr.span,
1227 "#[doc(cfg(...))] is experimental"
1233 if self.context.features.proc_macro && attr::is_known(attr) {
1237 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1238 if contains_novel_literal(&meta) {
1239 gate_feature_post!(&self, attr_literals, attr.span,
1240 "non-string literals in attributes, or string \
1241 literals in top-level positions, are experimental");
1245 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1246 if !name.as_str().is_ascii() {
1247 gate_feature_post!(&self, non_ascii_idents, sp,
1248 "non-ascii idents are not fully supported.");
1252 fn visit_item(&mut self, i: &'a ast::Item) {
1254 ast::ItemKind::ExternCrate(_) => {
1255 if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
1256 gate_feature_post!(&self, macro_reexport, attr.span,
1257 "macros reexports are experimental \
1258 and possibly buggy");
1262 ast::ItemKind::ForeignMod(ref foreign_module) => {
1263 self.check_abi(foreign_module.abi, i.span);
1266 ast::ItemKind::Fn(..) => {
1267 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1268 gate_feature_post!(&self, plugin_registrar, i.span,
1269 "compiler plugins are experimental and possibly buggy");
1271 if attr::contains_name(&i.attrs[..], "start") {
1272 gate_feature_post!(&self, start, i.span,
1273 "a #[start] function is an experimental \
1274 feature whose signature may change \
1277 if attr::contains_name(&i.attrs[..], "main") {
1278 gate_feature_post!(&self, main, i.span,
1279 "declaration of a nonstandard #[main] \
1280 function may change over time, for now \
1281 a top-level `fn main()` is required");
1283 if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") {
1284 gate_feature_post!(&self, fn_must_use, attr.span,
1285 "`#[must_use]` on functions is experimental",
1286 GateStrength::Soft);
1290 ast::ItemKind::Struct(..) => {
1291 if let Some(attr) = attr::find_by_name(&i.attrs[..], "simd") {
1292 gate_feature_post!(&self, simd, attr.span,
1293 "SIMD types are experimental and possibly buggy");
1294 self.context.parse_sess.span_diagnostic.span_warn(attr.span,
1295 "the `#[simd]` attribute \
1296 is deprecated, use \
1297 `#[repr(simd)]` instead");
1299 if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
1300 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1301 if item.check_name("simd") {
1302 gate_feature_post!(&self, repr_simd, attr.span,
1303 "SIMD types are experimental and possibly buggy");
1305 if item.check_name("align") {
1306 gate_feature_post!(&self, repr_align, attr.span,
1307 "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 let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") {
1338 gate_feature_post!(&self, fn_must_use, attr.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::Yield(..) => {
1414 gate_feature_post!(&self, generators,
1416 "yield syntax is experimental");
1418 ast::ExprKind::Lit(ref lit) => {
1419 if let ast::LitKind::Int(_, ref ty) = lit.node {
1421 ast::LitIntType::Signed(ast::IntTy::I128) |
1422 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1423 gate_feature_post!(&self, i128_type, e.span,
1424 "128-bit integers are not stable");
1430 ast::ExprKind::Catch(_) => {
1431 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1435 visit::walk_expr(self, e);
1438 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1439 match pattern.node {
1440 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1441 gate_feature_post!(&self, advanced_slice_patterns,
1443 "multiple-element slice matches anywhere \
1444 but at the end of a slice (e.g. \
1445 `[0, ..xs, 0]`) are experimental")
1447 PatKind::Slice(..) => {
1448 gate_feature_post!(&self, slice_patterns,
1450 "slice pattern syntax is experimental");
1452 PatKind::Box(..) => {
1453 gate_feature_post!(&self, box_patterns,
1455 "box pattern syntax is experimental");
1457 PatKind::Range(_, _, RangeEnd::Excluded) => {
1458 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1459 "exclusive range pattern syntax is experimental");
1463 visit::walk_pat(self, pattern)
1466 fn visit_fn(&mut self,
1467 fn_kind: FnKind<'a>,
1468 fn_decl: &'a ast::FnDecl,
1471 // check for const fn declarations
1472 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1474 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1476 // stability of const fn methods are covered in
1477 // visit_trait_item and visit_impl_item below; this is
1478 // because default methods don't pass through this
1482 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1483 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1484 self.check_abi(abi, span);
1488 visit::walk_fn(self, fn_kind, fn_decl, span);
1491 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1493 ast::TraitItemKind::Method(ref sig, ref block) => {
1494 if block.is_none() {
1495 self.check_abi(sig.abi, ti.span);
1497 if sig.constness.node == ast::Constness::Const {
1498 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1501 ast::TraitItemKind::Type(_, Some(_)) => {
1502 gate_feature_post!(&self, associated_type_defaults, ti.span,
1503 "associated type defaults are unstable");
1507 visit::walk_trait_item(self, ti);
1510 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1511 if ii.defaultness == ast::Defaultness::Default {
1512 gate_feature_post!(&self, specialization,
1514 "specialization is unstable");
1518 ast::ImplItemKind::Method(ref sig, _) => {
1519 if sig.constness.node == ast::Constness::Const {
1520 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1525 visit::walk_impl_item(self, ii);
1528 fn visit_generics(&mut self, g: &'a ast::Generics) {
1529 for t in &g.ty_params {
1530 if !t.attrs.is_empty() {
1531 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1532 "attributes on type parameter bindings are experimental");
1535 visit::walk_generics(self, g)
1538 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1539 if !lifetime_def.attrs.is_empty() {
1540 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1541 "attributes on lifetime bindings are experimental");
1543 visit::walk_lifetime_def(self, lifetime_def)
1547 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1548 let mut features = Features::new();
1550 let mut feature_checker = MutexFeatureChecker::default();
1552 for attr in krate_attrs {
1553 if !attr.check_name("feature") {
1557 match attr.meta_item_list() {
1559 span_err!(span_handler, attr.span, E0555,
1560 "malformed feature attribute, expected #![feature(...)]");
1564 let name = if let Some(word) = mi.word() {
1567 span_err!(span_handler, mi.span, E0556,
1568 "malformed feature, expected just one word");
1572 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1573 .find(|& &(n, _, _, _)| name == n) {
1574 set(&mut features, mi.span);
1575 feature_checker.collect(&features, mi.span);
1577 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1578 .find(|& &(n, _, _)| name == n)
1579 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1580 .find(|& &(n, _, _)| name == n)) {
1581 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1583 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1584 .find(|& &(n, _, _)| name == n) {
1585 features.declared_stable_lang_features.push((name, mi.span));
1587 features.declared_lib_features.push((name, mi.span));
1594 feature_checker.check(span_handler);
1599 // A collector for mutually-exclusive features and their flag spans
1601 struct MutexFeatureChecker {
1602 proc_macro: Option<Span>,
1603 custom_attribute: Option<Span>,
1606 impl MutexFeatureChecker {
1607 // If this method turns out to be a hotspot due to branching,
1608 // the branching can be eliminated by modifying `set!()` to set these spans
1609 // only for the features that need to be checked for mutual exclusion.
1610 fn collect(&mut self, features: &Features, span: Span) {
1611 if features.proc_macro {
1612 // If self.proc_macro is None, set to Some(span)
1613 self.proc_macro = self.proc_macro.or(Some(span));
1616 if features.custom_attribute {
1617 self.custom_attribute = self.custom_attribute.or(Some(span));
1621 fn check(self, handler: &Handler) {
1622 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1623 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1624 `#![feature(custom_attribute)] at the same time")
1625 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1633 pub fn check_crate(krate: &ast::Crate,
1635 features: &Features,
1636 plugin_attributes: &[(String, AttributeType)],
1637 unstable: UnstableFeatures) {
1638 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1644 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1647 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1648 pub enum UnstableFeatures {
1649 /// Hard errors for unstable features are active, as on
1650 /// beta/stable channels.
1652 /// Allow features to be activated, as on nightly.
1654 /// Errors are bypassed for bootstrapping. This is required any time
1655 /// during the build that feature-related lints are set to warn or above
1656 /// because the build turns on warnings-as-errors and uses lots of unstable
1657 /// features. As a result, this is always required for building Rust itself.
1661 impl UnstableFeatures {
1662 pub fn from_environment() -> UnstableFeatures {
1663 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1664 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1665 // Whether we should enable unstable features for bootstrapping
1666 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1667 match (disable_unstable_features, bootstrap) {
1668 (_, true) => UnstableFeatures::Cheat,
1669 (true, _) => UnstableFeatures::Disallow,
1670 (false, _) => UnstableFeatures::Allow
1674 pub fn is_nightly_build(&self) -> bool {
1676 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1682 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1683 unstable: UnstableFeatures) {
1684 let allow_features = match unstable {
1685 UnstableFeatures::Allow => true,
1686 UnstableFeatures::Disallow => false,
1687 UnstableFeatures::Cheat => true
1689 if !allow_features {
1690 for attr in &krate.attrs {
1691 if attr.check_name("feature") {
1692 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1693 span_err!(span_handler, attr.span, E0554,
1694 "#![feature] may not be used on the {} release channel",