1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 //! This module implements the gating necessary for preventing certain compiler
14 //! features from being used by default. This module will crawl a pre-expanded
15 //! AST to ensure that there are no features which are used that are not
18 //! Features are enabled in programs via the crate-level attributes of
19 //! `#![feature(...)]` with a comma-separated list of features.
21 //! For the purpose of future feature-tracking, once code for detection of feature
22 //! gate usage is added, *do not remove it again* even once the feature
25 use self::AttributeType::*;
26 use self::AttributeGate::*;
29 use ast::{self, NodeId, PatKind, RangeEnd};
33 use errors::{DiagnosticBuilder, Handler, FatalError};
34 use visit::{self, FnKind, Visitor};
38 use std::ascii::AsciiExt;
43 fn f(features: &mut Features, span: Span) {
44 features.declared_lib_features.push((Symbol::intern("proc_macro"), span));
45 features.proc_macro = true;
47 f as fn(&mut Features, Span)
50 fn f(features: &mut Features, _: Span) {
51 features.$field = true;
53 f as fn(&mut Features, Span)
57 macro_rules! declare_features {
58 ($((active, $feature: ident, $ver: expr, $issue: expr),)+) => {
59 /// Represents active features that are currently being implemented or
60 /// currently being considered for addition/removal.
61 const ACTIVE_FEATURES:
62 &'static [(&'static str, &'static str, Option<u32>, fn(&mut Features, Span))] =
63 &[$((stringify!($feature), $ver, $issue, set!($feature))),+];
65 /// A set of features to be used by later passes.
67 /// #![feature] attrs for stable language features, for error reporting
68 pub declared_stable_lang_features: Vec<(Symbol, Span)>,
69 /// #![feature] attrs for non-language (library) features
70 pub declared_lib_features: Vec<(Symbol, Span)>,
71 $(pub $feature: bool),+
75 pub fn new() -> Features {
77 declared_stable_lang_features: Vec::new(),
78 declared_lib_features: Vec::new(),
85 ($((removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
86 /// Represents unstable features which have since been removed (it was once Active)
87 const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
88 $((stringify!($feature), $ver, $issue)),+
92 ($((stable_removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
93 /// Represents stable features which have since been removed (it was once Accepted)
94 const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
95 $((stringify!($feature), $ver, $issue)),+
99 ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => {
100 /// Those language feature has since been Accepted (it was once Active)
101 const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
102 $((stringify!($feature), $ver, $issue)),+
107 // If you change this, please modify src/doc/unstable-book as well.
109 // Don't ever remove anything from this list; set them to 'Removed'.
111 // The version numbers here correspond to the version in which the current status
112 // was set. This is most important for knowing when a particular feature became
115 // NB: The featureck.py script parses this information directly out of the source
116 // so take care when modifying it.
119 (active, asm, "1.0.0", Some(29722)),
120 (active, concat_idents, "1.0.0", Some(29599)),
121 (active, link_args, "1.0.0", Some(29596)),
122 (active, log_syntax, "1.0.0", Some(29598)),
123 (active, non_ascii_idents, "1.0.0", Some(28979)),
124 (active, plugin_registrar, "1.0.0", Some(29597)),
125 (active, thread_local, "1.0.0", Some(29594)),
126 (active, trace_macros, "1.0.0", Some(29598)),
128 // rustc internal, for now:
129 (active, intrinsics, "1.0.0", None),
130 (active, lang_items, "1.0.0", None),
132 (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
133 (active, linkage, "1.0.0", Some(29603)),
134 (active, quote, "1.0.0", Some(29601)),
135 (active, simd, "1.0.0", Some(27731)),
139 (active, rustc_diagnostic_macros, "1.0.0", None),
140 (active, advanced_slice_patterns, "1.0.0", Some(23121)),
141 (active, box_syntax, "1.0.0", Some(27779)),
142 (active, placement_in_syntax, "1.0.0", Some(27779)),
143 (active, unboxed_closures, "1.0.0", Some(29625)),
145 (active, fundamental, "1.0.0", Some(29635)),
146 (active, main, "1.0.0", Some(29634)),
147 (active, needs_allocator, "1.4.0", Some(27389)),
148 (active, on_unimplemented, "1.0.0", Some(29628)),
149 (active, plugin, "1.0.0", Some(29597)),
150 (active, simd_ffi, "1.0.0", Some(27731)),
151 (active, start, "1.0.0", Some(29633)),
152 (active, structural_match, "1.8.0", Some(31434)),
153 (active, panic_runtime, "1.10.0", Some(32837)),
154 (active, needs_panic_runtime, "1.10.0", Some(32837)),
156 // OIBIT specific features
157 (active, optin_builtin_traits, "1.0.0", Some(13231)),
159 // macro reexport needs more discussion and stabilization
160 (active, macro_reexport, "1.0.0", Some(29638)),
162 // Allows use of #[staged_api]
164 (active, staged_api, "1.0.0", None),
166 // Allows using #![no_core]
167 (active, no_core, "1.3.0", Some(29639)),
169 // Allows using `box` in patterns; RFC 469
170 (active, box_patterns, "1.0.0", Some(29641)),
172 // Allows using the unsafe_destructor_blind_to_params attribute;
174 (active, dropck_parametricity, "1.3.0", Some(28498)),
176 // Allows using the may_dangle attribute; RFC 1327
177 (active, dropck_eyepatch, "1.10.0", Some(34761)),
179 // Allows the use of custom attributes; RFC 572
180 (active, custom_attribute, "1.0.0", Some(29642)),
182 // Allows the use of #[derive(Anything)] as sugar for
183 // #[derive_Anything].
184 (active, custom_derive, "1.0.0", Some(29644)),
186 // Allows the use of rustc_* attributes; RFC 572
187 (active, rustc_attrs, "1.0.0", Some(29642)),
189 // Allows the use of #[allow_internal_unstable]. This is an
190 // attribute on macro_rules! and can't use the attribute handling
191 // below (it has to be checked before expansion possibly makes
192 // macros disappear).
195 (active, allow_internal_unstable, "1.0.0", None),
197 // #23121. Array patterns have some hazards yet.
198 (active, slice_patterns, "1.0.0", Some(23121)),
200 // Allows the definition of `const fn` functions.
201 (active, const_fn, "1.2.0", Some(24111)),
203 // Allows indexing into constant arrays.
204 (active, const_indexing, "1.4.0", Some(29947)),
206 // Allows using #[prelude_import] on glob `use` items.
209 (active, prelude_import, "1.2.0", None),
211 // Allows default type parameters to influence type inference.
212 (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
214 // Allows associated type defaults
215 (active, associated_type_defaults, "1.2.0", Some(29661)),
217 // allow `repr(simd)`, and importing the various simd intrinsics
218 (active, repr_simd, "1.4.0", Some(27731)),
220 // Allows cfg(target_feature = "...").
221 (active, cfg_target_feature, "1.4.0", Some(29717)),
223 // allow `extern "platform-intrinsic" { ... }`
224 (active, platform_intrinsics, "1.4.0", Some(27731)),
227 // rust runtime internal
228 (active, unwind_attributes, "1.4.0", None),
230 // allow the use of `#[naked]` on functions.
231 (active, naked_functions, "1.9.0", Some(32408)),
233 // allow `#[no_debug]`
234 (active, no_debug, "1.5.0", Some(29721)),
236 // allow `#[omit_gdb_pretty_printer_section]`
238 (active, omit_gdb_pretty_printer_section, "1.5.0", None),
240 // Allows cfg(target_vendor = "...").
241 (active, cfg_target_vendor, "1.5.0", Some(29718)),
243 // Allow attributes on expressions and non-item statements
244 (active, stmt_expr_attributes, "1.6.0", Some(15701)),
246 // allow using type ascription in expressions
247 (active, type_ascription, "1.6.0", Some(23416)),
249 // Allows cfg(target_thread_local)
250 (active, cfg_target_thread_local, "1.7.0", Some(29594)),
253 (active, abi_vectorcall, "1.7.0", None),
256 (active, inclusive_range_syntax, "1.7.0", Some(28237)),
259 (active, exclusive_range_pattern, "1.11.0", Some(37854)),
261 // impl specialization (RFC 1210)
262 (active, specialization, "1.7.0", Some(31844)),
264 // Allow Drop types in statics/const functions (RFC 1440)
265 (active, drop_types_in_const, "1.9.0", Some(33156)),
267 // Allows cfg(target_has_atomic = "...").
268 (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
270 // Allows `impl Trait` in function return types.
271 (active, conservative_impl_trait, "1.12.0", Some(34511)),
274 (active, never_type, "1.13.0", Some(35121)),
276 // Allows all literals in attribute lists and values of key-value pairs.
277 (active, attr_literals, "1.13.0", Some(34981)),
279 // Allows the sysV64 ABI to be specified on all platforms
280 // instead of just the platforms on which it is the C ABI
281 (active, abi_sysv64, "1.13.0", Some(36167)),
283 // Allows untagged unions `union U { ... }`
284 (active, untagged_unions, "1.13.0", Some(32836)),
286 // Used to identify the `compiler_builtins` crate
288 (active, compiler_builtins, "1.13.0", None),
290 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
291 (active, generic_param_attrs, "1.11.0", Some(34761)),
293 // Allows #[link(..., cfg(..))]
294 (active, link_cfg, "1.14.0", Some(37406)),
296 (active, use_extern_macros, "1.15.0", Some(35896)),
298 // Allows #[target_feature(...)]
299 (active, target_feature, "1.15.0", None),
301 // `extern "ptx-*" fn()`
302 (active, abi_ptx, "1.15.0", None),
305 (active, i128_type, "1.16.0", Some(35118)),
307 // The `unadjusted` ABI. Perma unstable.
308 (active, abi_unadjusted, "1.16.0", None),
310 // Procedural macros 2.0.
311 (active, proc_macro, "1.16.0", Some(38356)),
313 // Declarative macros 2.0 (`macro`).
314 (active, decl_macro, "1.17.0", Some(39412)),
316 // Allows #[link(kind="static-nobundle"...]
317 (active, static_nobundle, "1.16.0", Some(37403)),
319 // `extern "msp430-interrupt" fn()`
320 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
322 // Used to identify crates that contain sanitizer runtimes
324 (active, sanitizer_runtime, "1.17.0", None),
326 // Used to identify crates that contain the profiler runtime
328 (active, profiler_runtime, "1.18.0", None),
330 // `extern "x86-interrupt" fn()`
331 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
334 // Allows the `catch {...}` expression
335 (active, catch_expr, "1.17.0", Some(31436)),
337 // Allows `repr(align(u16))` struct attribute (RFC 1358)
338 (active, repr_align, "1.17.0", Some(33626)),
340 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
341 (active, rvalue_static_promotion, "1.15.1", Some(38865)),
343 // Used to preserve symbols (see llvm.used)
344 (active, used, "1.18.0", Some(40289)),
346 // Allows module-level inline assembly by way of global_asm!()
347 (active, global_asm, "1.18.0", Some(35119)),
349 // Allows overlapping impls of marker traits
350 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
352 // Allows use of the :vis macro fragment specifier
353 (active, macro_vis_matcher, "1.18.0", Some(41022)),
356 (active, abi_thiscall, "1.19.0", None),
358 // Allows a test to fail without failing the whole suite
359 (active, allow_fail, "1.19.0", Some(42219)),
361 // Allows unsized tuple coercion.
362 (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
364 // global allocators and their internals
365 (active, global_allocator, "1.20.0", None),
366 (active, allocator_internals, "1.20.0", None),
370 (removed, import_shadowing, "1.0.0", None),
371 (removed, managed_boxes, "1.0.0", None),
372 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
373 (removed, negate_unsigned, "1.0.0", Some(29645)),
374 (removed, reflect, "1.0.0", Some(27749)),
375 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
376 (removed, opt_out_copy, "1.0.0", None),
377 (removed, quad_precision_float, "1.0.0", None),
378 (removed, struct_inherit, "1.0.0", None),
379 (removed, test_removed_feature, "1.0.0", None),
380 (removed, visible_private_types, "1.0.0", None),
381 (removed, unsafe_no_drop_flag, "1.0.0", None),
382 // Allows using items which are missing stability attributes
384 (removed, unmarked_api, "1.0.0", None),
385 (removed, pushpop_unsafe, "1.2.0", None),
386 (removed, allocator, "1.0.0", None),
390 (stable_removed, no_stack_check, "1.0.0", None),
394 (accepted, associated_types, "1.0.0", None),
395 // allow overloading augmented assignment operations like `a += b`
396 (accepted, augmented_assignments, "1.8.0", Some(28235)),
397 // allow empty structs and enum variants with braces
398 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
399 (accepted, default_type_params, "1.0.0", None),
400 (accepted, globs, "1.0.0", None),
401 (accepted, if_let, "1.0.0", None),
402 // A temporary feature gate used to enable parser extensions needed
403 // to bootstrap fix for #5723.
404 (accepted, issue_5723_bootstrap, "1.0.0", None),
405 (accepted, macro_rules, "1.0.0", None),
406 // Allows using #![no_std]
407 (accepted, no_std, "1.6.0", None),
408 (accepted, slicing_syntax, "1.0.0", None),
409 (accepted, struct_variant, "1.0.0", None),
410 // These are used to test this portion of the compiler, they don't actually
412 (accepted, test_accepted_feature, "1.0.0", None),
413 (accepted, tuple_indexing, "1.0.0", None),
414 // Allows macros to appear in the type position.
415 (accepted, type_macros, "1.13.0", Some(27245)),
416 (accepted, while_let, "1.0.0", None),
417 // Allows `#[deprecated]` attribute
418 (accepted, deprecated, "1.9.0", Some(29935)),
420 (accepted, question_mark, "1.13.0", Some(31436)),
421 // Allows `..` in tuple (struct) patterns
422 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
423 (accepted, item_like_imports, "1.15.0", Some(35120)),
424 // Allows using `Self` and associated types in struct expressions and patterns.
425 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
426 // elide `'static` lifetimes in `static`s and `const`s
427 (accepted, static_in_const, "1.17.0", Some(35897)),
428 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
429 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
430 // Allows the definition recursive static items.
431 (accepted, static_recursion, "1.17.0", Some(29719)),
432 // pub(restricted) visibilities (RFC 1422)
433 (accepted, pub_restricted, "1.18.0", Some(32409)),
434 // The #![windows_subsystem] attribute
435 (accepted, windows_subsystem, "1.18.0", Some(37499)),
436 // Allows `break {expr}` with a value inside `loop`s.
437 (accepted, loop_break_value, "1.19.0", Some(37339)),
438 // Permits numeric fields in struct expressions and patterns.
439 (accepted, relaxed_adts, "1.19.0", Some(35626)),
440 // Coerces non capturing closures to function pointers
441 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
442 // Allows attributes on struct literal fields.
443 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
444 // Allows the definition of associated constants in `trait` or `impl`
446 (accepted, associated_consts, "1.20.0", Some(29646)),
447 // Usage of the `compile_error!` macro
448 (accepted, compile_error, "1.20.0", Some(40872)),
451 // If you change this, please modify src/doc/unstable-book as well. You must
452 // move that documentation into the relevant place in the other docs, and
453 // remove the chapter on the flag.
455 #[derive(PartialEq, Copy, Clone, Debug)]
456 pub enum AttributeType {
457 /// Normal, builtin attribute that is consumed
458 /// by the compiler before the unused_attribute check
461 /// Builtin attribute that may not be consumed by the compiler
462 /// before the unused_attribute check. These attributes
463 /// will be ignored by the unused_attribute lint
466 /// Builtin attribute that is only allowed at the crate level
470 pub enum AttributeGate {
471 /// Is gated by a given feature gate, reason
472 /// and function to check if enabled
473 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
475 /// Ungated attribute, can be used on all release channels
480 fn is_deprecated(&self) -> bool {
482 Gated(Stability::Deprecated(_), ..) => true,
488 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
491 // Argument is tracking issue link.
492 Deprecated(&'static str),
496 impl ::std::fmt::Debug for AttributeGate {
497 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
499 Gated(ref stab, name, expl, _) =>
500 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
501 Ungated => write!(fmt, "Ungated")
506 macro_rules! cfg_fn {
507 ($field: ident) => {{
508 fn f(features: &Features) -> bool {
511 f as fn(&Features) -> bool
515 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
516 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
519 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
520 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
523 // Attributes that have a special meaning to rustc or rustdoc
524 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
527 ("warn", Normal, Ungated),
528 ("allow", Normal, Ungated),
529 ("forbid", Normal, Ungated),
530 ("deny", Normal, Ungated),
532 ("macro_reexport", Normal, Ungated),
533 ("macro_use", Normal, Ungated),
534 ("macro_export", Normal, Ungated),
535 ("plugin_registrar", Normal, Ungated),
537 ("cfg", Normal, Ungated),
538 ("cfg_attr", Normal, Ungated),
539 ("main", Normal, Ungated),
540 ("start", Normal, Ungated),
541 ("test", Normal, Ungated),
542 ("bench", Normal, Ungated),
543 ("simd", Normal, Ungated),
544 ("repr", Normal, Ungated),
545 ("path", Normal, Ungated),
546 ("abi", Normal, Ungated),
547 ("automatically_derived", Normal, Ungated),
548 ("no_mangle", Normal, Ungated),
549 ("no_link", Normal, Ungated),
550 ("derive", Normal, Ungated),
551 ("should_panic", Normal, Ungated),
552 ("ignore", Normal, Ungated),
553 ("no_implicit_prelude", Normal, Ungated),
554 ("reexport_test_harness_main", Normal, Ungated),
555 ("link_args", Normal, Gated(Stability::Unstable,
557 "the `link_args` attribute is experimental and not \
558 portable across platforms, it is recommended to \
559 use `#[link(name = \"foo\")] instead",
560 cfg_fn!(link_args))),
561 ("macro_escape", Normal, Ungated),
564 ("structural_match", Whitelisted, Gated(Stability::Unstable,
566 "the semantics of constant patterns is \
568 cfg_fn!(structural_match))),
570 ("plugin", CrateLevel, Gated(Stability::Unstable,
572 "compiler plugins are experimental \
576 ("no_std", CrateLevel, Ungated),
577 ("no_core", CrateLevel, Gated(Stability::Unstable,
579 "no_core is experimental",
581 ("lang", Normal, Gated(Stability::Unstable,
583 "language items are subject to change",
584 cfg_fn!(lang_items))),
585 ("linkage", Whitelisted, Gated(Stability::Unstable,
587 "the `linkage` attribute is experimental \
588 and not portable across platforms",
590 ("thread_local", Whitelisted, Gated(Stability::Unstable,
592 "`#[thread_local]` is an experimental feature, and does \
593 not currently handle destructors. There is no \
594 corresponding `#[task_local]` mapping to the task \
596 cfg_fn!(thread_local))),
598 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
600 "the `#[rustc_on_unimplemented]` attribute \
601 is an experimental feature",
602 cfg_fn!(on_unimplemented))),
603 ("global_allocator", Normal, Gated(Stability::Unstable,
605 "the `#[global_allocator]` attribute is \
606 an experimental feature",
607 cfg_fn!(global_allocator))),
608 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
609 "allocator_internals",
610 "the `#[default_lib_allocator]` \
611 attribute is an experimental feature",
612 cfg_fn!(allocator_internals))),
613 ("needs_allocator", Normal, Gated(Stability::Unstable,
614 "allocator_internals",
615 "the `#[needs_allocator]` \
616 attribute is an experimental \
618 cfg_fn!(allocator_internals))),
619 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
621 "the `#[panic_runtime]` attribute is \
622 an experimental feature",
623 cfg_fn!(panic_runtime))),
624 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
625 "needs_panic_runtime",
626 "the `#[needs_panic_runtime]` \
627 attribute is an experimental \
629 cfg_fn!(needs_panic_runtime))),
630 ("rustc_variance", Normal, Gated(Stability::Unstable,
632 "the `#[rustc_variance]` attribute \
633 is just used for rustc unit tests \
634 and will never be stable",
635 cfg_fn!(rustc_attrs))),
636 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
638 "the `#[rustc_error]` attribute \
639 is just used for rustc unit tests \
640 and will never be stable",
641 cfg_fn!(rustc_attrs))),
642 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
644 "the `#[rustc_if_this_changed]` attribute \
645 is just used for rustc unit tests \
646 and will never be stable",
647 cfg_fn!(rustc_attrs))),
648 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
650 "the `#[rustc_if_this_changed]` attribute \
651 is just used for rustc unit tests \
652 and will never be stable",
653 cfg_fn!(rustc_attrs))),
654 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
656 "the `#[rustc_dirty]` attribute \
657 is just used for rustc unit tests \
658 and will never be stable",
659 cfg_fn!(rustc_attrs))),
660 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
662 "the `#[rustc_clean]` attribute \
663 is just used for rustc unit tests \
664 and will never be stable",
665 cfg_fn!(rustc_attrs))),
666 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
668 "the `#[rustc_metadata_dirty]` attribute \
669 is just used for rustc unit tests \
670 and will never be stable",
671 cfg_fn!(rustc_attrs))),
672 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
674 "the `#[rustc_metadata_clean]` attribute \
675 is just used for rustc unit tests \
676 and will never be stable",
677 cfg_fn!(rustc_attrs))),
678 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
681 is just used for rustc unit tests \
682 and will never be stable",
683 cfg_fn!(rustc_attrs))),
684 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
687 is just used for rustc unit tests \
688 and will never be stable",
689 cfg_fn!(rustc_attrs))),
690 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
692 "internal rustc attributes will never be stable",
693 cfg_fn!(rustc_attrs))),
694 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
696 "internal rustc attributes will never be stable",
697 cfg_fn!(rustc_attrs))),
698 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
700 "the `#[rustc_mir]` attribute \
701 is just used for rustc unit tests \
702 and will never be stable",
703 cfg_fn!(rustc_attrs))),
704 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
706 "the `#[rustc_inherit_overflow_checks]` \
707 attribute is just used to control \
708 overflow checking behavior of several \
709 libcore functions that are inlined \
710 across crates and will never be stable",
711 cfg_fn!(rustc_attrs))),
712 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
714 "the `#[compiler_builtins]` attribute is used to \
715 identify the `compiler_builtins` crate which \
716 contains compiler-rt intrinsics and will never be \
718 cfg_fn!(compiler_builtins))),
719 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
721 "the `#[sanitizer_runtime]` attribute is used to \
722 identify crates that contain the runtime of a \
723 sanitizer and will never be stable",
724 cfg_fn!(sanitizer_runtime))),
725 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
727 "the `#[profiler_runtime]` attribute is used to \
728 identify the `profiler_builtins` crate which \
729 contains the profiler runtime and will never be \
731 cfg_fn!(profiler_runtime))),
733 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
734 "allow_internal_unstable",
735 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
736 cfg_fn!(allow_internal_unstable))),
738 ("fundamental", Whitelisted, Gated(Stability::Unstable,
740 "the `#[fundamental]` attribute \
741 is an experimental feature",
742 cfg_fn!(fundamental))),
744 ("proc_macro_derive", Normal, Ungated),
746 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
748 "internal implementation detail",
749 cfg_fn!(rustc_attrs))),
751 // FIXME: #14408 whitelist docs since rustdoc looks at them
752 ("doc", Whitelisted, Ungated),
754 // FIXME: #14406 these are processed in trans, which happens after the
756 ("cold", Whitelisted, Ungated),
757 ("naked", Whitelisted, Gated(Stability::Unstable,
759 "the `#[naked]` attribute \
760 is an experimental feature",
761 cfg_fn!(naked_functions))),
762 ("target_feature", Whitelisted, Gated(
763 Stability::Unstable, "target_feature",
764 "the `#[target_feature]` attribute is an experimental feature",
765 cfg_fn!(target_feature))),
766 ("export_name", Whitelisted, Ungated),
767 ("inline", Whitelisted, Ungated),
768 ("link", Whitelisted, Ungated),
769 ("link_name", Whitelisted, Ungated),
770 ("link_section", Whitelisted, Ungated),
771 ("no_builtins", Whitelisted, Ungated),
772 ("no_mangle", Whitelisted, Ungated),
773 ("no_debug", Whitelisted, Gated(
774 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
776 "the `#[no_debug]` attribute is an experimental feature",
778 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
779 "omit_gdb_pretty_printer_section",
780 "the `#[omit_gdb_pretty_printer_section]` \
781 attribute is just used for the Rust test \
783 cfg_fn!(omit_gdb_pretty_printer_section))),
784 ("unsafe_destructor_blind_to_params",
786 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
787 "dropck_parametricity",
788 "unsafe_destructor_blind_to_params has been replaced by \
789 may_dangle and will be removed in the future",
790 cfg_fn!(dropck_parametricity))),
793 Gated(Stability::Unstable,
795 "may_dangle has unstable semantics and may be removed in the future",
796 cfg_fn!(dropck_eyepatch))),
797 ("unwind", Whitelisted, Gated(Stability::Unstable,
799 "#[unwind] is experimental",
800 cfg_fn!(unwind_attributes))),
801 ("used", Whitelisted, Gated(
802 Stability::Unstable, "used",
803 "the `#[used]` attribute is an experimental feature",
807 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
809 "`#[prelude_import]` is for use by rustc only",
810 cfg_fn!(prelude_import))),
812 // FIXME: #14407 these are only looked at on-demand so we can't
813 // guarantee they'll have already been checked
814 ("rustc_deprecated", Whitelisted, Ungated),
815 ("must_use", Whitelisted, Ungated),
816 ("stable", Whitelisted, Ungated),
817 ("unstable", Whitelisted, Ungated),
818 ("deprecated", Normal, Ungated),
820 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
822 "unboxed_closures are still evolving",
823 cfg_fn!(unboxed_closures))),
825 ("windows_subsystem", Whitelisted, Ungated),
827 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
829 "attribute proc macros are currently unstable",
830 cfg_fn!(proc_macro))),
832 ("proc_macro", Normal, Gated(Stability::Unstable,
834 "function-like proc macros are currently unstable",
835 cfg_fn!(proc_macro))),
837 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
838 "rustc_derive_registrar",
839 "used internally by rustc",
840 cfg_fn!(rustc_attrs))),
842 ("allow_fail", Normal, Gated(Stability::Unstable,
844 "allow_fail attribute is currently unstable",
845 cfg_fn!(allow_fail))),
847 // Crate level attributes
848 ("crate_name", CrateLevel, Ungated),
849 ("crate_type", CrateLevel, Ungated),
850 ("crate_id", CrateLevel, Ungated),
851 ("feature", CrateLevel, Ungated),
852 ("no_start", CrateLevel, Ungated),
853 ("no_main", CrateLevel, Ungated),
854 ("no_builtins", CrateLevel, Ungated),
855 ("recursion_limit", CrateLevel, Ungated),
856 ("type_length_limit", CrateLevel, Ungated),
859 // cfg(...)'s that are feature gated
860 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
861 // (name in cfg, feature, function to check if the feature is enabled)
862 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
863 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
864 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
865 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
868 #[derive(Debug, Eq, PartialEq)]
869 pub struct GatedCfg {
875 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
876 let name = cfg.name().as_str();
878 .position(|info| info.0 == name)
887 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
888 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
889 if !has_feature(features) && !self.span.allows_unstable() {
890 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
891 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
897 features: &'a Features,
898 parse_sess: &'a ParseSess,
899 plugin_attributes: &'a [(String, AttributeType)],
902 macro_rules! gate_feature_fn {
903 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
904 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
905 let has_feature: bool = has_feature(&$cx.features);
906 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
907 if !has_feature && !span.allows_unstable() {
908 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
913 macro_rules! gate_feature {
914 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
915 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
919 impl<'a> Context<'a> {
920 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
921 debug!("check_attribute(attr = {:?})", attr);
922 let name = unwrap_or!(attr.name(), return).as_str();
923 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
925 if let Gated(_, name, desc, ref has_feature) = *gateage {
926 gate_feature_fn!(self, has_feature, attr.span, name, desc);
928 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
932 for &(ref n, ref ty) in self.plugin_attributes {
933 if attr.path == &**n {
934 // Plugins can't gate attributes, so we don't check for it
935 // unlike the code above; we only use this loop to
936 // short-circuit to avoid the checks below
937 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
941 if name.starts_with("rustc_") {
942 gate_feature!(self, rustc_attrs, attr.span,
943 "unless otherwise specified, attributes \
944 with the prefix `rustc_` \
945 are reserved for internal compiler diagnostics");
946 } else if name.starts_with("derive_") {
947 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
948 } else if !attr::is_known(attr) {
949 // Only run the custom attribute lint during regular
950 // feature gate checking. Macro gating runs
951 // before the plugin attributes are registered
952 // so we skip this then
954 gate_feature!(self, custom_attribute, attr.span,
955 &format!("The attribute `{}` is currently \
956 unknown to the compiler and \
958 added to it in the future",
965 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
966 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
967 cx.check_attribute(attr, true);
970 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
971 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
974 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
975 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
977 // FIXME (#28244): enforce that active features have issue numbers
978 // assert!(issue.is_some())
981 // search in Accepted, Removed, or Stable Removed features
982 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
983 .find(|t| t.0 == feature);
985 Some(&(_, _, issue)) => issue,
986 None => panic!("Feature `{}` is not declared anywhere", feature),
996 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
998 feature_err(sess, feature, span, issue, explain).emit();
1001 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1002 explain: &str) -> DiagnosticBuilder<'a> {
1003 let diag = &sess.span_diagnostic;
1005 let issue = match issue {
1006 GateIssue::Language => find_lang_feature_issue(feature),
1007 GateIssue::Library(lib) => lib,
1010 let mut err = if let Some(n) = issue {
1011 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
1013 diag.struct_span_err(span, explain)
1016 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1017 if sess.unstable_features.is_nightly_build() {
1018 err.help(&format!("add #![feature({})] to the \
1019 crate attributes to enable",
1026 const EXPLAIN_BOX_SYNTAX: &'static str =
1027 "box expression syntax is experimental; you can call `Box::new` instead.";
1029 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1030 "attributes on non-item statements and expressions are experimental.";
1032 pub const EXPLAIN_ASM: &'static str =
1033 "inline assembly is not stable enough for use and is subject to change";
1035 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1036 "`global_asm!` is not stable enough for use and is subject to change";
1038 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1039 "`log_syntax!` is not stable enough for use and is subject to change";
1041 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1042 "`concat_idents` is not stable enough for use and is subject to change";
1044 pub const EXPLAIN_TRACE_MACROS: &'static str =
1045 "`trace_macros` is not stable enough for use and is subject to change";
1046 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1047 "allow_internal_unstable side-steps feature gating and stability checks";
1049 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1050 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1052 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1053 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1054 Prefer using procedural macro custom derive.";
1056 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1057 "attributes of the form `#[derive_*]` are reserved for the compiler";
1059 pub const EXPLAIN_VIS_MATCHER: &'static str =
1060 ":vis fragment specifier is experimental and subject to change";
1062 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1063 "placement-in expression syntax is experimental and subject to change.";
1065 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1066 "Unsized tuple coercion is not stable enough for use and is subject to change";
1068 struct PostExpansionVisitor<'a> {
1069 context: &'a Context<'a>,
1072 macro_rules! gate_feature_post {
1073 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1074 let (cx, span) = ($cx, $span);
1075 if !span.allows_unstable() {
1076 gate_feature!(cx.context, $feature, span, $explain)
1081 impl<'a> PostExpansionVisitor<'a> {
1082 fn check_abi(&self, abi: Abi, span: Span) {
1084 Abi::RustIntrinsic => {
1085 gate_feature_post!(&self, intrinsics, span,
1086 "intrinsics are subject to change");
1088 Abi::PlatformIntrinsic => {
1089 gate_feature_post!(&self, platform_intrinsics, span,
1090 "platform intrinsics are experimental and possibly buggy");
1092 Abi::Vectorcall => {
1093 gate_feature_post!(&self, abi_vectorcall, span,
1094 "vectorcall is experimental and subject to change");
1097 gate_feature_post!(&self, abi_thiscall, span,
1098 "thiscall is experimental and subject to change");
1101 gate_feature_post!(&self, unboxed_closures, span,
1102 "rust-call ABI is subject to change");
1105 gate_feature_post!(&self, abi_sysv64, span,
1106 "sysv64 ABI is experimental and subject to change");
1109 gate_feature_post!(&self, abi_ptx, span,
1110 "PTX ABIs are experimental and subject to change");
1112 Abi::Unadjusted => {
1113 gate_feature_post!(&self, abi_unadjusted, span,
1114 "unadjusted ABI is an implementation detail and perma-unstable");
1116 Abi::Msp430Interrupt => {
1117 gate_feature_post!(&self, abi_msp430_interrupt, span,
1118 "msp430-interrupt ABI is experimental and subject to change");
1120 Abi::X86Interrupt => {
1121 gate_feature_post!(&self, abi_x86_interrupt, span,
1122 "x86-interrupt ABI is experimental and subject to change");
1137 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1138 use ast::MetaItemKind::*;
1139 use ast::NestedMetaItemKind::*;
1143 NameValue(ref lit) => !lit.node.is_str(),
1144 List(ref list) => list.iter().any(|li| {
1146 MetaItem(ref mi) => contains_novel_literal(mi),
1153 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1154 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1155 if !attr.span.allows_unstable() {
1156 // check for gated attributes
1157 self.context.check_attribute(attr, false);
1160 if self.context.features.proc_macro && attr::is_known(attr) {
1164 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1165 if contains_novel_literal(&meta) {
1166 gate_feature_post!(&self, attr_literals, attr.span,
1167 "non-string literals in attributes, or string \
1168 literals in top-level positions, are experimental");
1172 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1173 if !name.as_str().is_ascii() {
1174 gate_feature_post!(&self, non_ascii_idents, sp,
1175 "non-ascii idents are not fully supported.");
1179 fn visit_item(&mut self, i: &'a ast::Item) {
1181 ast::ItemKind::ExternCrate(_) => {
1182 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1183 gate_feature_post!(&self, macro_reexport, i.span,
1184 "macros reexports are experimental \
1185 and possibly buggy");
1189 ast::ItemKind::ForeignMod(ref foreign_module) => {
1190 self.check_abi(foreign_module.abi, i.span);
1193 ast::ItemKind::Fn(..) => {
1194 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1195 gate_feature_post!(&self, plugin_registrar, i.span,
1196 "compiler plugins are experimental and possibly buggy");
1198 if attr::contains_name(&i.attrs[..], "start") {
1199 gate_feature_post!(&self, start, i.span,
1200 "a #[start] function is an experimental \
1201 feature whose signature may change \
1204 if attr::contains_name(&i.attrs[..], "main") {
1205 gate_feature_post!(&self, main, i.span,
1206 "declaration of a nonstandard #[main] \
1207 function may change over time, for now \
1208 a top-level `fn main()` is required");
1212 ast::ItemKind::Struct(..) => {
1213 if attr::contains_name(&i.attrs[..], "simd") {
1214 gate_feature_post!(&self, simd, i.span,
1215 "SIMD types are experimental and possibly buggy");
1216 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1217 "the `#[simd]` attribute \
1218 is deprecated, use \
1219 `#[repr(simd)]` instead");
1221 for attr in &i.attrs {
1222 if attr.path == "repr" {
1223 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1224 if item.check_name("simd") {
1225 gate_feature_post!(&self, repr_simd, i.span,
1226 "SIMD types are experimental \
1227 and possibly buggy");
1230 if item.check_name("align") {
1231 gate_feature_post!(&self, repr_align, i.span,
1232 "the struct `#[repr(align(u16))]` attribute \
1240 ast::ItemKind::DefaultImpl(..) => {
1241 gate_feature_post!(&self, optin_builtin_traits,
1243 "default trait implementations are experimental \
1244 and possibly buggy");
1247 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1248 if polarity == ast::ImplPolarity::Negative {
1249 gate_feature_post!(&self, optin_builtin_traits,
1251 "negative trait bounds are not yet fully implemented; \
1252 use marker types for now");
1255 if let ast::Defaultness::Default = defaultness {
1256 gate_feature_post!(&self, specialization,
1258 "specialization is unstable");
1262 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1263 let msg = "`macro` is experimental";
1264 gate_feature_post!(&self, decl_macro, i.span, msg);
1270 visit::walk_item(self, i);
1273 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1274 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1275 Some(val) => val.as_str().starts_with("llvm."),
1279 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1280 "linking to LLVM intrinsics is experimental");
1283 visit::walk_foreign_item(self, i)
1286 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1288 ast::TyKind::BareFn(ref bare_fn_ty) => {
1289 self.check_abi(bare_fn_ty.abi, ty.span);
1291 ast::TyKind::ImplTrait(..) => {
1292 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1293 "`impl Trait` is experimental");
1295 ast::TyKind::Never => {
1296 gate_feature_post!(&self, never_type, ty.span,
1297 "The `!` type is experimental");
1301 visit::walk_ty(self, ty)
1304 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1305 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1306 if output_ty.node != ast::TyKind::Never {
1307 self.visit_ty(output_ty)
1312 fn visit_expr(&mut self, e: &'a ast::Expr) {
1314 ast::ExprKind::Box(_) => {
1315 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1317 ast::ExprKind::Type(..) => {
1318 gate_feature_post!(&self, type_ascription, e.span,
1319 "type ascription is experimental");
1321 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1322 gate_feature_post!(&self, inclusive_range_syntax,
1324 "inclusive range syntax is experimental");
1326 ast::ExprKind::InPlace(..) => {
1327 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1329 ast::ExprKind::Lit(ref lit) => {
1330 if let ast::LitKind::Int(_, ref ty) = lit.node {
1332 ast::LitIntType::Signed(ast::IntTy::I128) |
1333 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1334 gate_feature_post!(&self, i128_type, e.span,
1335 "128-bit integers are not stable");
1341 ast::ExprKind::Catch(_) => {
1342 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1346 visit::walk_expr(self, e);
1349 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1350 match pattern.node {
1351 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1352 gate_feature_post!(&self, advanced_slice_patterns,
1354 "multiple-element slice matches anywhere \
1355 but at the end of a slice (e.g. \
1356 `[0, ..xs, 0]`) are experimental")
1358 PatKind::Slice(..) => {
1359 gate_feature_post!(&self, slice_patterns,
1361 "slice pattern syntax is experimental");
1363 PatKind::Box(..) => {
1364 gate_feature_post!(&self, box_patterns,
1366 "box pattern syntax is experimental");
1368 PatKind::Range(_, _, RangeEnd::Excluded) => {
1369 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1370 "exclusive range pattern syntax is experimental");
1374 visit::walk_pat(self, pattern)
1377 fn visit_fn(&mut self,
1378 fn_kind: FnKind<'a>,
1379 fn_decl: &'a ast::FnDecl,
1382 // check for const fn declarations
1383 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1385 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1387 // stability of const fn methods are covered in
1388 // visit_trait_item and visit_impl_item below; this is
1389 // because default methods don't pass through this
1393 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1394 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1395 self.check_abi(abi, span);
1399 visit::walk_fn(self, fn_kind, fn_decl, span);
1402 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1404 ast::TraitItemKind::Method(ref sig, ref block) => {
1405 if block.is_none() {
1406 self.check_abi(sig.abi, ti.span);
1408 if sig.constness.node == ast::Constness::Const {
1409 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1412 ast::TraitItemKind::Type(_, Some(_)) => {
1413 gate_feature_post!(&self, associated_type_defaults, ti.span,
1414 "associated type defaults are unstable");
1418 visit::walk_trait_item(self, ti);
1421 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1422 if ii.defaultness == ast::Defaultness::Default {
1423 gate_feature_post!(&self, specialization,
1425 "specialization is unstable");
1429 ast::ImplItemKind::Method(ref sig, _) => {
1430 if sig.constness.node == ast::Constness::Const {
1431 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1436 visit::walk_impl_item(self, ii);
1439 fn visit_generics(&mut self, g: &'a ast::Generics) {
1440 for t in &g.ty_params {
1441 if !t.attrs.is_empty() {
1442 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1443 "attributes on type parameter bindings are experimental");
1446 visit::walk_generics(self, g)
1449 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1450 if !lifetime_def.attrs.is_empty() {
1451 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1452 "attributes on lifetime bindings are experimental");
1454 visit::walk_lifetime_def(self, lifetime_def)
1458 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1459 let mut features = Features::new();
1461 let mut feature_checker = MutexFeatureChecker::default();
1463 for attr in krate_attrs {
1464 if !attr.check_name("feature") {
1468 match attr.meta_item_list() {
1470 span_err!(span_handler, attr.span, E0555,
1471 "malformed feature attribute, expected #![feature(...)]");
1475 let name = if let Some(word) = mi.word() {
1478 span_err!(span_handler, mi.span, E0556,
1479 "malformed feature, expected just one word");
1483 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1484 .find(|& &(n, _, _, _)| name == n) {
1485 set(&mut features, mi.span);
1486 feature_checker.collect(&features, mi.span);
1488 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1489 .find(|& &(n, _, _)| name == n)
1490 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1491 .find(|& &(n, _, _)| name == n)) {
1492 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1494 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1495 .find(|& &(n, _, _)| name == n) {
1496 features.declared_stable_lang_features.push((name, mi.span));
1498 features.declared_lib_features.push((name, mi.span));
1505 feature_checker.check(span_handler);
1510 // A collector for mutually-exclusive features and their flag spans
1512 struct MutexFeatureChecker {
1513 proc_macro: Option<Span>,
1514 custom_attribute: Option<Span>,
1517 impl MutexFeatureChecker {
1518 // If this method turns out to be a hotspot due to branching,
1519 // the branching can be eliminated by modifying `set!()` to set these spans
1520 // only for the features that need to be checked for mutual exclusion.
1521 fn collect(&mut self, features: &Features, span: Span) {
1522 if features.proc_macro {
1523 // If self.proc_macro is None, set to Some(span)
1524 self.proc_macro = self.proc_macro.or(Some(span));
1527 if features.custom_attribute {
1528 self.custom_attribute = self.custom_attribute.or(Some(span));
1532 fn check(self, handler: &Handler) {
1533 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1534 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1535 `#![feature(custom_attribute)] at the same time")
1536 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1544 pub fn check_crate(krate: &ast::Crate,
1546 features: &Features,
1547 plugin_attributes: &[(String, AttributeType)],
1548 unstable: UnstableFeatures) {
1549 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1553 plugin_attributes: plugin_attributes,
1555 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1558 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1559 pub enum UnstableFeatures {
1560 /// Hard errors for unstable features are active, as on
1561 /// beta/stable channels.
1563 /// Allow features to be activated, as on nightly.
1565 /// Errors are bypassed for bootstrapping. This is required any time
1566 /// during the build that feature-related lints are set to warn or above
1567 /// because the build turns on warnings-as-errors and uses lots of unstable
1568 /// features. As a result, this is always required for building Rust itself.
1572 impl UnstableFeatures {
1573 pub fn from_environment() -> UnstableFeatures {
1574 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1575 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1576 // Whether we should enable unstable features for bootstrapping
1577 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1578 match (disable_unstable_features, bootstrap) {
1579 (_, true) => UnstableFeatures::Cheat,
1580 (true, _) => UnstableFeatures::Disallow,
1581 (false, _) => UnstableFeatures::Allow
1585 pub fn is_nightly_build(&self) -> bool {
1587 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1593 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1594 unstable: UnstableFeatures) {
1595 let allow_features = match unstable {
1596 UnstableFeatures::Allow => true,
1597 UnstableFeatures::Disallow => false,
1598 UnstableFeatures::Cheat => true
1600 if !allow_features {
1601 for attr in &krate.attrs {
1602 if attr.check_name("feature") {
1603 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1604 span_err!(span_handler, attr.span, E0554,
1605 "#![feature] may not be used on the {} release channel",