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) -> &mut bool {
46 f as fn(&mut Features) -> &mut bool
50 macro_rules! declare_features {
51 ($((active, $feature: ident, $ver: expr, $issue: expr),)+) => {
52 /// Represents active features that are currently being implemented or
53 /// currently being considered for addition/removal.
54 const ACTIVE_FEATURES: &'static [(&'static str, &'static str,
55 Option<u32>, fn(&mut Features) -> &mut bool)] = &[
56 $((stringify!($feature), $ver, $issue, setter!($feature))),+
59 /// A set of features to be used by later passes.
61 /// #![feature] attrs for stable language features, for error reporting
62 pub declared_stable_lang_features: Vec<(Symbol, Span)>,
63 /// #![feature] attrs for non-language (library) features
64 pub declared_lib_features: Vec<(Symbol, Span)>,
65 $(pub $feature: bool),+
69 pub fn new() -> Features {
71 declared_stable_lang_features: Vec::new(),
72 declared_lib_features: Vec::new(),
79 ($((removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
80 /// Represents unstable features which have since been removed (it was once Active)
81 const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
82 $((stringify!($feature), $ver, $issue)),+
86 ($((stable_removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
87 /// Represents stable features which have since been removed (it was once Accepted)
88 const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
89 $((stringify!($feature), $ver, $issue)),+
93 ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => {
94 /// Those language feature has since been Accepted (it was once Active)
95 const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
96 $((stringify!($feature), $ver, $issue)),+
101 // If you change this, please modify src/doc/unstable-book as well.
103 // Don't ever remove anything from this list; set them to 'Removed'.
105 // The version numbers here correspond to the version in which the current status
106 // was set. This is most important for knowing when a particular feature became
109 // NB: The featureck.py script parses this information directly out of the source
110 // so take care when modifying it.
113 (active, asm, "1.0.0", Some(29722)),
114 (active, concat_idents, "1.0.0", Some(29599)),
115 (active, link_args, "1.0.0", Some(29596)),
116 (active, log_syntax, "1.0.0", Some(29598)),
117 (active, non_ascii_idents, "1.0.0", Some(28979)),
118 (active, plugin_registrar, "1.0.0", Some(29597)),
119 (active, thread_local, "1.0.0", Some(29594)),
120 (active, trace_macros, "1.0.0", Some(29598)),
122 // rustc internal, for now:
123 (active, intrinsics, "1.0.0", None),
124 (active, lang_items, "1.0.0", None),
126 (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
127 (active, linkage, "1.0.0", Some(29603)),
128 (active, quote, "1.0.0", Some(29601)),
129 (active, simd, "1.0.0", Some(27731)),
133 (active, rustc_diagnostic_macros, "1.0.0", None),
134 (active, advanced_slice_patterns, "1.0.0", Some(23121)),
135 (active, box_syntax, "1.0.0", Some(27779)),
136 (active, placement_in_syntax, "1.0.0", Some(27779)),
137 (active, unboxed_closures, "1.0.0", Some(29625)),
139 (active, allocator, "1.0.0", Some(27389)),
140 (active, fundamental, "1.0.0", Some(29635)),
141 (active, main, "1.0.0", Some(29634)),
142 (active, needs_allocator, "1.4.0", Some(27389)),
143 (active, on_unimplemented, "1.0.0", Some(29628)),
144 (active, plugin, "1.0.0", Some(29597)),
145 (active, simd_ffi, "1.0.0", Some(27731)),
146 (active, start, "1.0.0", Some(29633)),
147 (active, structural_match, "1.8.0", Some(31434)),
148 (active, panic_runtime, "1.10.0", Some(32837)),
149 (active, needs_panic_runtime, "1.10.0", Some(32837)),
151 // OIBIT specific features
152 (active, optin_builtin_traits, "1.0.0", Some(13231)),
154 // macro reexport needs more discussion and stabilization
155 (active, macro_reexport, "1.0.0", Some(29638)),
157 // Allows use of #[staged_api]
159 (active, staged_api, "1.0.0", None),
161 // Allows using #![no_core]
162 (active, no_core, "1.3.0", Some(29639)),
164 // Allows using `box` in patterns; RFC 469
165 (active, box_patterns, "1.0.0", Some(29641)),
167 // Allows using the unsafe_destructor_blind_to_params attribute;
169 (active, dropck_parametricity, "1.3.0", Some(28498)),
171 // Allows using the may_dangle attribute; RFC 1327
172 (active, dropck_eyepatch, "1.10.0", Some(34761)),
174 // Allows the use of custom attributes; RFC 572
175 (active, custom_attribute, "1.0.0", Some(29642)),
177 // Allows the use of #[derive(Anything)] as sugar for
178 // #[derive_Anything].
179 (active, custom_derive, "1.0.0", Some(29644)),
181 // Allows the use of rustc_* attributes; RFC 572
182 (active, rustc_attrs, "1.0.0", Some(29642)),
184 // Allows the use of #[allow_internal_unstable]. This is an
185 // attribute on macro_rules! and can't use the attribute handling
186 // below (it has to be checked before expansion possibly makes
187 // macros disappear).
190 (active, allow_internal_unstable, "1.0.0", None),
192 // #23121. Array patterns have some hazards yet.
193 (active, slice_patterns, "1.0.0", Some(23121)),
195 // Allows the definition of associated constants in `trait` or `impl`
197 (active, associated_consts, "1.0.0", Some(29646)),
199 // Allows the definition of `const fn` functions.
200 (active, const_fn, "1.2.0", Some(24111)),
202 // Allows indexing into constant arrays.
203 (active, const_indexing, "1.4.0", Some(29947)),
205 // Allows using #[prelude_import] on glob `use` items.
208 (active, prelude_import, "1.2.0", None),
210 // Allows default type parameters to influence type inference.
211 (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
213 // Allows associated type defaults
214 (active, associated_type_defaults, "1.2.0", Some(29661)),
216 // allow `repr(simd)`, and importing the various simd intrinsics
217 (active, repr_simd, "1.4.0", Some(27731)),
219 // Allows cfg(target_feature = "...").
220 (active, cfg_target_feature, "1.4.0", Some(29717)),
222 // allow `extern "platform-intrinsic" { ... }`
223 (active, platform_intrinsics, "1.4.0", Some(27731)),
226 // rust runtime internal
227 (active, unwind_attributes, "1.4.0", None),
229 // allow the use of `#[naked]` on functions.
230 (active, naked_functions, "1.9.0", Some(32408)),
232 // allow `#[no_debug]`
233 (active, no_debug, "1.5.0", Some(29721)),
235 // allow `#[omit_gdb_pretty_printer_section]`
237 (active, omit_gdb_pretty_printer_section, "1.5.0", None),
239 // Allows cfg(target_vendor = "...").
240 (active, cfg_target_vendor, "1.5.0", Some(29718)),
242 // Allow attributes on expressions and non-item statements
243 (active, stmt_expr_attributes, "1.6.0", Some(15701)),
245 // allow using type ascription in expressions
246 (active, type_ascription, "1.6.0", Some(23416)),
248 // Allows cfg(target_thread_local)
249 (active, cfg_target_thread_local, "1.7.0", Some(29594)),
252 (active, abi_vectorcall, "1.7.0", None),
255 (active, inclusive_range_syntax, "1.7.0", Some(28237)),
258 (active, exclusive_range_pattern, "1.11.0", Some(37854)),
260 // impl specialization (RFC 1210)
261 (active, specialization, "1.7.0", Some(31844)),
263 // Allow Drop types in statics/const functions (RFC 1440)
264 (active, drop_types_in_const, "1.9.0", Some(33156)),
266 // Allows cfg(target_has_atomic = "...").
267 (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
269 // Allows `impl Trait` in function return types.
270 (active, conservative_impl_trait, "1.12.0", Some(34511)),
272 // Permits numeric fields in struct expressions and patterns.
273 (active, relaxed_adts, "1.12.0", Some(35626)),
276 (active, never_type, "1.13.0", Some(35121)),
278 // Allows all literals in attribute lists and values of key-value pairs.
279 (active, attr_literals, "1.13.0", Some(34981)),
281 // Allows the sysV64 ABI to be specified on all platforms
282 // instead of just the platforms on which it is the C ABI
283 (active, abi_sysv64, "1.13.0", Some(36167)),
285 // Allows untagged unions `union U { ... }`
286 (active, untagged_unions, "1.13.0", Some(32836)),
288 // Used to identify the `compiler_builtins` crate
290 (active, compiler_builtins, "1.13.0", None),
292 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
293 (active, generic_param_attrs, "1.11.0", Some(34761)),
295 // Allows #[link(..., cfg(..))]
296 (active, link_cfg, "1.14.0", Some(37406)),
298 (active, use_extern_macros, "1.15.0", Some(35896)),
300 // Allows `break {expr}` with a value inside `loop`s.
301 (active, loop_break_value, "1.14.0", Some(37339)),
303 // Allows #[target_feature(...)]
304 (active, target_feature, "1.15.0", None),
306 // `extern "ptx-*" fn()`
307 (active, abi_ptx, "1.15.0", None),
310 (active, i128_type, "1.16.0", Some(35118)),
312 // The `unadjusted` ABI. Perma unstable.
313 (active, abi_unadjusted, "1.16.0", None),
316 (active, proc_macro, "1.16.0", Some(38356)),
318 // Allows attributes on struct literal fields.
319 (active, struct_field_attributes, "1.16.0", Some(38814)),
321 // Allows #[link(kind="static-nobundle"...]
322 (active, static_nobundle, "1.16.0", Some(37403)),
324 // `extern "msp430-interrupt" fn()`
325 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
327 // Coerces non capturing closures to function pointers
328 (active, closure_to_fn_coercion, "1.17.0", Some(39817)),
330 // Used to identify crates that contain sanitizer runtimes
332 (active, sanitizer_runtime, "1.17.0", None),
334 // `extern "x86-interrupt" fn()`
335 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
338 // Allows the `catch {...}` expression
339 (active, catch_expr, "1.17.0", Some(31436)),
341 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
342 (active, rvalue_static_promotion, "1.15.1", Some(38865)),
344 // Used to preserve symbols (see llvm.used)
345 (active, used, "1.18.0", Some(40289)),
349 (removed, import_shadowing, "1.0.0", None),
350 (removed, managed_boxes, "1.0.0", None),
351 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
352 (removed, negate_unsigned, "1.0.0", Some(29645)),
353 (removed, reflect, "1.0.0", Some(27749)),
354 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
355 (removed, opt_out_copy, "1.0.0", None),
356 (removed, quad_precision_float, "1.0.0", None),
357 (removed, struct_inherit, "1.0.0", None),
358 (removed, test_removed_feature, "1.0.0", None),
359 (removed, visible_private_types, "1.0.0", None),
360 (removed, unsafe_no_drop_flag, "1.0.0", None),
361 // Allows using items which are missing stability attributes
363 (removed, unmarked_api, "1.0.0", None),
364 (removed, pushpop_unsafe, "1.2.0", None),
368 (stable_removed, no_stack_check, "1.0.0", None),
372 (accepted, associated_types, "1.0.0", None),
373 // allow overloading augmented assignment operations like `a += b`
374 (accepted, augmented_assignments, "1.8.0", Some(28235)),
375 // allow empty structs and enum variants with braces
376 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
377 (accepted, default_type_params, "1.0.0", None),
378 (accepted, globs, "1.0.0", None),
379 (accepted, if_let, "1.0.0", None),
380 // A temporary feature gate used to enable parser extensions needed
381 // to bootstrap fix for #5723.
382 (accepted, issue_5723_bootstrap, "1.0.0", None),
383 (accepted, macro_rules, "1.0.0", None),
384 // Allows using #![no_std]
385 (accepted, no_std, "1.6.0", None),
386 (accepted, slicing_syntax, "1.0.0", None),
387 (accepted, struct_variant, "1.0.0", None),
388 // These are used to test this portion of the compiler, they don't actually
390 (accepted, test_accepted_feature, "1.0.0", None),
391 (accepted, tuple_indexing, "1.0.0", None),
392 // Allows macros to appear in the type position.
393 (accepted, type_macros, "1.13.0", Some(27245)),
394 (accepted, while_let, "1.0.0", None),
395 // Allows `#[deprecated]` attribute
396 (accepted, deprecated, "1.9.0", Some(29935)),
398 (accepted, question_mark, "1.13.0", Some(31436)),
399 // Allows `..` in tuple (struct) patterns
400 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
401 (accepted, item_like_imports, "1.14.0", Some(35120)),
402 // Allows using `Self` and associated types in struct expressions and patterns.
403 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
404 // elide `'static` lifetimes in `static`s and `const`s
405 (accepted, static_in_const, "1.17.0", Some(35897)),
406 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
407 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
408 // Allows the definition recursive static items.
409 (accepted, static_recursion, "1.17.0", Some(29719)),
410 // pub(restricted) visibilities (RFC 1422)
411 (accepted, pub_restricted, "1.17.0", Some(32409)),
412 // The #![windows_subsystem] attribute
413 (accepted, windows_subsystem, "1.18.0", Some(37499)),
415 // If you change this, please modify src/doc/unstable-book as well. You must
416 // move that documentation into the relevant place in the other docs, and
417 // remove the chapter on the flag.
419 #[derive(PartialEq, Copy, Clone, Debug)]
420 pub enum AttributeType {
421 /// Normal, builtin attribute that is consumed
422 /// by the compiler before the unused_attribute check
425 /// Builtin attribute that may not be consumed by the compiler
426 /// before the unused_attribute check. These attributes
427 /// will be ignored by the unused_attribute lint
430 /// Builtin attribute that is only allowed at the crate level
434 pub enum AttributeGate {
435 /// Is gated by a given feature gate, reason
436 /// and function to check if enabled
437 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
439 /// Ungated attribute, can be used on all release channels
444 fn is_deprecated(&self) -> bool {
446 Gated(Stability::Deprecated(_), ..) => true,
452 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
455 // Argument is tracking issue link.
456 Deprecated(&'static str),
460 impl ::std::fmt::Debug for AttributeGate {
461 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
463 Gated(ref stab, ref name, ref expl, _) =>
464 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
465 Ungated => write!(fmt, "Ungated")
470 macro_rules! cfg_fn {
471 ($field: ident) => {{
472 fn f(features: &Features) -> bool {
475 f as fn(&Features) -> bool
479 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
480 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
483 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
484 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
487 // Attributes that have a special meaning to rustc or rustdoc
488 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
491 ("warn", Normal, Ungated),
492 ("allow", Normal, Ungated),
493 ("forbid", Normal, Ungated),
494 ("deny", Normal, Ungated),
496 ("macro_reexport", Normal, Ungated),
497 ("macro_use", Normal, Ungated),
498 ("macro_export", Normal, Ungated),
499 ("plugin_registrar", Normal, Ungated),
501 ("cfg", Normal, Ungated),
502 ("cfg_attr", Normal, Ungated),
503 ("main", Normal, Ungated),
504 ("start", Normal, Ungated),
505 ("test", Normal, Ungated),
506 ("bench", Normal, Ungated),
507 ("simd", Normal, Ungated),
508 ("repr", Normal, Ungated),
509 ("path", Normal, Ungated),
510 ("abi", Normal, Ungated),
511 ("automatically_derived", Normal, Ungated),
512 ("no_mangle", Normal, Ungated),
513 ("no_link", Normal, Ungated),
514 ("derive", Normal, Ungated),
515 ("should_panic", Normal, Ungated),
516 ("ignore", Normal, Ungated),
517 ("no_implicit_prelude", Normal, Ungated),
518 ("reexport_test_harness_main", Normal, Ungated),
519 ("link_args", Normal, Ungated),
520 ("macro_escape", Normal, Ungated),
523 ("structural_match", Whitelisted, Gated(Stability::Unstable,
525 "the semantics of constant patterns is \
527 cfg_fn!(structural_match))),
529 ("plugin", CrateLevel, Gated(Stability::Unstable,
531 "compiler plugins are experimental \
535 ("no_std", CrateLevel, Ungated),
536 ("no_core", CrateLevel, Gated(Stability::Unstable,
538 "no_core is experimental",
540 ("lang", Normal, Gated(Stability::Unstable,
542 "language items are subject to change",
543 cfg_fn!(lang_items))),
544 ("linkage", Whitelisted, Gated(Stability::Unstable,
546 "the `linkage` attribute is experimental \
547 and not portable across platforms",
549 ("thread_local", Whitelisted, Gated(Stability::Unstable,
551 "`#[thread_local]` is an experimental feature, and does \
552 not currently handle destructors. There is no \
553 corresponding `#[task_local]` mapping to the task \
555 cfg_fn!(thread_local))),
557 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
559 "the `#[rustc_on_unimplemented]` attribute \
560 is an experimental feature",
561 cfg_fn!(on_unimplemented))),
562 ("allocator", Whitelisted, Gated(Stability::Unstable,
564 "the `#[allocator]` attribute is an experimental feature",
565 cfg_fn!(allocator))),
566 ("needs_allocator", Normal, Gated(Stability::Unstable,
568 "the `#[needs_allocator]` \
569 attribute is an experimental \
571 cfg_fn!(needs_allocator))),
572 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
574 "the `#[panic_runtime]` attribute is \
575 an experimental feature",
576 cfg_fn!(panic_runtime))),
577 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
578 "needs_panic_runtime",
579 "the `#[needs_panic_runtime]` \
580 attribute is an experimental \
582 cfg_fn!(needs_panic_runtime))),
583 ("rustc_variance", Normal, Gated(Stability::Unstable,
585 "the `#[rustc_variance]` attribute \
586 is just used for rustc unit tests \
587 and will never be stable",
588 cfg_fn!(rustc_attrs))),
589 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
591 "the `#[rustc_error]` attribute \
592 is just used for rustc unit tests \
593 and will never be stable",
594 cfg_fn!(rustc_attrs))),
595 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
597 "the `#[rustc_if_this_changed]` attribute \
598 is just used for rustc unit tests \
599 and will never be stable",
600 cfg_fn!(rustc_attrs))),
601 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
603 "the `#[rustc_if_this_changed]` attribute \
604 is just used for rustc unit tests \
605 and will never be stable",
606 cfg_fn!(rustc_attrs))),
607 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
609 "the `#[rustc_dirty]` attribute \
610 is just used for rustc unit tests \
611 and will never be stable",
612 cfg_fn!(rustc_attrs))),
613 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
615 "the `#[rustc_clean]` attribute \
616 is just used for rustc unit tests \
617 and will never be stable",
618 cfg_fn!(rustc_attrs))),
619 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
621 "the `#[rustc_metadata_dirty]` attribute \
622 is just used for rustc unit tests \
623 and will never be stable",
624 cfg_fn!(rustc_attrs))),
625 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
627 "the `#[rustc_metadata_clean]` attribute \
628 is just used for rustc unit tests \
629 and will never be stable",
630 cfg_fn!(rustc_attrs))),
631 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
634 is just used for rustc unit tests \
635 and will never be stable",
636 cfg_fn!(rustc_attrs))),
637 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
640 is just used for rustc unit tests \
641 and will never be stable",
642 cfg_fn!(rustc_attrs))),
643 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
645 "internal rustc attributes will never be stable",
646 cfg_fn!(rustc_attrs))),
647 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
649 "internal rustc attributes will never be stable",
650 cfg_fn!(rustc_attrs))),
651 ("rustc_move_fragments", Normal, Gated(Stability::Unstable,
653 "the `#[rustc_move_fragments]` attribute \
654 is just used for rustc unit tests \
655 and will never be stable",
656 cfg_fn!(rustc_attrs))),
657 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
659 "the `#[rustc_mir]` attribute \
660 is just used for rustc unit tests \
661 and will never be stable",
662 cfg_fn!(rustc_attrs))),
663 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
665 "the `#[rustc_inherit_overflow_checks]` \
666 attribute is just used to control \
667 overflow checking behavior of several \
668 libcore functions that are inlined \
669 across crates and will never be stable",
670 cfg_fn!(rustc_attrs))),
671 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
673 "the `#[compiler_builtins]` attribute is used to \
674 identify the `compiler_builtins` crate which \
675 contains compiler-rt intrinsics and will never be \
677 cfg_fn!(compiler_builtins))),
678 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
680 "the `#[sanitizer_runtime]` attribute is used to \
681 identify crates that contain the runtime of a \
682 sanitizer and will never be stable",
683 cfg_fn!(sanitizer_runtime))),
685 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
686 "allow_internal_unstable",
687 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
688 cfg_fn!(allow_internal_unstable))),
690 ("fundamental", Whitelisted, Gated(Stability::Unstable,
692 "the `#[fundamental]` attribute \
693 is an experimental feature",
694 cfg_fn!(fundamental))),
696 ("proc_macro_derive", Normal, Ungated),
698 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
700 "internal implementation detail",
701 cfg_fn!(rustc_attrs))),
703 // FIXME: #14408 whitelist docs since rustdoc looks at them
704 ("doc", Whitelisted, Ungated),
706 // FIXME: #14406 these are processed in trans, which happens after the
708 ("cold", Whitelisted, Ungated),
709 ("naked", Whitelisted, Gated(Stability::Unstable,
711 "the `#[naked]` attribute \
712 is an experimental feature",
713 cfg_fn!(naked_functions))),
714 ("target_feature", Whitelisted, Gated(
715 Stability::Unstable, "target_feature",
716 "the `#[target_feature]` attribute is an experimental feature",
717 cfg_fn!(target_feature))),
718 ("export_name", Whitelisted, Ungated),
719 ("inline", Whitelisted, Ungated),
720 ("link", Whitelisted, Ungated),
721 ("link_name", Whitelisted, Ungated),
722 ("link_section", Whitelisted, Ungated),
723 ("no_builtins", Whitelisted, Ungated),
724 ("no_mangle", Whitelisted, Ungated),
725 ("no_debug", Whitelisted, Gated(
726 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
728 "the `#[no_debug]` attribute is an experimental feature",
730 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
731 "omit_gdb_pretty_printer_section",
732 "the `#[omit_gdb_pretty_printer_section]` \
733 attribute is just used for the Rust test \
735 cfg_fn!(omit_gdb_pretty_printer_section))),
736 ("unsafe_destructor_blind_to_params",
738 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
739 "dropck_parametricity",
740 "unsafe_destructor_blind_to_params has been replaced by \
741 may_dangle and will be removed in the future",
742 cfg_fn!(dropck_parametricity))),
745 Gated(Stability::Unstable,
747 "may_dangle has unstable semantics and may be removed in the future",
748 cfg_fn!(dropck_eyepatch))),
749 ("unwind", Whitelisted, Gated(Stability::Unstable,
751 "#[unwind] is experimental",
752 cfg_fn!(unwind_attributes))),
753 ("used", Whitelisted, Gated(
754 Stability::Unstable, "used",
755 "the `#[used]` attribute is an experimental feature",
759 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
761 "`#[prelude_import]` is for use by rustc only",
762 cfg_fn!(prelude_import))),
764 // FIXME: #14407 these are only looked at on-demand so we can't
765 // guarantee they'll have already been checked
766 ("rustc_deprecated", Whitelisted, Ungated),
767 ("must_use", Whitelisted, Ungated),
768 ("stable", Whitelisted, Ungated),
769 ("unstable", Whitelisted, Ungated),
770 ("deprecated", Normal, Ungated),
772 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
774 "unboxed_closures are still evolving",
775 cfg_fn!(unboxed_closures))),
777 ("windows_subsystem", Whitelisted, Ungated),
779 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
781 "attribute proc macros are currently unstable",
782 cfg_fn!(proc_macro))),
784 ("proc_macro", Normal, Gated(Stability::Unstable,
786 "function-like proc macros are currently unstable",
787 cfg_fn!(proc_macro))),
789 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
790 "rustc_derive_registrar",
791 "used internally by rustc",
792 cfg_fn!(rustc_attrs))),
794 // Crate level attributes
795 ("crate_name", CrateLevel, Ungated),
796 ("crate_type", CrateLevel, Ungated),
797 ("crate_id", CrateLevel, Ungated),
798 ("feature", CrateLevel, Ungated),
799 ("no_start", CrateLevel, Ungated),
800 ("no_main", CrateLevel, Ungated),
801 ("no_builtins", CrateLevel, Ungated),
802 ("recursion_limit", CrateLevel, Ungated),
803 ("type_length_limit", CrateLevel, Ungated),
806 // cfg(...)'s that are feature gated
807 const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] = &[
808 // (name in cfg, feature, function to check if the feature is enabled)
809 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
810 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
811 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
812 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
815 #[derive(Debug, Eq, PartialEq)]
816 pub struct GatedCfg {
822 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
823 let name = cfg.name().as_str();
825 .position(|info| info.0 == name)
834 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
835 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
836 if !has_feature(features) && !self.span.allows_unstable() {
837 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
838 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
844 features: &'a Features,
845 parse_sess: &'a ParseSess,
846 plugin_attributes: &'a [(String, AttributeType)],
849 macro_rules! gate_feature_fn {
850 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
851 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
852 let has_feature: bool = has_feature(&$cx.features);
853 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
854 if !has_feature && !span.allows_unstable() {
855 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
860 macro_rules! gate_feature {
861 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
862 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
866 impl<'a> Context<'a> {
867 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
868 debug!("check_attribute(attr = {:?})", attr);
869 let name = unwrap_or!(attr.name(), return).as_str();
870 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
872 if let &Gated(_, ref name, ref desc, ref has_feature) = gateage {
873 gate_feature_fn!(self, has_feature, attr.span, name, desc);
875 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
879 for &(ref n, ref ty) in self.plugin_attributes {
880 if attr.path == &**n {
881 // Plugins can't gate attributes, so we don't check for it
882 // unlike the code above; we only use this loop to
883 // short-circuit to avoid the checks below
884 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
888 if name.starts_with("rustc_") {
889 gate_feature!(self, rustc_attrs, attr.span,
890 "unless otherwise specified, attributes \
891 with the prefix `rustc_` \
892 are reserved for internal compiler diagnostics");
893 } else if name.starts_with("derive_") {
894 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
895 } else if !attr::is_known(attr) {
896 // Only run the custom attribute lint during regular
897 // feature gate checking. Macro gating runs
898 // before the plugin attributes are registered
899 // so we skip this then
901 gate_feature!(self, custom_attribute, attr.span,
902 &format!("The attribute `{}` is currently \
903 unknown to the compiler and \
905 added to it in the future",
912 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
913 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
914 cx.check_attribute(attr, true);
917 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
918 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
921 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
922 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
924 // FIXME (#28244): enforce that active features have issue numbers
925 // assert!(issue.is_some())
928 // search in Accepted, Removed, or Stable Removed features
929 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
930 .find(|t| t.0 == feature);
932 Some(&(_, _, issue)) => issue,
933 None => panic!("Feature `{}` is not declared anywhere", feature),
943 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
945 feature_err(sess, feature, span, issue, explain).emit();
948 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
949 explain: &str) -> DiagnosticBuilder<'a> {
950 let diag = &sess.span_diagnostic;
952 let issue = match issue {
953 GateIssue::Language => find_lang_feature_issue(feature),
954 GateIssue::Library(lib) => lib,
957 let mut err = if let Some(n) = issue {
958 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
960 diag.struct_span_err(span, explain)
963 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
964 if sess.unstable_features.is_nightly_build() {
965 err.help(&format!("add #![feature({})] to the \
966 crate attributes to enable",
973 const EXPLAIN_BOX_SYNTAX: &'static str =
974 "box expression syntax is experimental; you can call `Box::new` instead.";
976 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
977 "attributes on non-item statements and expressions are experimental.";
979 pub const EXPLAIN_ASM: &'static str =
980 "inline assembly is not stable enough for use and is subject to change";
982 pub const EXPLAIN_LOG_SYNTAX: &'static str =
983 "`log_syntax!` is not stable enough for use and is subject to change";
985 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
986 "`concat_idents` is not stable enough for use and is subject to change";
988 pub const EXPLAIN_TRACE_MACROS: &'static str =
989 "`trace_macros` is not stable enough for use and is subject to change";
990 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
991 "allow_internal_unstable side-steps feature gating and stability checks";
993 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
994 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
996 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
997 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
998 Prefer using procedural macro custom derive.";
1000 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1001 "attributes of the form `#[derive_*]` are reserved for the compiler";
1003 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1004 "placement-in expression syntax is experimental and subject to change.";
1006 pub const CLOSURE_TO_FN_COERCION: &'static str =
1007 "non-capturing closure to fn coercion is experimental";
1009 struct PostExpansionVisitor<'a> {
1010 context: &'a Context<'a>,
1013 macro_rules! gate_feature_post {
1014 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1015 let (cx, span) = ($cx, $span);
1016 if !span.allows_unstable() {
1017 gate_feature!(cx.context, $feature, span, $explain)
1022 impl<'a> PostExpansionVisitor<'a> {
1023 fn check_abi(&self, abi: Abi, span: Span) {
1025 Abi::RustIntrinsic => {
1026 gate_feature_post!(&self, intrinsics, span,
1027 "intrinsics are subject to change");
1029 Abi::PlatformIntrinsic => {
1030 gate_feature_post!(&self, platform_intrinsics, span,
1031 "platform intrinsics are experimental and possibly buggy");
1033 Abi::Vectorcall => {
1034 gate_feature_post!(&self, abi_vectorcall, span,
1035 "vectorcall is experimental and subject to change");
1038 gate_feature_post!(&self, unboxed_closures, span,
1039 "rust-call ABI is subject to change");
1042 gate_feature_post!(&self, abi_sysv64, span,
1043 "sysv64 ABI is experimental and subject to change");
1046 gate_feature_post!(&self, abi_ptx, span,
1047 "PTX ABIs are experimental and subject to change");
1049 Abi::Unadjusted => {
1050 gate_feature_post!(&self, abi_unadjusted, span,
1051 "unadjusted ABI is an implementation detail and perma-unstable");
1053 Abi::Msp430Interrupt => {
1054 gate_feature_post!(&self, abi_msp430_interrupt, span,
1055 "msp430-interrupt ABI is experimental and subject to change");
1057 Abi::X86Interrupt => {
1058 gate_feature_post!(&self, abi_x86_interrupt, span,
1059 "x86-interrupt ABI is experimental and subject to change");
1074 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1075 use ast::MetaItemKind::*;
1076 use ast::NestedMetaItemKind::*;
1080 NameValue(ref lit) => !lit.node.is_str(),
1081 List(ref list) => list.iter().any(|li| {
1083 MetaItem(ref mi) => contains_novel_literal(&mi),
1090 fn starts_with_digit(s: &str) -> bool {
1091 s.as_bytes().first().cloned().map_or(false, |b| b >= b'0' && b <= b'9')
1094 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1095 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1096 if !attr.span.allows_unstable() {
1097 // check for gated attributes
1098 self.context.check_attribute(attr, false);
1101 if self.context.features.proc_macro && attr::is_known(attr) {
1105 let meta = panictry!(attr.parse_meta(&self.context.parse_sess));
1106 if contains_novel_literal(&meta) {
1107 gate_feature_post!(&self, attr_literals, attr.span,
1108 "non-string literals in attributes, or string \
1109 literals in top-level positions, are experimental");
1113 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1114 if !name.as_str().is_ascii() {
1115 gate_feature_post!(&self, non_ascii_idents, sp,
1116 "non-ascii idents are not fully supported.");
1120 fn visit_item(&mut self, i: &'a ast::Item) {
1122 ast::ItemKind::ExternCrate(_) => {
1123 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1124 gate_feature_post!(&self, macro_reexport, i.span,
1125 "macros reexports are experimental \
1126 and possibly buggy");
1130 ast::ItemKind::ForeignMod(ref foreign_module) => {
1131 if attr::contains_name(&i.attrs[..], "link_args") {
1132 gate_feature_post!(&self, link_args, i.span,
1133 "the `link_args` attribute is not portable \
1134 across platforms, it is recommended to \
1135 use `#[link(name = \"foo\")]` instead")
1137 self.check_abi(foreign_module.abi, i.span);
1140 ast::ItemKind::Fn(..) => {
1141 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1142 gate_feature_post!(&self, plugin_registrar, i.span,
1143 "compiler plugins are experimental and possibly buggy");
1145 if attr::contains_name(&i.attrs[..], "start") {
1146 gate_feature_post!(&self, start, i.span,
1147 "a #[start] function is an experimental \
1148 feature whose signature may change \
1151 if attr::contains_name(&i.attrs[..], "main") {
1152 gate_feature_post!(&self, main, i.span,
1153 "declaration of a nonstandard #[main] \
1154 function may change over time, for now \
1155 a top-level `fn main()` is required");
1159 ast::ItemKind::Struct(..) => {
1160 if attr::contains_name(&i.attrs[..], "simd") {
1161 gate_feature_post!(&self, simd, i.span,
1162 "SIMD types are experimental and possibly buggy");
1163 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1164 "the `#[simd]` attribute \
1165 is deprecated, use \
1166 `#[repr(simd)]` instead");
1168 for attr in &i.attrs {
1169 if attr.path == "repr" {
1170 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1171 if item.check_name("simd") {
1172 gate_feature_post!(&self, repr_simd, i.span,
1173 "SIMD types are experimental \
1174 and possibly buggy");
1182 ast::ItemKind::Union(..) => {
1183 gate_feature_post!(&self, untagged_unions,
1185 "unions are unstable and possibly buggy");
1188 ast::ItemKind::DefaultImpl(..) => {
1189 gate_feature_post!(&self, optin_builtin_traits,
1191 "default trait implementations are experimental \
1192 and possibly buggy");
1195 ast::ItemKind::Impl(_, polarity, _, _, _, _) => {
1197 ast::ImplPolarity::Negative => {
1198 gate_feature_post!(&self, optin_builtin_traits,
1200 "negative trait bounds are not yet fully implemented; \
1201 use marker types for now");
1210 visit::walk_item(self, i);
1213 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1214 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1215 Some(val) => val.as_str().starts_with("llvm."),
1219 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1220 "linking to LLVM intrinsics is experimental");
1223 visit::walk_foreign_item(self, i)
1226 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1228 ast::TyKind::BareFn(ref bare_fn_ty) => {
1229 self.check_abi(bare_fn_ty.abi, ty.span);
1231 ast::TyKind::ImplTrait(..) => {
1232 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1233 "`impl Trait` is experimental");
1235 ast::TyKind::Never => {
1236 gate_feature_post!(&self, never_type, ty.span,
1237 "The `!` type is experimental");
1241 visit::walk_ty(self, ty)
1244 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1245 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1246 match output_ty.node {
1247 ast::TyKind::Never => return,
1250 self.visit_ty(output_ty)
1254 fn visit_expr(&mut self, e: &'a ast::Expr) {
1256 ast::ExprKind::Box(_) => {
1257 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1259 ast::ExprKind::Type(..) => {
1260 gate_feature_post!(&self, type_ascription, e.span,
1261 "type ascription is experimental");
1263 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1264 gate_feature_post!(&self, inclusive_range_syntax,
1266 "inclusive range syntax is experimental");
1268 ast::ExprKind::InPlace(..) => {
1269 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1271 ast::ExprKind::Struct(_, ref fields, _) => {
1272 for field in fields {
1273 if starts_with_digit(&field.ident.node.name.as_str()) {
1274 gate_feature_post!(&self, relaxed_adts,
1276 "numeric fields in struct expressions are unstable");
1280 ast::ExprKind::Break(_, Some(_)) => {
1281 gate_feature_post!(&self, loop_break_value, e.span,
1282 "`break` with a value is experimental");
1284 ast::ExprKind::Lit(ref lit) => {
1285 if let ast::LitKind::Int(_, ref ty) = lit.node {
1287 ast::LitIntType::Signed(ast::IntTy::I128) |
1288 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1289 gate_feature_post!(&self, i128_type, e.span,
1290 "128-bit integers are not stable");
1296 ast::ExprKind::Catch(_) => {
1297 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1301 visit::walk_expr(self, e);
1304 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1305 match pattern.node {
1306 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1307 gate_feature_post!(&self, advanced_slice_patterns,
1309 "multiple-element slice matches anywhere \
1310 but at the end of a slice (e.g. \
1311 `[0, ..xs, 0]`) are experimental")
1313 PatKind::Slice(..) => {
1314 gate_feature_post!(&self, slice_patterns,
1316 "slice pattern syntax is experimental");
1318 PatKind::Box(..) => {
1319 gate_feature_post!(&self, box_patterns,
1321 "box pattern syntax is experimental");
1323 PatKind::Struct(_, ref fields, _) => {
1324 for field in fields {
1325 if starts_with_digit(&field.node.ident.name.as_str()) {
1326 gate_feature_post!(&self, relaxed_adts,
1328 "numeric fields in struct patterns are unstable");
1332 PatKind::Range(_, _, RangeEnd::Excluded) => {
1333 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1334 "exclusive range pattern syntax is experimental");
1338 visit::walk_pat(self, pattern)
1341 fn visit_fn(&mut self,
1342 fn_kind: FnKind<'a>,
1343 fn_decl: &'a ast::FnDecl,
1346 // check for const fn declarations
1348 FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) => {
1349 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1352 // stability of const fn methods are covered in
1353 // visit_trait_item and visit_impl_item below; this is
1354 // because default methods don't pass through this
1360 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1361 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1362 self.check_abi(abi, span);
1366 visit::walk_fn(self, fn_kind, fn_decl, span);
1369 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1371 ast::TraitItemKind::Const(..) => {
1372 gate_feature_post!(&self, associated_consts,
1374 "associated constants are experimental")
1376 ast::TraitItemKind::Method(ref sig, ref block) => {
1377 if block.is_none() {
1378 self.check_abi(sig.abi, ti.span);
1380 if sig.constness.node == ast::Constness::Const {
1381 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1384 ast::TraitItemKind::Type(_, Some(_)) => {
1385 gate_feature_post!(&self, associated_type_defaults, ti.span,
1386 "associated type defaults are unstable");
1390 visit::walk_trait_item(self, ti);
1393 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1394 if ii.defaultness == ast::Defaultness::Default {
1395 gate_feature_post!(&self, specialization,
1397 "specialization is unstable");
1401 ast::ImplItemKind::Const(..) => {
1402 gate_feature_post!(&self, associated_consts,
1404 "associated constants are experimental")
1406 ast::ImplItemKind::Method(ref sig, _) => {
1407 if sig.constness.node == ast::Constness::Const {
1408 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1413 visit::walk_impl_item(self, ii);
1416 fn visit_generics(&mut self, g: &'a ast::Generics) {
1417 for t in &g.ty_params {
1418 if !t.attrs.is_empty() {
1419 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1420 "attributes on type parameter bindings are experimental");
1423 visit::walk_generics(self, g)
1426 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1427 if !lifetime_def.attrs.is_empty() {
1428 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1429 "attributes on lifetime bindings are experimental");
1431 visit::walk_lifetime_def(self, lifetime_def)
1435 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1436 let mut features = Features::new();
1438 let mut feature_checker = MutexFeatureChecker::default();
1440 for attr in krate_attrs {
1441 if !attr.check_name("feature") {
1445 match attr.meta_item_list() {
1447 span_err!(span_handler, attr.span, E0555,
1448 "malformed feature attribute, expected #![feature(...)]");
1452 let name = if let Some(word) = mi.word() {
1455 span_err!(span_handler, mi.span, E0556,
1456 "malformed feature, expected just one word");
1460 if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
1461 .find(|& &(n, _, _, _)| name == n) {
1462 *(setter(&mut features)) = true;
1463 feature_checker.collect(&features, mi.span);
1465 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1466 .find(|& &(n, _, _)| name == n)
1467 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1468 .find(|& &(n, _, _)| name == n)) {
1469 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1471 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1472 .find(|& &(n, _, _)| name == n) {
1473 features.declared_stable_lang_features.push((name, mi.span));
1475 features.declared_lib_features.push((name, mi.span));
1482 feature_checker.check(span_handler);
1487 // A collector for mutually-exclusive features and their flag spans
1489 struct MutexFeatureChecker {
1490 proc_macro: Option<Span>,
1491 custom_attribute: Option<Span>,
1494 impl MutexFeatureChecker {
1495 // If this method turns out to be a hotspot due to branching,
1496 // the branching can be eliminated by modifying `setter!()` to set these spans
1497 // only for the features that need to be checked for mutual exclusion.
1498 fn collect(&mut self, features: &Features, span: Span) {
1499 if features.proc_macro {
1500 // If self.proc_macro is None, set to Some(span)
1501 self.proc_macro = self.proc_macro.or(Some(span));
1504 if features.custom_attribute {
1505 self.custom_attribute = self.custom_attribute.or(Some(span));
1509 fn check(self, handler: &Handler) {
1510 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1511 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1512 `#![feature(custom_attribute)] at the same time")
1513 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1521 pub fn check_crate(krate: &ast::Crate,
1523 features: &Features,
1524 plugin_attributes: &[(String, AttributeType)],
1525 unstable: UnstableFeatures) {
1526 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1530 plugin_attributes: plugin_attributes,
1532 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1535 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1536 pub enum UnstableFeatures {
1537 /// Hard errors for unstable features are active, as on
1538 /// beta/stable channels.
1540 /// Allow features to be activated, as on nightly.
1542 /// Errors are bypassed for bootstrapping. This is required any time
1543 /// during the build that feature-related lints are set to warn or above
1544 /// because the build turns on warnings-as-errors and uses lots of unstable
1545 /// features. As a result, this is always required for building Rust itself.
1549 impl UnstableFeatures {
1550 pub fn from_environment() -> UnstableFeatures {
1551 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1552 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1553 // Whether we should enable unstable features for bootstrapping
1554 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1555 match (disable_unstable_features, bootstrap) {
1556 (_, true) => UnstableFeatures::Cheat,
1557 (true, _) => UnstableFeatures::Disallow,
1558 (false, _) => UnstableFeatures::Allow
1562 pub fn is_nightly_build(&self) -> bool {
1564 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1570 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1571 unstable: UnstableFeatures) {
1572 let allow_features = match unstable {
1573 UnstableFeatures::Allow => true,
1574 UnstableFeatures::Disallow => false,
1575 UnstableFeatures::Cheat => true
1577 if !allow_features {
1578 for attr in &krate.attrs {
1579 if attr.check_name("feature") {
1580 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1581 span_err!(span_handler, attr.span, E0554,
1582 "#[feature] may not be used on the {} release channel",