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)),
337 // Allows the `catch {...}` expression
338 (active, catch_expr, "1.17.0", Some(31436)),
340 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
341 (active, rvalue_static_promotion, "1.15.1", Some(38865)),
345 (removed, import_shadowing, "1.0.0", None),
346 (removed, managed_boxes, "1.0.0", None),
347 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
348 (removed, negate_unsigned, "1.0.0", Some(29645)),
349 (removed, reflect, "1.0.0", Some(27749)),
350 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
351 (removed, opt_out_copy, "1.0.0", None),
352 (removed, quad_precision_float, "1.0.0", None),
353 (removed, struct_inherit, "1.0.0", None),
354 (removed, test_removed_feature, "1.0.0", None),
355 (removed, visible_private_types, "1.0.0", None),
356 (removed, unsafe_no_drop_flag, "1.0.0", None),
357 // Allows using items which are missing stability attributes
359 (removed, unmarked_api, "1.0.0", None),
360 (removed, pushpop_unsafe, "1.2.0", None),
364 (stable_removed, no_stack_check, "1.0.0", None),
368 (accepted, associated_types, "1.0.0", None),
369 // allow overloading augmented assignment operations like `a += b`
370 (accepted, augmented_assignments, "1.8.0", Some(28235)),
371 // allow empty structs and enum variants with braces
372 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
373 (accepted, default_type_params, "1.0.0", None),
374 (accepted, globs, "1.0.0", None),
375 (accepted, if_let, "1.0.0", None),
376 // A temporary feature gate used to enable parser extensions needed
377 // to bootstrap fix for #5723.
378 (accepted, issue_5723_bootstrap, "1.0.0", None),
379 (accepted, macro_rules, "1.0.0", None),
380 // Allows using #![no_std]
381 (accepted, no_std, "1.6.0", None),
382 (accepted, slicing_syntax, "1.0.0", None),
383 (accepted, struct_variant, "1.0.0", None),
384 // These are used to test this portion of the compiler, they don't actually
386 (accepted, test_accepted_feature, "1.0.0", None),
387 (accepted, tuple_indexing, "1.0.0", None),
388 // Allows macros to appear in the type position.
389 (accepted, type_macros, "1.13.0", Some(27245)),
390 (accepted, while_let, "1.0.0", None),
391 // Allows `#[deprecated]` attribute
392 (accepted, deprecated, "1.9.0", Some(29935)),
394 (accepted, question_mark, "1.13.0", Some(31436)),
395 // Allows `..` in tuple (struct) patterns
396 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
397 (accepted, item_like_imports, "1.14.0", Some(35120)),
398 // Allows using `Self` and associated types in struct expressions and patterns.
399 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
400 // elide `'static` lifetimes in `static`s and `const`s
401 (accepted, static_in_const, "1.17.0", Some(35897)),
402 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
403 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
404 // Allows the definition recursive static items.
405 (accepted, static_recursion, "1.17.0", Some(29719)),
406 // pub(restricted) visibilities (RFC 1422)
407 (accepted, pub_restricted, "1.17.0", Some(32409)),
408 // The #![windows_subsystem] attribute
409 (accepted, windows_subsystem, "1.18.0", Some(37499)),
411 // If you change this, please modify src/doc/unstable-book as well. You must
412 // move that documentation into the relevant place in the other docs, and
413 // remove the chapter on the flag.
415 #[derive(PartialEq, Copy, Clone, Debug)]
416 pub enum AttributeType {
417 /// Normal, builtin attribute that is consumed
418 /// by the compiler before the unused_attribute check
421 /// Builtin attribute that may not be consumed by the compiler
422 /// before the unused_attribute check. These attributes
423 /// will be ignored by the unused_attribute lint
426 /// Builtin attribute that is only allowed at the crate level
430 pub enum AttributeGate {
431 /// Is gated by a given feature gate, reason
432 /// and function to check if enabled
433 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
435 /// Ungated attribute, can be used on all release channels
440 fn is_deprecated(&self) -> bool {
442 Gated(Stability::Deprecated(_), ..) => true,
448 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
451 // Argument is tracking issue link.
452 Deprecated(&'static str),
456 impl ::std::fmt::Debug for AttributeGate {
457 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
459 Gated(ref stab, ref name, ref expl, _) =>
460 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
461 Ungated => write!(fmt, "Ungated")
466 macro_rules! cfg_fn {
467 ($field: ident) => {{
468 fn f(features: &Features) -> bool {
471 f as fn(&Features) -> bool
475 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
476 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
479 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
480 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
483 // Attributes that have a special meaning to rustc or rustdoc
484 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
487 ("warn", Normal, Ungated),
488 ("allow", Normal, Ungated),
489 ("forbid", Normal, Ungated),
490 ("deny", Normal, Ungated),
492 ("macro_reexport", Normal, Ungated),
493 ("macro_use", Normal, Ungated),
494 ("macro_export", Normal, Ungated),
495 ("plugin_registrar", Normal, Ungated),
497 ("cfg", Normal, Ungated),
498 ("cfg_attr", Normal, Ungated),
499 ("main", Normal, Ungated),
500 ("start", Normal, Ungated),
501 ("test", Normal, Ungated),
502 ("bench", Normal, Ungated),
503 ("simd", Normal, Ungated),
504 ("repr", Normal, Ungated),
505 ("path", Normal, Ungated),
506 ("abi", Normal, Ungated),
507 ("automatically_derived", Normal, Ungated),
508 ("no_mangle", Normal, Ungated),
509 ("no_link", Normal, Ungated),
510 ("derive", Normal, Ungated),
511 ("should_panic", Normal, Ungated),
512 ("ignore", Normal, Ungated),
513 ("no_implicit_prelude", Normal, Ungated),
514 ("reexport_test_harness_main", Normal, Ungated),
515 ("link_args", Normal, Ungated),
516 ("macro_escape", Normal, Ungated),
519 ("structural_match", Whitelisted, Gated(Stability::Unstable,
521 "the semantics of constant patterns is \
523 cfg_fn!(structural_match))),
525 ("plugin", CrateLevel, Gated(Stability::Unstable,
527 "compiler plugins are experimental \
531 ("no_std", CrateLevel, Ungated),
532 ("no_core", CrateLevel, Gated(Stability::Unstable,
534 "no_core is experimental",
536 ("lang", Normal, Gated(Stability::Unstable,
538 "language items are subject to change",
539 cfg_fn!(lang_items))),
540 ("linkage", Whitelisted, Gated(Stability::Unstable,
542 "the `linkage` attribute is experimental \
543 and not portable across platforms",
545 ("thread_local", Whitelisted, Gated(Stability::Unstable,
547 "`#[thread_local]` is an experimental feature, and does \
548 not currently handle destructors. There is no \
549 corresponding `#[task_local]` mapping to the task \
551 cfg_fn!(thread_local))),
553 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
555 "the `#[rustc_on_unimplemented]` attribute \
556 is an experimental feature",
557 cfg_fn!(on_unimplemented))),
558 ("allocator", Whitelisted, Gated(Stability::Unstable,
560 "the `#[allocator]` attribute is an experimental feature",
561 cfg_fn!(allocator))),
562 ("needs_allocator", Normal, Gated(Stability::Unstable,
564 "the `#[needs_allocator]` \
565 attribute is an experimental \
567 cfg_fn!(needs_allocator))),
568 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
570 "the `#[panic_runtime]` attribute is \
571 an experimental feature",
572 cfg_fn!(panic_runtime))),
573 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
574 "needs_panic_runtime",
575 "the `#[needs_panic_runtime]` \
576 attribute is an experimental \
578 cfg_fn!(needs_panic_runtime))),
579 ("rustc_variance", Normal, Gated(Stability::Unstable,
581 "the `#[rustc_variance]` attribute \
582 is just used for rustc unit tests \
583 and will never be stable",
584 cfg_fn!(rustc_attrs))),
585 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
587 "the `#[rustc_error]` attribute \
588 is just used for rustc unit tests \
589 and will never be stable",
590 cfg_fn!(rustc_attrs))),
591 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
593 "the `#[rustc_if_this_changed]` attribute \
594 is just used for rustc unit tests \
595 and will never be stable",
596 cfg_fn!(rustc_attrs))),
597 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
599 "the `#[rustc_if_this_changed]` attribute \
600 is just used for rustc unit tests \
601 and will never be stable",
602 cfg_fn!(rustc_attrs))),
603 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
605 "the `#[rustc_dirty]` attribute \
606 is just used for rustc unit tests \
607 and will never be stable",
608 cfg_fn!(rustc_attrs))),
609 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
611 "the `#[rustc_clean]` attribute \
612 is just used for rustc unit tests \
613 and will never be stable",
614 cfg_fn!(rustc_attrs))),
615 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
617 "the `#[rustc_metadata_dirty]` attribute \
618 is just used for rustc unit tests \
619 and will never be stable",
620 cfg_fn!(rustc_attrs))),
621 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
623 "the `#[rustc_metadata_clean]` attribute \
624 is just used for rustc unit tests \
625 and will never be stable",
626 cfg_fn!(rustc_attrs))),
627 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
630 is just used for rustc unit tests \
631 and will never be stable",
632 cfg_fn!(rustc_attrs))),
633 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
636 is just used for rustc unit tests \
637 and will never be stable",
638 cfg_fn!(rustc_attrs))),
639 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
641 "internal rustc attributes will never be stable",
642 cfg_fn!(rustc_attrs))),
643 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
645 "internal rustc attributes will never be stable",
646 cfg_fn!(rustc_attrs))),
647 ("rustc_move_fragments", Normal, Gated(Stability::Unstable,
649 "the `#[rustc_move_fragments]` attribute \
650 is just used for rustc unit tests \
651 and will never be stable",
652 cfg_fn!(rustc_attrs))),
653 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
655 "the `#[rustc_mir]` attribute \
656 is just used for rustc unit tests \
657 and will never be stable",
658 cfg_fn!(rustc_attrs))),
659 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
661 "the `#[rustc_inherit_overflow_checks]` \
662 attribute is just used to control \
663 overflow checking behavior of several \
664 libcore functions that are inlined \
665 across crates and will never be stable",
666 cfg_fn!(rustc_attrs))),
667 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
669 "the `#[compiler_builtins]` attribute is used to \
670 identify the `compiler_builtins` crate which \
671 contains compiler-rt intrinsics and will never be \
673 cfg_fn!(compiler_builtins))),
674 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
676 "the `#[sanitizer_runtime]` attribute is used to \
677 identify crates that contain the runtime of a \
678 sanitizer and will never be stable",
679 cfg_fn!(sanitizer_runtime))),
681 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
682 "allow_internal_unstable",
683 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
684 cfg_fn!(allow_internal_unstable))),
686 ("fundamental", Whitelisted, Gated(Stability::Unstable,
688 "the `#[fundamental]` attribute \
689 is an experimental feature",
690 cfg_fn!(fundamental))),
692 ("proc_macro_derive", Normal, Ungated),
694 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
696 "internal implementation detail",
697 cfg_fn!(rustc_attrs))),
699 // FIXME: #14408 whitelist docs since rustdoc looks at them
700 ("doc", Whitelisted, Ungated),
702 // FIXME: #14406 these are processed in trans, which happens after the
704 ("cold", Whitelisted, Ungated),
705 ("naked", Whitelisted, Gated(Stability::Unstable,
707 "the `#[naked]` attribute \
708 is an experimental feature",
709 cfg_fn!(naked_functions))),
710 ("target_feature", Whitelisted, Gated(
711 Stability::Unstable, "target_feature",
712 "the `#[target_feature]` attribute is an experimental feature",
713 cfg_fn!(target_feature))),
714 ("export_name", Whitelisted, Ungated),
715 ("inline", Whitelisted, Ungated),
716 ("link", Whitelisted, Ungated),
717 ("link_name", Whitelisted, Ungated),
718 ("link_section", Whitelisted, Ungated),
719 ("no_builtins", Whitelisted, Ungated),
720 ("no_mangle", Whitelisted, Ungated),
721 ("no_debug", Whitelisted, Gated(
722 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
724 "the `#[no_debug]` attribute is an experimental feature",
726 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
727 "omit_gdb_pretty_printer_section",
728 "the `#[omit_gdb_pretty_printer_section]` \
729 attribute is just used for the Rust test \
731 cfg_fn!(omit_gdb_pretty_printer_section))),
732 ("unsafe_destructor_blind_to_params",
734 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
735 "dropck_parametricity",
736 "unsafe_destructor_blind_to_params has been replaced by \
737 may_dangle and will be removed in the future",
738 cfg_fn!(dropck_parametricity))),
741 Gated(Stability::Unstable,
743 "may_dangle has unstable semantics and may be removed in the future",
744 cfg_fn!(dropck_eyepatch))),
745 ("unwind", Whitelisted, Gated(Stability::Unstable,
747 "#[unwind] is experimental",
748 cfg_fn!(unwind_attributes))),
751 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
753 "`#[prelude_import]` is for use by rustc only",
754 cfg_fn!(prelude_import))),
756 // FIXME: #14407 these are only looked at on-demand so we can't
757 // guarantee they'll have already been checked
758 ("rustc_deprecated", Whitelisted, Ungated),
759 ("must_use", Whitelisted, Ungated),
760 ("stable", Whitelisted, Ungated),
761 ("unstable", Whitelisted, Ungated),
762 ("deprecated", Normal, Ungated),
764 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
766 "unboxed_closures are still evolving",
767 cfg_fn!(unboxed_closures))),
769 ("windows_subsystem", Whitelisted, Ungated),
771 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
773 "attribute proc macros are currently unstable",
774 cfg_fn!(proc_macro))),
776 ("proc_macro", Normal, Gated(Stability::Unstable,
778 "function-like proc macros are currently unstable",
779 cfg_fn!(proc_macro))),
781 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
782 "rustc_derive_registrar",
783 "used internally by rustc",
784 cfg_fn!(rustc_attrs))),
786 // Crate level attributes
787 ("crate_name", CrateLevel, Ungated),
788 ("crate_type", CrateLevel, Ungated),
789 ("crate_id", CrateLevel, Ungated),
790 ("feature", CrateLevel, Ungated),
791 ("no_start", CrateLevel, Ungated),
792 ("no_main", CrateLevel, Ungated),
793 ("no_builtins", CrateLevel, Ungated),
794 ("recursion_limit", CrateLevel, Ungated),
795 ("type_length_limit", CrateLevel, Ungated),
798 // cfg(...)'s that are feature gated
799 const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] = &[
800 // (name in cfg, feature, function to check if the feature is enabled)
801 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
802 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
803 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
804 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
807 #[derive(Debug, Eq, PartialEq)]
808 pub struct GatedCfg {
814 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
815 let name = cfg.name().as_str();
817 .position(|info| info.0 == name)
826 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
827 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
828 if !has_feature(features) && !self.span.allows_unstable() {
829 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
830 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
836 features: &'a Features,
837 parse_sess: &'a ParseSess,
838 plugin_attributes: &'a [(String, AttributeType)],
841 macro_rules! gate_feature_fn {
842 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
843 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
844 let has_feature: bool = has_feature(&$cx.features);
845 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
846 if !has_feature && !span.allows_unstable() {
847 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
852 macro_rules! gate_feature {
853 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
854 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
858 impl<'a> Context<'a> {
859 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
860 debug!("check_attribute(attr = {:?})", attr);
861 let name = unwrap_or!(attr.name(), return).as_str();
862 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
864 if let &Gated(_, ref name, ref desc, ref has_feature) = gateage {
865 gate_feature_fn!(self, has_feature, attr.span, name, desc);
867 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
871 for &(ref n, ref ty) in self.plugin_attributes {
872 if attr.path == &**n {
873 // Plugins can't gate attributes, so we don't check for it
874 // unlike the code above; we only use this loop to
875 // short-circuit to avoid the checks below
876 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
880 if name.starts_with("rustc_") {
881 gate_feature!(self, rustc_attrs, attr.span,
882 "unless otherwise specified, attributes \
883 with the prefix `rustc_` \
884 are reserved for internal compiler diagnostics");
885 } else if name.starts_with("derive_") {
886 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
887 } else if !attr::is_known(attr) {
888 // Only run the custom attribute lint during regular
889 // feature gate checking. Macro gating runs
890 // before the plugin attributes are registered
891 // so we skip this then
893 gate_feature!(self, custom_attribute, attr.span,
894 &format!("The attribute `{}` is currently \
895 unknown to the compiler and \
897 added to it in the future",
904 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
905 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
906 cx.check_attribute(attr, true);
909 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
910 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
913 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
914 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
916 // FIXME (#28244): enforce that active features have issue numbers
917 // assert!(issue.is_some())
920 // search in Accepted, Removed, or Stable Removed features
921 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
922 .find(|t| t.0 == feature);
924 Some(&(_, _, issue)) => issue,
925 None => panic!("Feature `{}` is not declared anywhere", feature),
935 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
937 feature_err(sess, feature, span, issue, explain).emit();
940 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
941 explain: &str) -> DiagnosticBuilder<'a> {
942 let diag = &sess.span_diagnostic;
944 let issue = match issue {
945 GateIssue::Language => find_lang_feature_issue(feature),
946 GateIssue::Library(lib) => lib,
949 let mut err = if let Some(n) = issue {
950 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
952 diag.struct_span_err(span, explain)
955 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
956 if sess.unstable_features.is_nightly_build() {
957 err.help(&format!("add #![feature({})] to the \
958 crate attributes to enable",
965 const EXPLAIN_BOX_SYNTAX: &'static str =
966 "box expression syntax is experimental; you can call `Box::new` instead.";
968 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
969 "attributes on non-item statements and expressions are experimental.";
971 pub const EXPLAIN_ASM: &'static str =
972 "inline assembly is not stable enough for use and is subject to change";
974 pub const EXPLAIN_LOG_SYNTAX: &'static str =
975 "`log_syntax!` is not stable enough for use and is subject to change";
977 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
978 "`concat_idents` is not stable enough for use and is subject to change";
980 pub const EXPLAIN_TRACE_MACROS: &'static str =
981 "`trace_macros` is not stable enough for use and is subject to change";
982 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
983 "allow_internal_unstable side-steps feature gating and stability checks";
985 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
986 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
988 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
989 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
990 Prefer using procedural macro custom derive.";
992 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
993 "attributes of the form `#[derive_*]` are reserved for the compiler";
995 pub const EXPLAIN_PLACEMENT_IN: &'static str =
996 "placement-in expression syntax is experimental and subject to change.";
998 pub const CLOSURE_TO_FN_COERCION: &'static str =
999 "non-capturing closure to fn coercion is experimental";
1001 struct PostExpansionVisitor<'a> {
1002 context: &'a Context<'a>,
1005 macro_rules! gate_feature_post {
1006 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1007 let (cx, span) = ($cx, $span);
1008 if !span.allows_unstable() {
1009 gate_feature!(cx.context, $feature, span, $explain)
1014 impl<'a> PostExpansionVisitor<'a> {
1015 fn check_abi(&self, abi: Abi, span: Span) {
1017 Abi::RustIntrinsic => {
1018 gate_feature_post!(&self, intrinsics, span,
1019 "intrinsics are subject to change");
1021 Abi::PlatformIntrinsic => {
1022 gate_feature_post!(&self, platform_intrinsics, span,
1023 "platform intrinsics are experimental and possibly buggy");
1025 Abi::Vectorcall => {
1026 gate_feature_post!(&self, abi_vectorcall, span,
1027 "vectorcall is experimental and subject to change");
1030 gate_feature_post!(&self, unboxed_closures, span,
1031 "rust-call ABI is subject to change");
1034 gate_feature_post!(&self, abi_sysv64, span,
1035 "sysv64 ABI is experimental and subject to change");
1038 gate_feature_post!(&self, abi_ptx, span,
1039 "PTX ABIs are experimental and subject to change");
1041 Abi::Unadjusted => {
1042 gate_feature_post!(&self, abi_unadjusted, span,
1043 "unadjusted ABI is an implementation detail and perma-unstable");
1045 Abi::Msp430Interrupt => {
1046 gate_feature_post!(&self, abi_msp430_interrupt, span,
1047 "msp430-interrupt ABI is experimental and subject to change");
1049 Abi::X86Interrupt => {
1050 gate_feature_post!(&self, abi_x86_interrupt, span,
1051 "x86-interrupt ABI is experimental and subject to change");
1066 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1067 use ast::MetaItemKind::*;
1068 use ast::NestedMetaItemKind::*;
1072 NameValue(ref lit) => !lit.node.is_str(),
1073 List(ref list) => list.iter().any(|li| {
1075 MetaItem(ref mi) => contains_novel_literal(&mi),
1082 fn starts_with_digit(s: &str) -> bool {
1083 s.as_bytes().first().cloned().map_or(false, |b| b >= b'0' && b <= b'9')
1086 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1087 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1088 if !attr.span.allows_unstable() {
1089 // check for gated attributes
1090 self.context.check_attribute(attr, false);
1093 if self.context.features.proc_macro && attr::is_known(attr) {
1097 let meta = panictry!(attr.parse_meta(&self.context.parse_sess));
1098 if contains_novel_literal(&meta) {
1099 gate_feature_post!(&self, attr_literals, attr.span,
1100 "non-string literals in attributes, or string \
1101 literals in top-level positions, are experimental");
1105 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1106 if !name.as_str().is_ascii() {
1107 gate_feature_post!(&self, non_ascii_idents, sp,
1108 "non-ascii idents are not fully supported.");
1112 fn visit_item(&mut self, i: &'a ast::Item) {
1114 ast::ItemKind::ExternCrate(_) => {
1115 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1116 gate_feature_post!(&self, macro_reexport, i.span,
1117 "macros reexports are experimental \
1118 and possibly buggy");
1122 ast::ItemKind::ForeignMod(ref foreign_module) => {
1123 if attr::contains_name(&i.attrs[..], "link_args") {
1124 gate_feature_post!(&self, link_args, i.span,
1125 "the `link_args` attribute is not portable \
1126 across platforms, it is recommended to \
1127 use `#[link(name = \"foo\")]` instead")
1129 self.check_abi(foreign_module.abi, i.span);
1132 ast::ItemKind::Fn(..) => {
1133 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1134 gate_feature_post!(&self, plugin_registrar, i.span,
1135 "compiler plugins are experimental and possibly buggy");
1137 if attr::contains_name(&i.attrs[..], "start") {
1138 gate_feature_post!(&self, start, i.span,
1139 "a #[start] function is an experimental \
1140 feature whose signature may change \
1143 if attr::contains_name(&i.attrs[..], "main") {
1144 gate_feature_post!(&self, main, i.span,
1145 "declaration of a nonstandard #[main] \
1146 function may change over time, for now \
1147 a top-level `fn main()` is required");
1151 ast::ItemKind::Struct(..) => {
1152 if attr::contains_name(&i.attrs[..], "simd") {
1153 gate_feature_post!(&self, simd, i.span,
1154 "SIMD types are experimental and possibly buggy");
1155 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1156 "the `#[simd]` attribute \
1157 is deprecated, use \
1158 `#[repr(simd)]` instead");
1160 for attr in &i.attrs {
1161 if attr.path == "repr" {
1162 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1163 if item.check_name("simd") {
1164 gate_feature_post!(&self, repr_simd, i.span,
1165 "SIMD types are experimental \
1166 and possibly buggy");
1174 ast::ItemKind::Union(..) => {
1175 gate_feature_post!(&self, untagged_unions,
1177 "unions are unstable and possibly buggy");
1180 ast::ItemKind::DefaultImpl(..) => {
1181 gate_feature_post!(&self, optin_builtin_traits,
1183 "default trait implementations are experimental \
1184 and possibly buggy");
1187 ast::ItemKind::Impl(_, polarity, _, _, _, _) => {
1189 ast::ImplPolarity::Negative => {
1190 gate_feature_post!(&self, optin_builtin_traits,
1192 "negative trait bounds are not yet fully implemented; \
1193 use marker types for now");
1202 visit::walk_item(self, i);
1205 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1206 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1207 Some(val) => val.as_str().starts_with("llvm."),
1211 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1212 "linking to LLVM intrinsics is experimental");
1215 visit::walk_foreign_item(self, i)
1218 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1220 ast::TyKind::BareFn(ref bare_fn_ty) => {
1221 self.check_abi(bare_fn_ty.abi, ty.span);
1223 ast::TyKind::ImplTrait(..) => {
1224 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1225 "`impl Trait` is experimental");
1227 ast::TyKind::Never => {
1228 gate_feature_post!(&self, never_type, ty.span,
1229 "The `!` type is experimental");
1233 visit::walk_ty(self, ty)
1236 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1237 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1238 match output_ty.node {
1239 ast::TyKind::Never => return,
1242 self.visit_ty(output_ty)
1246 fn visit_expr(&mut self, e: &'a ast::Expr) {
1248 ast::ExprKind::Box(_) => {
1249 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1251 ast::ExprKind::Type(..) => {
1252 gate_feature_post!(&self, type_ascription, e.span,
1253 "type ascription is experimental");
1255 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1256 gate_feature_post!(&self, inclusive_range_syntax,
1258 "inclusive range syntax is experimental");
1260 ast::ExprKind::InPlace(..) => {
1261 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1263 ast::ExprKind::Struct(_, ref fields, _) => {
1264 for field in fields {
1265 if starts_with_digit(&field.ident.node.name.as_str()) {
1266 gate_feature_post!(&self, relaxed_adts,
1268 "numeric fields in struct expressions are unstable");
1272 ast::ExprKind::Break(_, Some(_)) => {
1273 gate_feature_post!(&self, loop_break_value, e.span,
1274 "`break` with a value is experimental");
1276 ast::ExprKind::Lit(ref lit) => {
1277 if let ast::LitKind::Int(_, ref ty) = lit.node {
1279 ast::LitIntType::Signed(ast::IntTy::I128) |
1280 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1281 gate_feature_post!(&self, i128_type, e.span,
1282 "128-bit integers are not stable");
1288 ast::ExprKind::Catch(_) => {
1289 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1293 visit::walk_expr(self, e);
1296 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1297 match pattern.node {
1298 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1299 gate_feature_post!(&self, advanced_slice_patterns,
1301 "multiple-element slice matches anywhere \
1302 but at the end of a slice (e.g. \
1303 `[0, ..xs, 0]`) are experimental")
1305 PatKind::Slice(..) => {
1306 gate_feature_post!(&self, slice_patterns,
1308 "slice pattern syntax is experimental");
1310 PatKind::Box(..) => {
1311 gate_feature_post!(&self, box_patterns,
1313 "box pattern syntax is experimental");
1315 PatKind::Struct(_, ref fields, _) => {
1316 for field in fields {
1317 if starts_with_digit(&field.node.ident.name.as_str()) {
1318 gate_feature_post!(&self, relaxed_adts,
1320 "numeric fields in struct patterns are unstable");
1324 PatKind::Range(_, _, RangeEnd::Excluded) => {
1325 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1326 "exclusive range pattern syntax is experimental");
1330 visit::walk_pat(self, pattern)
1333 fn visit_fn(&mut self,
1334 fn_kind: FnKind<'a>,
1335 fn_decl: &'a ast::FnDecl,
1338 // check for const fn declarations
1340 FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) => {
1341 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1344 // stability of const fn methods are covered in
1345 // visit_trait_item and visit_impl_item below; this is
1346 // because default methods don't pass through this
1352 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1353 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1354 self.check_abi(abi, span);
1358 visit::walk_fn(self, fn_kind, fn_decl, span);
1361 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1363 ast::TraitItemKind::Const(..) => {
1364 gate_feature_post!(&self, associated_consts,
1366 "associated constants are experimental")
1368 ast::TraitItemKind::Method(ref sig, ref block) => {
1369 if block.is_none() {
1370 self.check_abi(sig.abi, ti.span);
1372 if sig.constness.node == ast::Constness::Const {
1373 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1376 ast::TraitItemKind::Type(_, Some(_)) => {
1377 gate_feature_post!(&self, associated_type_defaults, ti.span,
1378 "associated type defaults are unstable");
1382 visit::walk_trait_item(self, ti);
1385 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1386 if ii.defaultness == ast::Defaultness::Default {
1387 gate_feature_post!(&self, specialization,
1389 "specialization is unstable");
1393 ast::ImplItemKind::Const(..) => {
1394 gate_feature_post!(&self, associated_consts,
1396 "associated constants are experimental")
1398 ast::ImplItemKind::Method(ref sig, _) => {
1399 if sig.constness.node == ast::Constness::Const {
1400 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1405 visit::walk_impl_item(self, ii);
1408 fn visit_generics(&mut self, g: &'a ast::Generics) {
1409 for t in &g.ty_params {
1410 if !t.attrs.is_empty() {
1411 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1412 "attributes on type parameter bindings are experimental");
1415 visit::walk_generics(self, g)
1418 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1419 if !lifetime_def.attrs.is_empty() {
1420 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1421 "attributes on lifetime bindings are experimental");
1423 visit::walk_lifetime_def(self, lifetime_def)
1427 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1428 let mut features = Features::new();
1430 let mut feature_checker = MutexFeatureChecker::default();
1432 for attr in krate_attrs {
1433 if !attr.check_name("feature") {
1437 match attr.meta_item_list() {
1439 span_err!(span_handler, attr.span, E0555,
1440 "malformed feature attribute, expected #![feature(...)]");
1444 let name = if let Some(word) = mi.word() {
1447 span_err!(span_handler, mi.span, E0556,
1448 "malformed feature, expected just one word");
1452 if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
1453 .find(|& &(n, _, _, _)| name == n) {
1454 *(setter(&mut features)) = true;
1455 feature_checker.collect(&features, mi.span);
1457 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1458 .find(|& &(n, _, _)| name == n)
1459 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1460 .find(|& &(n, _, _)| name == n)) {
1461 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1463 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1464 .find(|& &(n, _, _)| name == n) {
1465 features.declared_stable_lang_features.push((name, mi.span));
1467 features.declared_lib_features.push((name, mi.span));
1474 feature_checker.check(span_handler);
1479 // A collector for mutually-exclusive features and their flag spans
1481 struct MutexFeatureChecker {
1482 proc_macro: Option<Span>,
1483 custom_attribute: Option<Span>,
1486 impl MutexFeatureChecker {
1487 // If this method turns out to be a hotspot due to branching,
1488 // the branching can be eliminated by modifying `setter!()` to set these spans
1489 // only for the features that need to be checked for mutual exclusion.
1490 fn collect(&mut self, features: &Features, span: Span) {
1491 if features.proc_macro {
1492 // If self.proc_macro is None, set to Some(span)
1493 self.proc_macro = self.proc_macro.or(Some(span));
1496 if features.custom_attribute {
1497 self.custom_attribute = self.custom_attribute.or(Some(span));
1501 fn check(self, handler: &Handler) {
1502 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1503 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1504 `#![feature(custom_attribute)] at the same time")
1505 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1513 pub fn check_crate(krate: &ast::Crate,
1515 features: &Features,
1516 plugin_attributes: &[(String, AttributeType)],
1517 unstable: UnstableFeatures) {
1518 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1522 plugin_attributes: plugin_attributes,
1524 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1527 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1528 pub enum UnstableFeatures {
1529 /// Hard errors for unstable features are active, as on
1530 /// beta/stable channels.
1532 /// Allow features to be activated, as on nightly.
1534 /// Errors are bypassed for bootstrapping. This is required any time
1535 /// during the build that feature-related lints are set to warn or above
1536 /// because the build turns on warnings-as-errors and uses lots of unstable
1537 /// features. As a result, this is always required for building Rust itself.
1541 impl UnstableFeatures {
1542 pub fn from_environment() -> UnstableFeatures {
1543 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1544 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1545 // Whether we should enable unstable features for bootstrapping
1546 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1547 match (disable_unstable_features, bootstrap) {
1548 (_, true) => UnstableFeatures::Cheat,
1549 (true, _) => UnstableFeatures::Disallow,
1550 (false, _) => UnstableFeatures::Allow
1554 pub fn is_nightly_build(&self) -> bool {
1556 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1562 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1563 unstable: UnstableFeatures) {
1564 let allow_features = match unstable {
1565 UnstableFeatures::Allow => true,
1566 UnstableFeatures::Disallow => false,
1567 UnstableFeatures::Cheat => true
1569 if !allow_features {
1570 for attr in &krate.attrs {
1571 if attr.check_name("feature") {
1572 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1573 span_err!(span_handler, attr.span, E0554,
1574 "#[feature] may not be used on the {} release channel",