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};
31 use codemap::{CodeMap, Spanned};
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 features which has since been removed (it was once Active)
81 const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
82 $((stringify!($feature), $ver, $issue)),+
86 ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => {
87 /// Those language feature has since been Accepted (it was once Active)
88 const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
89 $((stringify!($feature), $ver, $issue)),+
94 // If you change this list without updating src/doc/reference.md, @cmr will be sad
95 // Don't ever remove anything from this list; set them to 'Removed'.
96 // The version numbers here correspond to the version in which the current status
97 // was set. This is most important for knowing when a particular feature became
99 // NB: The featureck.py script parses this information directly out of the source
100 // so take care when modifying it.
103 (active, asm, "1.0.0", Some(29722)),
104 (active, concat_idents, "1.0.0", Some(29599)),
105 (active, link_args, "1.0.0", Some(29596)),
106 (active, log_syntax, "1.0.0", Some(29598)),
107 (active, non_ascii_idents, "1.0.0", Some(28979)),
108 (active, plugin_registrar, "1.0.0", Some(29597)),
109 (active, thread_local, "1.0.0", Some(29594)),
110 (active, trace_macros, "1.0.0", Some(29598)),
112 // rustc internal, for now:
113 (active, intrinsics, "1.0.0", None),
114 (active, lang_items, "1.0.0", None),
116 (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
117 (active, linkage, "1.0.0", Some(29603)),
118 (active, quote, "1.0.0", Some(29601)),
119 (active, simd, "1.0.0", Some(27731)),
123 (active, rustc_diagnostic_macros, "1.0.0", None),
124 (active, advanced_slice_patterns, "1.0.0", Some(23121)),
125 (active, box_syntax, "1.0.0", Some(27779)),
126 (active, placement_in_syntax, "1.0.0", Some(27779)),
127 (active, unboxed_closures, "1.0.0", Some(29625)),
129 (active, allocator, "1.0.0", Some(27389)),
130 (active, fundamental, "1.0.0", Some(29635)),
131 (active, main, "1.0.0", Some(29634)),
132 (active, needs_allocator, "1.4.0", Some(27389)),
133 (active, on_unimplemented, "1.0.0", Some(29628)),
134 (active, plugin, "1.0.0", Some(29597)),
135 (active, simd_ffi, "1.0.0", Some(27731)),
136 (active, start, "1.0.0", Some(29633)),
137 (active, structural_match, "1.8.0", Some(31434)),
138 (active, panic_runtime, "1.10.0", Some(32837)),
139 (active, needs_panic_runtime, "1.10.0", Some(32837)),
141 // OIBIT specific features
142 (active, optin_builtin_traits, "1.0.0", Some(13231)),
144 // macro reexport needs more discussion and stabilization
145 (active, macro_reexport, "1.0.0", Some(29638)),
147 // Allows use of #[staged_api]
149 (active, staged_api, "1.0.0", None),
151 // Allows using #![no_core]
152 (active, no_core, "1.3.0", Some(29639)),
154 // Allows using `box` in patterns; RFC 469
155 (active, box_patterns, "1.0.0", Some(29641)),
157 // Allows using the unsafe_destructor_blind_to_params attribute;
159 (active, dropck_parametricity, "1.3.0", Some(28498)),
161 // Allows using the may_dangle attribute; RFC 1327
162 (active, dropck_eyepatch, "1.10.0", Some(34761)),
164 // Allows the use of custom attributes; RFC 572
165 (active, custom_attribute, "1.0.0", Some(29642)),
167 // Allows the use of #[derive(Anything)] as sugar for
168 // #[derive_Anything].
169 (active, custom_derive, "1.0.0", Some(29644)),
171 // Allows the use of rustc_* attributes; RFC 572
172 (active, rustc_attrs, "1.0.0", Some(29642)),
174 // Allows the use of #[allow_internal_unstable]. This is an
175 // attribute on macro_rules! and can't use the attribute handling
176 // below (it has to be checked before expansion possibly makes
177 // macros disappear).
180 (active, allow_internal_unstable, "1.0.0", None),
182 // #23121. Array patterns have some hazards yet.
183 (active, slice_patterns, "1.0.0", Some(23121)),
185 // Allows the definition of associated constants in `trait` or `impl`
187 (active, associated_consts, "1.0.0", Some(29646)),
189 // Allows the definition of `const fn` functions.
190 (active, const_fn, "1.2.0", Some(24111)),
192 // Allows indexing into constant arrays.
193 (active, const_indexing, "1.4.0", Some(29947)),
195 // Allows using #[prelude_import] on glob `use` items.
198 (active, prelude_import, "1.2.0", None),
200 // Allows the definition recursive static items.
201 (active, static_recursion, "1.3.0", Some(29719)),
203 // Allows default type parameters to influence type inference.
204 (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
206 // Allows associated type defaults
207 (active, associated_type_defaults, "1.2.0", Some(29661)),
209 // allow `repr(simd)`, and importing the various simd intrinsics
210 (active, repr_simd, "1.4.0", Some(27731)),
212 // Allows cfg(target_feature = "...").
213 (active, cfg_target_feature, "1.4.0", Some(29717)),
215 // allow `extern "platform-intrinsic" { ... }`
216 (active, platform_intrinsics, "1.4.0", Some(27731)),
219 // rust runtime internal
220 (active, unwind_attributes, "1.4.0", None),
222 // allow the use of `#[naked]` on functions.
223 (active, naked_functions, "1.9.0", Some(32408)),
225 // allow `#[no_debug]`
226 (active, no_debug, "1.5.0", Some(29721)),
228 // allow `#[omit_gdb_pretty_printer_section]`
230 (active, omit_gdb_pretty_printer_section, "1.5.0", None),
232 // Allows cfg(target_vendor = "...").
233 (active, cfg_target_vendor, "1.5.0", Some(29718)),
235 // Allow attributes on expressions and non-item statements
236 (active, stmt_expr_attributes, "1.6.0", Some(15701)),
238 // allow using type ascription in expressions
239 (active, type_ascription, "1.6.0", Some(23416)),
241 // Allows cfg(target_thread_local)
242 (active, cfg_target_thread_local, "1.7.0", Some(29594)),
245 (active, abi_vectorcall, "1.7.0", None),
248 (active, inclusive_range_syntax, "1.7.0", Some(28237)),
251 (active, exclusive_range_pattern, "1.11.0", Some(37854)),
253 // impl specialization (RFC 1210)
254 (active, specialization, "1.7.0", Some(31844)),
256 // pub(restricted) visibilities (RFC 1422)
257 (active, pub_restricted, "1.9.0", Some(32409)),
259 // Allow Drop types in statics/const functions (RFC 1440)
260 (active, drop_types_in_const, "1.9.0", Some(33156)),
262 // Allows cfg(target_has_atomic = "...").
263 (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
265 // Allows `impl Trait` in function return types.
266 (active, conservative_impl_trait, "1.12.0", Some(34511)),
268 // Permits numeric fields in struct expressions and patterns.
269 (active, relaxed_adts, "1.12.0", Some(35626)),
272 (active, never_type, "1.13.0", Some(35121)),
274 // Allows all literals in attribute lists and values of key-value pairs.
275 (active, attr_literals, "1.13.0", Some(34981)),
277 // Allows the sysV64 ABI to be specified on all platforms
278 // instead of just the platforms on which it is the C ABI
279 (active, abi_sysv64, "1.13.0", Some(36167)),
281 // Allows untagged unions `union U { ... }`
282 (active, untagged_unions, "1.13.0", Some(32836)),
284 // Used to identify the `compiler_builtins` crate
286 (active, compiler_builtins, "1.13.0", None),
288 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
289 (active, generic_param_attrs, "1.11.0", Some(34761)),
291 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
292 (active, field_init_shorthand, "1.14.0", Some(37340)),
294 // The #![windows_subsystem] attribute
295 (active, windows_subsystem, "1.14.0", Some(37499)),
297 // Allows #[link(..., cfg(..))]
298 (active, link_cfg, "1.14.0", Some(37406)),
300 (active, use_extern_macros, "1.15.0", Some(35896)),
302 // Allows `break {expr}` with a value inside `loop`s.
303 (active, loop_break_value, "1.14.0", Some(37339)),
305 // Allows #[target_feature(...)]
306 (active, target_feature, "1.15.0", None),
308 // `extern "ptx-*" fn()`
309 (active, abi_ptx, "1.15.0", None),
312 (active, i128_type, "1.16.0", Some(35118)),
314 // The `unadjusted` ABI. Perma unstable.
315 (active, abi_unadjusted, "1.16.0", None),
318 (active, proc_macro, "1.16.0", Some(38356)),
320 // Allows attributes on struct literal fields.
321 (active, struct_field_attributes, "1.16.0", Some(38814)),
323 // Allows #[link(kind="static-nobundle"...]
324 (active, static_nobundle, "1.16.0", Some(37403)),
326 // `extern "msp430-interrupt" fn()`
327 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
329 // Used to identify crates that contain sanitizer runtimes
331 (active, sanitizer_runtime, "1.17.0", None),
335 (removed, import_shadowing, "1.0.0", None),
336 (removed, managed_boxes, "1.0.0", None),
337 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
338 (removed, negate_unsigned, "1.0.0", Some(29645)),
339 (removed, reflect, "1.0.0", Some(27749)),
340 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
341 (removed, opt_out_copy, "1.0.0", None),
342 (removed, quad_precision_float, "1.0.0", None),
343 (removed, struct_inherit, "1.0.0", None),
344 (removed, test_removed_feature, "1.0.0", None),
345 (removed, visible_private_types, "1.0.0", None),
346 (removed, unsafe_no_drop_flag, "1.0.0", None),
347 // Allows using items which are missing stability attributes
349 (removed, unmarked_api, "1.0.0", None),
350 (removed, pushpop_unsafe, "1.2.0", None),
354 (accepted, associated_types, "1.0.0", None),
355 // allow overloading augmented assignment operations like `a += b`
356 (accepted, augmented_assignments, "1.8.0", Some(28235)),
357 // allow empty structs and enum variants with braces
358 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
359 (accepted, default_type_params, "1.0.0", None),
360 (accepted, globs, "1.0.0", None),
361 (accepted, if_let, "1.0.0", None),
362 // A temporary feature gate used to enable parser extensions needed
363 // to bootstrap fix for #5723.
364 (accepted, issue_5723_bootstrap, "1.0.0", None),
365 (accepted, macro_rules, "1.0.0", None),
366 // Allows using #![no_std]
367 (accepted, no_std, "1.6.0", None),
368 (accepted, slicing_syntax, "1.0.0", None),
369 (accepted, struct_variant, "1.0.0", None),
370 // These are used to test this portion of the compiler, they don't actually
372 (accepted, test_accepted_feature, "1.0.0", None),
373 (accepted, tuple_indexing, "1.0.0", None),
374 // Allows macros to appear in the type position.
375 (accepted, type_macros, "1.13.0", Some(27245)),
376 (accepted, while_let, "1.0.0", None),
377 // Allows `#[deprecated]` attribute
378 (accepted, deprecated, "1.9.0", Some(29935)),
380 (accepted, question_mark, "1.13.0", Some(31436)),
381 // Allows `..` in tuple (struct) patterns
382 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
383 (accepted, item_like_imports, "1.14.0", Some(35120)),
384 // Allows using `Self` and associated types in struct expressions and patterns.
385 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
386 // elide `'static` lifetimes in `static`s and `const`s
387 (accepted, static_in_const, "1.17.0", Some(35897)),
389 // (changing above list without updating src/doc/reference.md makes @cmr sad)
391 #[derive(PartialEq, Copy, Clone, Debug)]
392 pub enum AttributeType {
393 /// Normal, builtin attribute that is consumed
394 /// by the compiler before the unused_attribute check
397 /// Builtin attribute that may not be consumed by the compiler
398 /// before the unused_attribute check. These attributes
399 /// will be ignored by the unused_attribute lint
402 /// Builtin attribute that is only allowed at the crate level
406 pub enum AttributeGate {
407 /// Is gated by a given feature gate, reason
408 /// and function to check if enabled
409 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
411 /// Ungated attribute, can be used on all release channels
416 fn is_deprecated(&self) -> bool {
418 Gated(Stability::Deprecated(_), ..) => true,
424 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
427 // Argument is tracking issue link.
428 Deprecated(&'static str),
432 impl ::std::fmt::Debug for AttributeGate {
433 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
435 Gated(ref stab, ref name, ref expl, _) =>
436 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
437 Ungated => write!(fmt, "Ungated")
442 macro_rules! cfg_fn {
443 ($field: ident) => {{
444 fn f(features: &Features) -> bool {
447 f as fn(&Features) -> bool
451 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
452 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
455 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
456 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
459 // Attributes that have a special meaning to rustc or rustdoc
460 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
463 ("warn", Normal, Ungated),
464 ("allow", Normal, Ungated),
465 ("forbid", Normal, Ungated),
466 ("deny", Normal, Ungated),
468 ("macro_reexport", Normal, Ungated),
469 ("macro_use", Normal, Ungated),
470 ("macro_export", Normal, Ungated),
471 ("plugin_registrar", Normal, Ungated),
473 ("cfg", Normal, Ungated),
474 ("cfg_attr", Normal, Ungated),
475 ("main", Normal, Ungated),
476 ("start", Normal, Ungated),
477 ("test", Normal, Ungated),
478 ("bench", Normal, Ungated),
479 ("simd", Normal, Ungated),
480 ("repr", Normal, Ungated),
481 ("path", Normal, Ungated),
482 ("abi", Normal, Ungated),
483 ("automatically_derived", Normal, Ungated),
484 ("no_mangle", Normal, Ungated),
485 ("no_link", Normal, Ungated),
486 ("derive", Normal, Ungated),
487 ("should_panic", Normal, Ungated),
488 ("ignore", Normal, Ungated),
489 ("no_implicit_prelude", Normal, Ungated),
490 ("reexport_test_harness_main", Normal, Ungated),
491 ("link_args", Normal, Ungated),
492 ("macro_escape", Normal, Ungated),
495 ("structural_match", Whitelisted, Gated(Stability::Unstable,
497 "the semantics of constant patterns is \
499 cfg_fn!(structural_match))),
501 // Not used any more, but we can't feature gate it
502 ("no_stack_check", Normal, Ungated),
504 ("plugin", CrateLevel, Gated(Stability::Unstable,
506 "compiler plugins are experimental \
510 ("no_std", CrateLevel, Ungated),
511 ("no_core", CrateLevel, Gated(Stability::Unstable,
513 "no_core is experimental",
515 ("lang", Normal, Gated(Stability::Unstable,
517 "language items are subject to change",
518 cfg_fn!(lang_items))),
519 ("linkage", Whitelisted, Gated(Stability::Unstable,
521 "the `linkage` attribute is experimental \
522 and not portable across platforms",
524 ("thread_local", Whitelisted, Gated(Stability::Unstable,
526 "`#[thread_local]` is an experimental feature, and does \
527 not currently handle destructors. There is no \
528 corresponding `#[task_local]` mapping to the task \
530 cfg_fn!(thread_local))),
532 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
534 "the `#[rustc_on_unimplemented]` attribute \
535 is an experimental feature",
536 cfg_fn!(on_unimplemented))),
537 ("allocator", Whitelisted, Gated(Stability::Unstable,
539 "the `#[allocator]` attribute is an experimental feature",
540 cfg_fn!(allocator))),
541 ("needs_allocator", Normal, Gated(Stability::Unstable,
543 "the `#[needs_allocator]` \
544 attribute is an experimental \
546 cfg_fn!(needs_allocator))),
547 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
549 "the `#[panic_runtime]` attribute is \
550 an experimental feature",
551 cfg_fn!(panic_runtime))),
552 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
553 "needs_panic_runtime",
554 "the `#[needs_panic_runtime]` \
555 attribute is an experimental \
557 cfg_fn!(needs_panic_runtime))),
558 ("rustc_variance", Normal, Gated(Stability::Unstable,
560 "the `#[rustc_variance]` attribute \
561 is just used for rustc unit tests \
562 and will never be stable",
563 cfg_fn!(rustc_attrs))),
564 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
566 "the `#[rustc_error]` attribute \
567 is just used for rustc unit tests \
568 and will never be stable",
569 cfg_fn!(rustc_attrs))),
570 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
572 "the `#[rustc_if_this_changed]` attribute \
573 is just used for rustc unit tests \
574 and will never be stable",
575 cfg_fn!(rustc_attrs))),
576 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
578 "the `#[rustc_if_this_changed]` attribute \
579 is just used for rustc unit tests \
580 and will never be stable",
581 cfg_fn!(rustc_attrs))),
582 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
584 "the `#[rustc_dirty]` attribute \
585 is just used for rustc unit tests \
586 and will never be stable",
587 cfg_fn!(rustc_attrs))),
588 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
590 "the `#[rustc_clean]` attribute \
591 is just used for rustc unit tests \
592 and will never be stable",
593 cfg_fn!(rustc_attrs))),
594 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
596 "the `#[rustc_metadata_dirty]` attribute \
597 is just used for rustc unit tests \
598 and will never be stable",
599 cfg_fn!(rustc_attrs))),
600 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
602 "the `#[rustc_metadata_clean]` attribute \
603 is just used for rustc unit tests \
604 and will never be stable",
605 cfg_fn!(rustc_attrs))),
606 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
609 is just used for rustc unit tests \
610 and will never be stable",
611 cfg_fn!(rustc_attrs))),
612 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
615 is just used for rustc unit tests \
616 and will never be stable",
617 cfg_fn!(rustc_attrs))),
618 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
620 "internal rustc attributes will never be stable",
621 cfg_fn!(rustc_attrs))),
622 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
624 "internal rustc attributes will never be stable",
625 cfg_fn!(rustc_attrs))),
626 ("rustc_move_fragments", Normal, Gated(Stability::Unstable,
628 "the `#[rustc_move_fragments]` attribute \
629 is just used for rustc unit tests \
630 and will never be stable",
631 cfg_fn!(rustc_attrs))),
632 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
634 "the `#[rustc_mir]` attribute \
635 is just used for rustc unit tests \
636 and will never be stable",
637 cfg_fn!(rustc_attrs))),
638 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
640 "the `#[rustc_inherit_overflow_checks]` \
641 attribute is just used to control \
642 overflow checking behavior of several \
643 libcore functions that are inlined \
644 across crates and will never be stable",
645 cfg_fn!(rustc_attrs))),
646 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
648 "the `#[compiler_builtins]` attribute is used to \
649 identify the `compiler_builtins` crate which \
650 contains compiler-rt intrinsics and will never be \
652 cfg_fn!(compiler_builtins))),
653 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
655 "the `#[sanitizer_runtime]` attribute is used to \
656 identify crates that contain the runtime of a \
657 sanitizer and will never be stable",
658 cfg_fn!(sanitizer_runtime))),
660 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
661 "allow_internal_unstable",
662 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
663 cfg_fn!(allow_internal_unstable))),
665 ("fundamental", Whitelisted, Gated(Stability::Unstable,
667 "the `#[fundamental]` attribute \
668 is an experimental feature",
669 cfg_fn!(fundamental))),
671 ("proc_macro_derive", Normal, Ungated),
673 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
675 "internal implementation detail",
676 cfg_fn!(rustc_attrs))),
678 // FIXME: #14408 whitelist docs since rustdoc looks at them
679 ("doc", Whitelisted, Ungated),
681 // FIXME: #14406 these are processed in trans, which happens after the
683 ("cold", Whitelisted, Ungated),
684 ("naked", Whitelisted, Gated(Stability::Unstable,
686 "the `#[naked]` attribute \
687 is an experimental feature",
688 cfg_fn!(naked_functions))),
689 ("target_feature", Whitelisted, Gated(
690 Stability::Unstable, "target_feature",
691 "the `#[target_feature]` attribute is an experimental feature",
692 cfg_fn!(target_feature))),
693 ("export_name", Whitelisted, Ungated),
694 ("inline", Whitelisted, Ungated),
695 ("link", Whitelisted, Ungated),
696 ("link_name", Whitelisted, Ungated),
697 ("link_section", Whitelisted, Ungated),
698 ("no_builtins", Whitelisted, Ungated),
699 ("no_mangle", Whitelisted, Ungated),
700 ("no_debug", Whitelisted, Gated(
701 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
703 "the `#[no_debug]` attribute is an experimental feature",
705 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
706 "omit_gdb_pretty_printer_section",
707 "the `#[omit_gdb_pretty_printer_section]` \
708 attribute is just used for the Rust test \
710 cfg_fn!(omit_gdb_pretty_printer_section))),
711 ("unsafe_destructor_blind_to_params",
713 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
714 "dropck_parametricity",
715 "unsafe_destructor_blind_to_params has been replaced by \
716 may_dangle and will be removed in the future",
717 cfg_fn!(dropck_parametricity))),
720 Gated(Stability::Unstable,
722 "may_dangle has unstable semantics and may be removed in the future",
723 cfg_fn!(dropck_eyepatch))),
724 ("unwind", Whitelisted, Gated(Stability::Unstable,
726 "#[unwind] is experimental",
727 cfg_fn!(unwind_attributes))),
730 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
732 "`#[prelude_import]` is for use by rustc only",
733 cfg_fn!(prelude_import))),
735 // FIXME: #14407 these are only looked at on-demand so we can't
736 // guarantee they'll have already been checked
737 ("rustc_deprecated", Whitelisted, Ungated),
738 ("must_use", Whitelisted, Ungated),
739 ("stable", Whitelisted, Ungated),
740 ("unstable", Whitelisted, Ungated),
741 ("deprecated", Normal, Ungated),
743 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
745 "unboxed_closures are still evolving",
746 cfg_fn!(unboxed_closures))),
748 ("windows_subsystem", Whitelisted, Gated(Stability::Unstable,
750 "the windows subsystem attribute \
751 is currently unstable",
752 cfg_fn!(windows_subsystem))),
754 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
756 "attribute proc macros are currently unstable",
757 cfg_fn!(proc_macro))),
759 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
760 "rustc_derive_registrar",
761 "used internally by rustc",
762 cfg_fn!(rustc_attrs))),
764 // Crate level attributes
765 ("crate_name", CrateLevel, Ungated),
766 ("crate_type", CrateLevel, Ungated),
767 ("crate_id", CrateLevel, Ungated),
768 ("feature", CrateLevel, Ungated),
769 ("no_start", CrateLevel, Ungated),
770 ("no_main", CrateLevel, Ungated),
771 ("no_builtins", CrateLevel, Ungated),
772 ("recursion_limit", CrateLevel, Ungated),
773 ("type_length_limit", CrateLevel, Ungated),
776 // cfg(...)'s that are feature gated
777 const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] = &[
778 // (name in cfg, feature, function to check if the feature is enabled)
779 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
780 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
781 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
782 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
785 #[derive(Debug, Eq, PartialEq)]
786 pub struct GatedCfg {
792 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
793 let name = &*cfg.name().as_str();
795 .position(|info| info.0 == name)
804 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
805 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
806 if !has_feature(features) && !sess.codemap().span_allows_unstable(self.span) {
807 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
808 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
814 features: &'a Features,
815 parse_sess: &'a ParseSess,
817 plugin_attributes: &'a [(String, AttributeType)],
820 macro_rules! gate_feature_fn {
821 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
822 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
823 let has_feature: bool = has_feature(&$cx.features);
824 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
825 if !has_feature && !cx.cm.span_allows_unstable(span) {
826 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
831 macro_rules! gate_feature {
832 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
833 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
837 impl<'a> Context<'a> {
838 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
839 debug!("check_attribute(attr = {:?})", attr);
840 let name = &*attr.name().as_str();
841 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
843 if let &Gated(_, ref name, ref desc, ref has_feature) = gateage {
844 gate_feature_fn!(self, has_feature, attr.span, name, desc);
846 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", name, ty, gateage);
850 for &(ref n, ref ty) in self.plugin_attributes {
852 // Plugins can't gate attributes, so we don't check for it
853 // unlike the code above; we only use this loop to
854 // short-circuit to avoid the checks below
855 debug!("check_attribute: {:?} is registered by a plugin, {:?}", name, ty);
859 if name.starts_with("rustc_") {
860 gate_feature!(self, rustc_attrs, attr.span,
861 "unless otherwise specified, attributes \
862 with the prefix `rustc_` \
863 are reserved for internal compiler diagnostics");
864 } else if name.starts_with("derive_") {
865 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
866 } else if attr::is_known(attr) {
867 debug!("check_attribute: {:?} is known", name);
869 // Only run the custom attribute lint during regular
870 // feature gate checking. Macro gating runs
871 // before the plugin attributes are registered
872 // so we skip this then
874 gate_feature!(self, custom_attribute, attr.span,
875 &format!("The attribute `{}` is currently \
876 unknown to the compiler and \
878 added to it in the future",
885 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess,
886 cm: &CodeMap, features: &Features) {
888 features: features, parse_sess: parse_sess,
889 cm: cm, plugin_attributes: &[]
891 cx.check_attribute(attr, true);
894 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
895 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
898 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
899 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
901 // FIXME (#28244): enforce that active features have issue numbers
902 // assert!(issue.is_some())
905 // search in Accepted or Removed features
906 match ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).find(|t| t.0 == feature) {
907 Some(&(_, _, issue)) => issue,
908 None => panic!("Feature `{}` is not declared anywhere", feature),
918 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
920 feature_err(sess, feature, span, issue, explain).emit();
923 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
924 explain: &str) -> DiagnosticBuilder<'a> {
925 let diag = &sess.span_diagnostic;
927 let issue = match issue {
928 GateIssue::Language => find_lang_feature_issue(feature),
929 GateIssue::Library(lib) => lib,
932 let mut err = if let Some(n) = issue {
933 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
935 diag.struct_span_err(span, explain)
938 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
939 if sess.unstable_features.is_nightly_build() {
940 err.help(&format!("add #![feature({})] to the \
941 crate attributes to enable",
948 const EXPLAIN_BOX_SYNTAX: &'static str =
949 "box expression syntax is experimental; you can call `Box::new` instead.";
951 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
952 "attributes on non-item statements and expressions are experimental.";
954 pub const EXPLAIN_ASM: &'static str =
955 "inline assembly is not stable enough for use and is subject to change";
957 pub const EXPLAIN_LOG_SYNTAX: &'static str =
958 "`log_syntax!` is not stable enough for use and is subject to change";
960 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
961 "`concat_idents` is not stable enough for use and is subject to change";
963 pub const EXPLAIN_TRACE_MACROS: &'static str =
964 "`trace_macros` is not stable enough for use and is subject to change";
965 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
966 "allow_internal_unstable side-steps feature gating and stability checks";
968 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
969 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
971 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
972 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
973 Prefer using procedural macro custom derive.";
975 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
976 "attributes of the form `#[derive_*]` are reserved for the compiler";
978 pub const EXPLAIN_PLACEMENT_IN: &'static str =
979 "placement-in expression syntax is experimental and subject to change.";
981 struct PostExpansionVisitor<'a> {
982 context: &'a Context<'a>,
985 macro_rules! gate_feature_post {
986 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
987 let (cx, span) = ($cx, $span);
988 if !cx.context.cm.span_allows_unstable(span) {
989 gate_feature!(cx.context, $feature, span, $explain)
994 impl<'a> PostExpansionVisitor<'a> {
995 fn check_abi(&self, abi: Abi, span: Span) {
997 Abi::RustIntrinsic => {
998 gate_feature_post!(&self, intrinsics, span,
999 "intrinsics are subject to change");
1001 Abi::PlatformIntrinsic => {
1002 gate_feature_post!(&self, platform_intrinsics, span,
1003 "platform intrinsics are experimental and possibly buggy");
1005 Abi::Vectorcall => {
1006 gate_feature_post!(&self, abi_vectorcall, span,
1007 "vectorcall is experimental and subject to change");
1010 gate_feature_post!(&self, unboxed_closures, span,
1011 "rust-call ABI is subject to change");
1014 gate_feature_post!(&self, abi_sysv64, span,
1015 "sysv64 ABI is experimental and subject to change");
1018 gate_feature_post!(&self, abi_ptx, span,
1019 "PTX ABIs are experimental and subject to change");
1021 Abi::Unadjusted => {
1022 gate_feature_post!(&self, abi_unadjusted, span,
1023 "unadjusted ABI is an implementation detail and perma-unstable");
1025 Abi::Msp430Interrupt => {
1026 gate_feature_post!(&self, abi_msp430_interrupt, span,
1027 "msp430-interrupt ABI is experimental and subject to change");
1042 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1043 use ast::MetaItemKind::*;
1044 use ast::NestedMetaItemKind::*;
1048 NameValue(ref lit) => !lit.node.is_str(),
1049 List(ref list) => list.iter().any(|li| {
1051 MetaItem(ref mi) => contains_novel_literal(&mi),
1058 fn starts_with_digit(s: &str) -> bool {
1059 s.as_bytes().first().cloned().map_or(false, |b| b >= b'0' && b <= b'9')
1062 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1063 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1064 if !self.context.cm.span_allows_unstable(attr.span) {
1065 // check for gated attributes
1066 self.context.check_attribute(attr, false);
1069 if contains_novel_literal(&attr.value) {
1070 gate_feature_post!(&self, attr_literals, attr.span,
1071 "non-string literals in attributes, or string \
1072 literals in top-level positions, are experimental");
1076 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1077 if !name.as_str().is_ascii() {
1078 gate_feature_post!(&self, non_ascii_idents, sp,
1079 "non-ascii idents are not fully supported.");
1083 fn visit_item(&mut self, i: &'a ast::Item) {
1085 ast::ItemKind::ExternCrate(_) => {
1086 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1087 gate_feature_post!(&self, macro_reexport, i.span,
1088 "macros reexports are experimental \
1089 and possibly buggy");
1093 ast::ItemKind::ForeignMod(ref foreign_module) => {
1094 if attr::contains_name(&i.attrs[..], "link_args") {
1095 gate_feature_post!(&self, link_args, i.span,
1096 "the `link_args` attribute is not portable \
1097 across platforms, it is recommended to \
1098 use `#[link(name = \"foo\")]` instead")
1100 self.check_abi(foreign_module.abi, i.span);
1103 ast::ItemKind::Fn(..) => {
1104 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1105 gate_feature_post!(&self, plugin_registrar, i.span,
1106 "compiler plugins are experimental and possibly buggy");
1108 if attr::contains_name(&i.attrs[..], "start") {
1109 gate_feature_post!(&self, start, i.span,
1110 "a #[start] function is an experimental \
1111 feature whose signature may change \
1114 if attr::contains_name(&i.attrs[..], "main") {
1115 gate_feature_post!(&self, main, i.span,
1116 "declaration of a nonstandard #[main] \
1117 function may change over time, for now \
1118 a top-level `fn main()` is required");
1122 ast::ItemKind::Struct(..) => {
1123 if attr::contains_name(&i.attrs[..], "simd") {
1124 gate_feature_post!(&self, simd, i.span,
1125 "SIMD types are experimental and possibly buggy");
1126 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1127 "the `#[simd]` attribute \
1128 is deprecated, use \
1129 `#[repr(simd)]` instead");
1131 for attr in &i.attrs {
1132 if attr.name() == "repr" {
1133 for item in attr.meta_item_list().unwrap_or(&[]) {
1134 if item.check_name("simd") {
1135 gate_feature_post!(&self, repr_simd, i.span,
1136 "SIMD types are experimental \
1137 and possibly buggy");
1145 ast::ItemKind::Union(..) => {
1146 gate_feature_post!(&self, untagged_unions,
1148 "unions are unstable and possibly buggy");
1151 ast::ItemKind::DefaultImpl(..) => {
1152 gate_feature_post!(&self, optin_builtin_traits,
1154 "default trait implementations are experimental \
1155 and possibly buggy");
1158 ast::ItemKind::Impl(_, polarity, _, _, _, _) => {
1160 ast::ImplPolarity::Negative => {
1161 gate_feature_post!(&self, optin_builtin_traits,
1163 "negative trait bounds are not yet fully implemented; \
1164 use marker types for now");
1173 visit::walk_item(self, i);
1176 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1177 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1178 Some(val) => val.as_str().starts_with("llvm."),
1182 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1183 "linking to LLVM intrinsics is experimental");
1186 visit::walk_foreign_item(self, i)
1189 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1191 ast::TyKind::BareFn(ref bare_fn_ty) => {
1192 self.check_abi(bare_fn_ty.abi, ty.span);
1194 ast::TyKind::ImplTrait(..) => {
1195 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1196 "`impl Trait` is experimental");
1198 ast::TyKind::Never => {
1199 gate_feature_post!(&self, never_type, ty.span,
1200 "The `!` type is experimental");
1204 visit::walk_ty(self, ty)
1207 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1208 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1209 match output_ty.node {
1210 ast::TyKind::Never => return,
1213 self.visit_ty(output_ty)
1217 fn visit_expr(&mut self, e: &'a ast::Expr) {
1219 ast::ExprKind::Box(_) => {
1220 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1222 ast::ExprKind::Type(..) => {
1223 gate_feature_post!(&self, type_ascription, e.span,
1224 "type ascription is experimental");
1226 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1227 gate_feature_post!(&self, inclusive_range_syntax,
1229 "inclusive range syntax is experimental");
1231 ast::ExprKind::InPlace(..) => {
1232 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1234 ast::ExprKind::Struct(_, ref fields, _) => {
1235 for field in fields {
1236 if field.is_shorthand {
1237 gate_feature_post!(&self, field_init_shorthand, field.span,
1238 "struct field shorthands are unstable");
1240 if starts_with_digit(&field.ident.node.name.as_str()) {
1241 gate_feature_post!(&self, relaxed_adts,
1243 "numeric fields in struct expressions are unstable");
1247 ast::ExprKind::Break(_, Some(_)) => {
1248 gate_feature_post!(&self, loop_break_value, e.span,
1249 "`break` with a value is experimental");
1251 ast::ExprKind::Lit(ref lit) => {
1252 if let ast::LitKind::Int(_, ref ty) = lit.node {
1254 ast::LitIntType::Signed(ast::IntTy::I128) |
1255 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1256 gate_feature_post!(&self, i128_type, e.span,
1257 "128-bit integers are not stable");
1265 visit::walk_expr(self, e);
1268 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1269 match pattern.node {
1270 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1271 gate_feature_post!(&self, advanced_slice_patterns,
1273 "multiple-element slice matches anywhere \
1274 but at the end of a slice (e.g. \
1275 `[0, ..xs, 0]`) are experimental")
1277 PatKind::Slice(..) => {
1278 gate_feature_post!(&self, slice_patterns,
1280 "slice pattern syntax is experimental");
1282 PatKind::Box(..) => {
1283 gate_feature_post!(&self, box_patterns,
1285 "box pattern syntax is experimental");
1287 PatKind::Struct(_, ref fields, _) => {
1288 for field in fields {
1289 if starts_with_digit(&field.node.ident.name.as_str()) {
1290 gate_feature_post!(&self, relaxed_adts,
1292 "numeric fields in struct patterns are unstable");
1296 PatKind::Range(_, _, RangeEnd::Excluded) => {
1297 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1298 "exclusive range pattern syntax is experimental");
1302 visit::walk_pat(self, pattern)
1305 fn visit_fn(&mut self,
1306 fn_kind: FnKind<'a>,
1307 fn_decl: &'a ast::FnDecl,
1310 // check for const fn declarations
1312 FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) => {
1313 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1316 // stability of const fn methods are covered in
1317 // visit_trait_item and visit_impl_item below; this is
1318 // because default methods don't pass through this
1324 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1325 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1326 self.check_abi(abi, span);
1330 visit::walk_fn(self, fn_kind, fn_decl, span);
1333 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1335 ast::TraitItemKind::Const(..) => {
1336 gate_feature_post!(&self, associated_consts,
1338 "associated constants are experimental")
1340 ast::TraitItemKind::Method(ref sig, ref block) => {
1341 if block.is_none() {
1342 self.check_abi(sig.abi, ti.span);
1344 if sig.constness.node == ast::Constness::Const {
1345 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1348 ast::TraitItemKind::Type(_, Some(_)) => {
1349 gate_feature_post!(&self, associated_type_defaults, ti.span,
1350 "associated type defaults are unstable");
1354 visit::walk_trait_item(self, ti);
1357 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1358 if ii.defaultness == ast::Defaultness::Default {
1359 gate_feature_post!(&self, specialization,
1361 "specialization is unstable");
1365 ast::ImplItemKind::Const(..) => {
1366 gate_feature_post!(&self, associated_consts,
1368 "associated constants are experimental")
1370 ast::ImplItemKind::Method(ref sig, _) => {
1371 if sig.constness.node == ast::Constness::Const {
1372 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1377 visit::walk_impl_item(self, ii);
1380 fn visit_vis(&mut self, vis: &'a ast::Visibility) {
1381 let span = match *vis {
1382 ast::Visibility::Crate(span) => span,
1383 ast::Visibility::Restricted { ref path, .. } => path.span,
1386 gate_feature_post!(&self, pub_restricted, span, "`pub(restricted)` syntax is experimental");
1388 visit::walk_vis(self, vis)
1391 fn visit_generics(&mut self, g: &'a ast::Generics) {
1392 for t in &g.ty_params {
1393 if !t.attrs.is_empty() {
1394 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1395 "attributes on type parameter bindings are experimental");
1398 visit::walk_generics(self, g)
1401 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1402 if !lifetime_def.attrs.is_empty() {
1403 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1404 "attributes on lifetime bindings are experimental");
1406 visit::walk_lifetime_def(self, lifetime_def)
1410 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1411 let mut features = Features::new();
1413 let mut feature_checker = MutexFeatureChecker::default();
1415 for attr in krate_attrs {
1416 if !attr.check_name("feature") {
1420 match attr.meta_item_list() {
1422 span_err!(span_handler, attr.span, E0555,
1423 "malformed feature attribute, expected #![feature(...)]");
1427 let name = if let Some(word) = mi.word() {
1430 span_err!(span_handler, mi.span, E0556,
1431 "malformed feature, expected just one word");
1435 if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
1436 .find(|& &(n, _, _, _)| name == n) {
1437 *(setter(&mut features)) = true;
1438 feature_checker.collect(&features, mi.span);
1440 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1441 .find(|& &(n, _, _)| name == n) {
1442 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1444 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1445 .find(|& &(n, _, _)| name == n) {
1446 features.declared_stable_lang_features.push((name, mi.span));
1448 features.declared_lib_features.push((name, mi.span));
1455 feature_checker.check(span_handler);
1460 // A collector for mutually-exclusive features and their flag spans
1462 struct MutexFeatureChecker {
1463 proc_macro: Option<Span>,
1464 custom_attribute: Option<Span>,
1467 impl MutexFeatureChecker {
1468 // If this method turns out to be a hotspot due to branching,
1469 // the branching can be eliminated by modifying `setter!()` to set these spans
1470 // only for the features that need to be checked for mutual exclusion.
1471 fn collect(&mut self, features: &Features, span: Span) {
1472 if features.proc_macro {
1473 // If self.proc_macro is None, set to Some(span)
1474 self.proc_macro = self.proc_macro.or(Some(span));
1477 if features.custom_attribute {
1478 self.custom_attribute = self.custom_attribute.or(Some(span));
1482 fn check(self, handler: &Handler) {
1483 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1484 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1485 `#![feature(custom_attribute)] at the same time")
1486 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1494 pub fn check_crate(krate: &ast::Crate,
1496 features: &Features,
1497 plugin_attributes: &[(String, AttributeType)],
1498 unstable: UnstableFeatures) {
1499 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1504 plugin_attributes: plugin_attributes,
1506 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1509 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1510 pub enum UnstableFeatures {
1511 /// Hard errors for unstable features are active, as on
1512 /// beta/stable channels.
1514 /// Allow features to be activated, as on nightly.
1516 /// Errors are bypassed for bootstrapping. This is required any time
1517 /// during the build that feature-related lints are set to warn or above
1518 /// because the build turns on warnings-as-errors and uses lots of unstable
1519 /// features. As a result, this is always required for building Rust itself.
1523 impl UnstableFeatures {
1524 pub fn from_environment() -> UnstableFeatures {
1525 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1526 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1527 // Whether we should enable unstable features for bootstrapping
1528 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1529 match (disable_unstable_features, bootstrap) {
1530 (_, true) => UnstableFeatures::Cheat,
1531 (true, _) => UnstableFeatures::Disallow,
1532 (false, _) => UnstableFeatures::Allow
1536 pub fn is_nightly_build(&self) -> bool {
1538 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1544 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1545 unstable: UnstableFeatures) {
1546 let allow_features = match unstable {
1547 UnstableFeatures::Allow => true,
1548 UnstableFeatures::Disallow => false,
1549 UnstableFeatures::Cheat => true
1551 if !allow_features {
1552 for attr in &krate.attrs {
1553 if attr.check_name("feature") {
1554 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1555 span_err!(span_handler, attr.span, E0554,
1556 "#[feature] may not be used on the {} release channel",