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)),
273 (active, never_type, "1.13.0", Some(35121)),
275 // Allows all literals in attribute lists and values of key-value pairs.
276 (active, attr_literals, "1.13.0", Some(34981)),
278 // Allows the sysV64 ABI to be specified on all platforms
279 // instead of just the platforms on which it is the C ABI
280 (active, abi_sysv64, "1.13.0", Some(36167)),
282 // Allows untagged unions `union U { ... }`
283 (active, untagged_unions, "1.13.0", Some(32836)),
285 // Used to identify the `compiler_builtins` crate
287 (active, compiler_builtins, "1.13.0", None),
289 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
290 (active, generic_param_attrs, "1.11.0", Some(34761)),
292 // Allows #[link(..., cfg(..))]
293 (active, link_cfg, "1.14.0", Some(37406)),
295 (active, use_extern_macros, "1.15.0", Some(35896)),
297 // Allows #[target_feature(...)]
298 (active, target_feature, "1.15.0", None),
300 // `extern "ptx-*" fn()`
301 (active, abi_ptx, "1.15.0", None),
304 (active, i128_type, "1.16.0", Some(35118)),
306 // The `unadjusted` ABI. Perma unstable.
307 (active, abi_unadjusted, "1.16.0", None),
310 (active, proc_macro, "1.16.0", Some(38356)),
312 // Allows attributes on struct literal fields.
313 (active, struct_field_attributes, "1.16.0", Some(38814)),
315 // Allows #[link(kind="static-nobundle"...]
316 (active, static_nobundle, "1.16.0", Some(37403)),
318 // `extern "msp430-interrupt" fn()`
319 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
321 // Used to identify crates that contain sanitizer runtimes
323 (active, sanitizer_runtime, "1.17.0", None),
325 // `extern "x86-interrupt" fn()`
326 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
329 // Allows the `catch {...}` expression
330 (active, catch_expr, "1.17.0", Some(31436)),
332 // Allows `repr(align(u16))` struct attribute (RFC 1358)
333 (active, repr_align, "1.17.0", Some(33626)),
335 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
336 (active, rvalue_static_promotion, "1.15.1", Some(38865)),
338 // Used to preserve symbols (see llvm.used)
339 (active, used, "1.18.0", Some(40289)),
341 // Allows module-level inline assembly by way of global_asm!()
342 (active, global_asm, "1.18.0", Some(35119)),
344 // Allows overlapping impls of marker traits
345 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
347 // Allows use of the :vis macro fragment specifier
348 (active, macro_vis_matcher, "1.18.0", Some(41022)),
352 (removed, import_shadowing, "1.0.0", None),
353 (removed, managed_boxes, "1.0.0", None),
354 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
355 (removed, negate_unsigned, "1.0.0", Some(29645)),
356 (removed, reflect, "1.0.0", Some(27749)),
357 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
358 (removed, opt_out_copy, "1.0.0", None),
359 (removed, quad_precision_float, "1.0.0", None),
360 (removed, struct_inherit, "1.0.0", None),
361 (removed, test_removed_feature, "1.0.0", None),
362 (removed, visible_private_types, "1.0.0", None),
363 (removed, unsafe_no_drop_flag, "1.0.0", None),
364 // Allows using items which are missing stability attributes
366 (removed, unmarked_api, "1.0.0", None),
367 (removed, pushpop_unsafe, "1.2.0", None),
371 (stable_removed, no_stack_check, "1.0.0", None),
375 (accepted, associated_types, "1.0.0", None),
376 // allow overloading augmented assignment operations like `a += b`
377 (accepted, augmented_assignments, "1.8.0", Some(28235)),
378 // allow empty structs and enum variants with braces
379 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
380 (accepted, default_type_params, "1.0.0", None),
381 (accepted, globs, "1.0.0", None),
382 (accepted, if_let, "1.0.0", None),
383 // A temporary feature gate used to enable parser extensions needed
384 // to bootstrap fix for #5723.
385 (accepted, issue_5723_bootstrap, "1.0.0", None),
386 (accepted, macro_rules, "1.0.0", None),
387 // Allows using #![no_std]
388 (accepted, no_std, "1.6.0", None),
389 (accepted, slicing_syntax, "1.0.0", None),
390 (accepted, struct_variant, "1.0.0", None),
391 // These are used to test this portion of the compiler, they don't actually
393 (accepted, test_accepted_feature, "1.0.0", None),
394 (accepted, tuple_indexing, "1.0.0", None),
395 // Allows macros to appear in the type position.
396 (accepted, type_macros, "1.13.0", Some(27245)),
397 (accepted, while_let, "1.0.0", None),
398 // Allows `#[deprecated]` attribute
399 (accepted, deprecated, "1.9.0", Some(29935)),
401 (accepted, question_mark, "1.13.0", Some(31436)),
402 // Allows `..` in tuple (struct) patterns
403 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
404 (accepted, item_like_imports, "1.15.0", Some(35120)),
405 // Allows using `Self` and associated types in struct expressions and patterns.
406 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
407 // elide `'static` lifetimes in `static`s and `const`s
408 (accepted, static_in_const, "1.17.0", Some(35897)),
409 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
410 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
411 // Allows the definition recursive static items.
412 (accepted, static_recursion, "1.17.0", Some(29719)),
413 // pub(restricted) visibilities (RFC 1422)
414 (accepted, pub_restricted, "1.18.0", Some(32409)),
415 // The #![windows_subsystem] attribute
416 (accepted, windows_subsystem, "1.18.0", Some(37499)),
417 // Allows `break {expr}` with a value inside `loop`s.
418 (accepted, loop_break_value, "1.19.0", Some(37339)),
419 // Permits numeric fields in struct expressions and patterns.
420 (accepted, relaxed_adts, "1.19.0", Some(35626)),
421 // Coerces non capturing closures to function pointers
422 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
425 // If you change this, please modify src/doc/unstable-book as well. You must
426 // move that documentation into the relevant place in the other docs, and
427 // remove the chapter on the flag.
429 #[derive(PartialEq, Copy, Clone, Debug)]
430 pub enum AttributeType {
431 /// Normal, builtin attribute that is consumed
432 /// by the compiler before the unused_attribute check
435 /// Builtin attribute that may not be consumed by the compiler
436 /// before the unused_attribute check. These attributes
437 /// will be ignored by the unused_attribute lint
440 /// Builtin attribute that is only allowed at the crate level
444 pub enum AttributeGate {
445 /// Is gated by a given feature gate, reason
446 /// and function to check if enabled
447 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
449 /// Ungated attribute, can be used on all release channels
454 fn is_deprecated(&self) -> bool {
456 Gated(Stability::Deprecated(_), ..) => true,
462 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
465 // Argument is tracking issue link.
466 Deprecated(&'static str),
470 impl ::std::fmt::Debug for AttributeGate {
471 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
473 Gated(ref stab, name, expl, _) =>
474 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
475 Ungated => write!(fmt, "Ungated")
480 macro_rules! cfg_fn {
481 ($field: ident) => {{
482 fn f(features: &Features) -> bool {
485 f as fn(&Features) -> bool
489 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
490 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
493 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
494 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
497 // Attributes that have a special meaning to rustc or rustdoc
498 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
501 ("warn", Normal, Ungated),
502 ("allow", Normal, Ungated),
503 ("forbid", Normal, Ungated),
504 ("deny", Normal, Ungated),
506 ("macro_reexport", Normal, Ungated),
507 ("macro_use", Normal, Ungated),
508 ("macro_export", Normal, Ungated),
509 ("plugin_registrar", Normal, Ungated),
511 ("cfg", Normal, Ungated),
512 ("cfg_attr", Normal, Ungated),
513 ("main", Normal, Ungated),
514 ("start", Normal, Ungated),
515 ("test", Normal, Ungated),
516 ("bench", Normal, Ungated),
517 ("simd", Normal, Ungated),
518 ("repr", Normal, Ungated),
519 ("path", Normal, Ungated),
520 ("abi", Normal, Ungated),
521 ("automatically_derived", Normal, Ungated),
522 ("no_mangle", Normal, Ungated),
523 ("no_link", Normal, Ungated),
524 ("derive", Normal, Ungated),
525 ("should_panic", Normal, Ungated),
526 ("ignore", Normal, Ungated),
527 ("no_implicit_prelude", Normal, Ungated),
528 ("reexport_test_harness_main", Normal, Ungated),
529 ("link_args", Normal, Ungated),
530 ("macro_escape", Normal, Ungated),
533 ("structural_match", Whitelisted, Gated(Stability::Unstable,
535 "the semantics of constant patterns is \
537 cfg_fn!(structural_match))),
539 ("plugin", CrateLevel, Gated(Stability::Unstable,
541 "compiler plugins are experimental \
545 ("no_std", CrateLevel, Ungated),
546 ("no_core", CrateLevel, Gated(Stability::Unstable,
548 "no_core is experimental",
550 ("lang", Normal, Gated(Stability::Unstable,
552 "language items are subject to change",
553 cfg_fn!(lang_items))),
554 ("linkage", Whitelisted, Gated(Stability::Unstable,
556 "the `linkage` attribute is experimental \
557 and not portable across platforms",
559 ("thread_local", Whitelisted, Gated(Stability::Unstable,
561 "`#[thread_local]` is an experimental feature, and does \
562 not currently handle destructors. There is no \
563 corresponding `#[task_local]` mapping to the task \
565 cfg_fn!(thread_local))),
567 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
569 "the `#[rustc_on_unimplemented]` attribute \
570 is an experimental feature",
571 cfg_fn!(on_unimplemented))),
572 ("allocator", Whitelisted, Gated(Stability::Unstable,
574 "the `#[allocator]` attribute is an experimental feature",
575 cfg_fn!(allocator))),
576 ("needs_allocator", Normal, Gated(Stability::Unstable,
578 "the `#[needs_allocator]` \
579 attribute is an experimental \
581 cfg_fn!(needs_allocator))),
582 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
584 "the `#[panic_runtime]` attribute is \
585 an experimental feature",
586 cfg_fn!(panic_runtime))),
587 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
588 "needs_panic_runtime",
589 "the `#[needs_panic_runtime]` \
590 attribute is an experimental \
592 cfg_fn!(needs_panic_runtime))),
593 ("rustc_variance", Normal, Gated(Stability::Unstable,
595 "the `#[rustc_variance]` attribute \
596 is just used for rustc unit tests \
597 and will never be stable",
598 cfg_fn!(rustc_attrs))),
599 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
601 "the `#[rustc_error]` attribute \
602 is just used for rustc unit tests \
603 and will never be stable",
604 cfg_fn!(rustc_attrs))),
605 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
607 "the `#[rustc_if_this_changed]` attribute \
608 is just used for rustc unit tests \
609 and will never be stable",
610 cfg_fn!(rustc_attrs))),
611 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
613 "the `#[rustc_if_this_changed]` attribute \
614 is just used for rustc unit tests \
615 and will never be stable",
616 cfg_fn!(rustc_attrs))),
617 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
619 "the `#[rustc_dirty]` attribute \
620 is just used for rustc unit tests \
621 and will never be stable",
622 cfg_fn!(rustc_attrs))),
623 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
625 "the `#[rustc_clean]` attribute \
626 is just used for rustc unit tests \
627 and will never be stable",
628 cfg_fn!(rustc_attrs))),
629 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
631 "the `#[rustc_metadata_dirty]` attribute \
632 is just used for rustc unit tests \
633 and will never be stable",
634 cfg_fn!(rustc_attrs))),
635 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
637 "the `#[rustc_metadata_clean]` attribute \
638 is just used for rustc unit tests \
639 and will never be stable",
640 cfg_fn!(rustc_attrs))),
641 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
644 is just used for rustc unit tests \
645 and will never be stable",
646 cfg_fn!(rustc_attrs))),
647 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
650 is just used for rustc unit tests \
651 and will never be stable",
652 cfg_fn!(rustc_attrs))),
653 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
655 "internal rustc attributes will never be stable",
656 cfg_fn!(rustc_attrs))),
657 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
659 "internal rustc attributes will never be stable",
660 cfg_fn!(rustc_attrs))),
661 ("rustc_move_fragments", Normal, Gated(Stability::Unstable,
663 "the `#[rustc_move_fragments]` attribute \
664 is just used for rustc unit tests \
665 and will never be stable",
666 cfg_fn!(rustc_attrs))),
667 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
669 "the `#[rustc_mir]` attribute \
670 is just used for rustc unit tests \
671 and will never be stable",
672 cfg_fn!(rustc_attrs))),
673 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
675 "the `#[rustc_inherit_overflow_checks]` \
676 attribute is just used to control \
677 overflow checking behavior of several \
678 libcore functions that are inlined \
679 across crates and will never be stable",
680 cfg_fn!(rustc_attrs))),
681 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
683 "the `#[compiler_builtins]` attribute is used to \
684 identify the `compiler_builtins` crate which \
685 contains compiler-rt intrinsics and will never be \
687 cfg_fn!(compiler_builtins))),
688 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
690 "the `#[sanitizer_runtime]` attribute is used to \
691 identify crates that contain the runtime of a \
692 sanitizer and will never be stable",
693 cfg_fn!(sanitizer_runtime))),
695 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
696 "allow_internal_unstable",
697 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
698 cfg_fn!(allow_internal_unstable))),
700 ("fundamental", Whitelisted, Gated(Stability::Unstable,
702 "the `#[fundamental]` attribute \
703 is an experimental feature",
704 cfg_fn!(fundamental))),
706 ("proc_macro_derive", Normal, Ungated),
708 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
710 "internal implementation detail",
711 cfg_fn!(rustc_attrs))),
713 // FIXME: #14408 whitelist docs since rustdoc looks at them
714 ("doc", Whitelisted, Ungated),
716 // FIXME: #14406 these are processed in trans, which happens after the
718 ("cold", Whitelisted, Ungated),
719 ("naked", Whitelisted, Gated(Stability::Unstable,
721 "the `#[naked]` attribute \
722 is an experimental feature",
723 cfg_fn!(naked_functions))),
724 ("target_feature", Whitelisted, Gated(
725 Stability::Unstable, "target_feature",
726 "the `#[target_feature]` attribute is an experimental feature",
727 cfg_fn!(target_feature))),
728 ("export_name", Whitelisted, Ungated),
729 ("inline", Whitelisted, Ungated),
730 ("link", Whitelisted, Ungated),
731 ("link_name", Whitelisted, Ungated),
732 ("link_section", Whitelisted, Ungated),
733 ("no_builtins", Whitelisted, Ungated),
734 ("no_mangle", Whitelisted, Ungated),
735 ("no_debug", Whitelisted, Gated(
736 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
738 "the `#[no_debug]` attribute is an experimental feature",
740 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
741 "omit_gdb_pretty_printer_section",
742 "the `#[omit_gdb_pretty_printer_section]` \
743 attribute is just used for the Rust test \
745 cfg_fn!(omit_gdb_pretty_printer_section))),
746 ("unsafe_destructor_blind_to_params",
748 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
749 "dropck_parametricity",
750 "unsafe_destructor_blind_to_params has been replaced by \
751 may_dangle and will be removed in the future",
752 cfg_fn!(dropck_parametricity))),
755 Gated(Stability::Unstable,
757 "may_dangle has unstable semantics and may be removed in the future",
758 cfg_fn!(dropck_eyepatch))),
759 ("unwind", Whitelisted, Gated(Stability::Unstable,
761 "#[unwind] is experimental",
762 cfg_fn!(unwind_attributes))),
763 ("used", Whitelisted, Gated(
764 Stability::Unstable, "used",
765 "the `#[used]` attribute is an experimental feature",
769 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
771 "`#[prelude_import]` is for use by rustc only",
772 cfg_fn!(prelude_import))),
774 // FIXME: #14407 these are only looked at on-demand so we can't
775 // guarantee they'll have already been checked
776 ("rustc_deprecated", Whitelisted, Ungated),
777 ("must_use", Whitelisted, Ungated),
778 ("stable", Whitelisted, Ungated),
779 ("unstable", Whitelisted, Ungated),
780 ("deprecated", Normal, Ungated),
782 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
784 "unboxed_closures are still evolving",
785 cfg_fn!(unboxed_closures))),
787 ("windows_subsystem", Whitelisted, Ungated),
789 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
791 "attribute proc macros are currently unstable",
792 cfg_fn!(proc_macro))),
794 ("proc_macro", Normal, Gated(Stability::Unstable,
796 "function-like proc macros are currently unstable",
797 cfg_fn!(proc_macro))),
799 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
800 "rustc_derive_registrar",
801 "used internally by rustc",
802 cfg_fn!(rustc_attrs))),
804 // Crate level attributes
805 ("crate_name", CrateLevel, Ungated),
806 ("crate_type", CrateLevel, Ungated),
807 ("crate_id", CrateLevel, Ungated),
808 ("feature", CrateLevel, Ungated),
809 ("no_start", CrateLevel, Ungated),
810 ("no_main", CrateLevel, Ungated),
811 ("no_builtins", CrateLevel, Ungated),
812 ("recursion_limit", CrateLevel, Ungated),
813 ("type_length_limit", CrateLevel, Ungated),
816 // cfg(...)'s that are feature gated
817 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
818 // (name in cfg, feature, function to check if the feature is enabled)
819 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
820 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
821 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
822 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
825 #[derive(Debug, Eq, PartialEq)]
826 pub struct GatedCfg {
832 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
833 let name = cfg.name().as_str();
835 .position(|info| info.0 == name)
844 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
845 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
846 if !has_feature(features) && !self.span.allows_unstable() {
847 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
848 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
854 features: &'a Features,
855 parse_sess: &'a ParseSess,
856 plugin_attributes: &'a [(String, AttributeType)],
859 macro_rules! gate_feature_fn {
860 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
861 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
862 let has_feature: bool = has_feature(&$cx.features);
863 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
864 if !has_feature && !span.allows_unstable() {
865 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
870 macro_rules! gate_feature {
871 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
872 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
876 impl<'a> Context<'a> {
877 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
878 debug!("check_attribute(attr = {:?})", attr);
879 let name = unwrap_or!(attr.name(), return).as_str();
880 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
882 if let Gated(_, name, desc, ref has_feature) = *gateage {
883 gate_feature_fn!(self, has_feature, attr.span, name, desc);
885 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
889 for &(ref n, ref ty) in self.plugin_attributes {
890 if attr.path == &**n {
891 // Plugins can't gate attributes, so we don't check for it
892 // unlike the code above; we only use this loop to
893 // short-circuit to avoid the checks below
894 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
898 if name.starts_with("rustc_") {
899 gate_feature!(self, rustc_attrs, attr.span,
900 "unless otherwise specified, attributes \
901 with the prefix `rustc_` \
902 are reserved for internal compiler diagnostics");
903 } else if name.starts_with("derive_") {
904 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
905 } else if !attr::is_known(attr) {
906 // Only run the custom attribute lint during regular
907 // feature gate checking. Macro gating runs
908 // before the plugin attributes are registered
909 // so we skip this then
911 gate_feature!(self, custom_attribute, attr.span,
912 &format!("The attribute `{}` is currently \
913 unknown to the compiler and \
915 added to it in the future",
922 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
923 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
924 cx.check_attribute(attr, true);
927 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
928 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
931 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
932 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
934 // FIXME (#28244): enforce that active features have issue numbers
935 // assert!(issue.is_some())
938 // search in Accepted, Removed, or Stable Removed features
939 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
940 .find(|t| t.0 == feature);
942 Some(&(_, _, issue)) => issue,
943 None => panic!("Feature `{}` is not declared anywhere", feature),
953 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
955 feature_err(sess, feature, span, issue, explain).emit();
958 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
959 explain: &str) -> DiagnosticBuilder<'a> {
960 let diag = &sess.span_diagnostic;
962 let issue = match issue {
963 GateIssue::Language => find_lang_feature_issue(feature),
964 GateIssue::Library(lib) => lib,
967 let mut err = if let Some(n) = issue {
968 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
970 diag.struct_span_err(span, explain)
973 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
974 if sess.unstable_features.is_nightly_build() {
975 err.help(&format!("add #![feature({})] to the \
976 crate attributes to enable",
983 const EXPLAIN_BOX_SYNTAX: &'static str =
984 "box expression syntax is experimental; you can call `Box::new` instead.";
986 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
987 "attributes on non-item statements and expressions are experimental.";
989 pub const EXPLAIN_ASM: &'static str =
990 "inline assembly is not stable enough for use and is subject to change";
992 pub const EXPLAIN_GLOBAL_ASM: &'static str =
993 "`global_asm!` is not stable enough for use and is subject to change";
995 pub const EXPLAIN_LOG_SYNTAX: &'static str =
996 "`log_syntax!` is not stable enough for use and is subject to change";
998 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
999 "`concat_idents` is not stable enough for use and is subject to change";
1001 pub const EXPLAIN_TRACE_MACROS: &'static str =
1002 "`trace_macros` is not stable enough for use and is subject to change";
1003 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1004 "allow_internal_unstable side-steps feature gating and stability checks";
1006 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1007 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1009 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1010 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1011 Prefer using procedural macro custom derive.";
1013 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1014 "attributes of the form `#[derive_*]` are reserved for the compiler";
1016 pub const EXPLAIN_VIS_MATCHER: &'static str =
1017 ":vis fragment specifier is experimental and subject to change";
1019 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1020 "placement-in expression syntax is experimental and subject to change.";
1022 struct PostExpansionVisitor<'a> {
1023 context: &'a Context<'a>,
1026 macro_rules! gate_feature_post {
1027 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1028 let (cx, span) = ($cx, $span);
1029 if !span.allows_unstable() {
1030 gate_feature!(cx.context, $feature, span, $explain)
1035 impl<'a> PostExpansionVisitor<'a> {
1036 fn check_abi(&self, abi: Abi, span: Span) {
1038 Abi::RustIntrinsic => {
1039 gate_feature_post!(&self, intrinsics, span,
1040 "intrinsics are subject to change");
1042 Abi::PlatformIntrinsic => {
1043 gate_feature_post!(&self, platform_intrinsics, span,
1044 "platform intrinsics are experimental and possibly buggy");
1046 Abi::Vectorcall => {
1047 gate_feature_post!(&self, abi_vectorcall, span,
1048 "vectorcall is experimental and subject to change");
1051 gate_feature_post!(&self, unboxed_closures, span,
1052 "rust-call ABI is subject to change");
1055 gate_feature_post!(&self, abi_sysv64, span,
1056 "sysv64 ABI is experimental and subject to change");
1059 gate_feature_post!(&self, abi_ptx, span,
1060 "PTX ABIs are experimental and subject to change");
1062 Abi::Unadjusted => {
1063 gate_feature_post!(&self, abi_unadjusted, span,
1064 "unadjusted ABI is an implementation detail and perma-unstable");
1066 Abi::Msp430Interrupt => {
1067 gate_feature_post!(&self, abi_msp430_interrupt, span,
1068 "msp430-interrupt ABI is experimental and subject to change");
1070 Abi::X86Interrupt => {
1071 gate_feature_post!(&self, abi_x86_interrupt, span,
1072 "x86-interrupt ABI is experimental and subject to change");
1087 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1088 use ast::MetaItemKind::*;
1089 use ast::NestedMetaItemKind::*;
1093 NameValue(ref lit) => !lit.node.is_str(),
1094 List(ref list) => list.iter().any(|li| {
1096 MetaItem(ref mi) => contains_novel_literal(mi),
1103 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1104 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1105 if !attr.span.allows_unstable() {
1106 // check for gated attributes
1107 self.context.check_attribute(attr, false);
1110 if self.context.features.proc_macro && attr::is_known(attr) {
1114 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1115 if contains_novel_literal(&meta) {
1116 gate_feature_post!(&self, attr_literals, attr.span,
1117 "non-string literals in attributes, or string \
1118 literals in top-level positions, are experimental");
1122 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1123 if !name.as_str().is_ascii() {
1124 gate_feature_post!(&self, non_ascii_idents, sp,
1125 "non-ascii idents are not fully supported.");
1129 fn visit_item(&mut self, i: &'a ast::Item) {
1131 ast::ItemKind::ExternCrate(_) => {
1132 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1133 gate_feature_post!(&self, macro_reexport, i.span,
1134 "macros reexports are experimental \
1135 and possibly buggy");
1139 ast::ItemKind::ForeignMod(ref foreign_module) => {
1140 if attr::contains_name(&i.attrs[..], "link_args") {
1141 gate_feature_post!(&self, link_args, i.span,
1142 "the `link_args` attribute is not portable \
1143 across platforms, it is recommended to \
1144 use `#[link(name = \"foo\")]` instead")
1146 self.check_abi(foreign_module.abi, i.span);
1149 ast::ItemKind::Fn(..) => {
1150 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1151 gate_feature_post!(&self, plugin_registrar, i.span,
1152 "compiler plugins are experimental and possibly buggy");
1154 if attr::contains_name(&i.attrs[..], "start") {
1155 gate_feature_post!(&self, start, i.span,
1156 "a #[start] function is an experimental \
1157 feature whose signature may change \
1160 if attr::contains_name(&i.attrs[..], "main") {
1161 gate_feature_post!(&self, main, i.span,
1162 "declaration of a nonstandard #[main] \
1163 function may change over time, for now \
1164 a top-level `fn main()` is required");
1168 ast::ItemKind::Struct(..) => {
1169 if attr::contains_name(&i.attrs[..], "simd") {
1170 gate_feature_post!(&self, simd, i.span,
1171 "SIMD types are experimental and possibly buggy");
1172 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1173 "the `#[simd]` attribute \
1174 is deprecated, use \
1175 `#[repr(simd)]` instead");
1177 for attr in &i.attrs {
1178 if attr.path == "repr" {
1179 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1180 if item.check_name("simd") {
1181 gate_feature_post!(&self, repr_simd, i.span,
1182 "SIMD types are experimental \
1183 and possibly buggy");
1186 if item.check_name("align") {
1187 gate_feature_post!(&self, repr_align, i.span,
1188 "the struct `#[repr(align(u16))]` attribute \
1196 ast::ItemKind::Union(..) => {
1197 gate_feature_post!(&self, untagged_unions,
1199 "unions are unstable and possibly buggy");
1202 ast::ItemKind::DefaultImpl(..) => {
1203 gate_feature_post!(&self, optin_builtin_traits,
1205 "default trait implementations are experimental \
1206 and possibly buggy");
1209 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1210 if polarity == ast::ImplPolarity::Negative {
1211 gate_feature_post!(&self, optin_builtin_traits,
1213 "negative trait bounds are not yet fully implemented; \
1214 use marker types for now");
1217 if let ast::Defaultness::Default = defaultness {
1218 gate_feature_post!(&self, specialization,
1220 "specialization is unstable");
1227 visit::walk_item(self, i);
1230 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1231 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1232 Some(val) => val.as_str().starts_with("llvm."),
1236 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1237 "linking to LLVM intrinsics is experimental");
1240 visit::walk_foreign_item(self, i)
1243 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1245 ast::TyKind::BareFn(ref bare_fn_ty) => {
1246 self.check_abi(bare_fn_ty.abi, ty.span);
1248 ast::TyKind::ImplTrait(..) => {
1249 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1250 "`impl Trait` is experimental");
1252 ast::TyKind::Never => {
1253 gate_feature_post!(&self, never_type, ty.span,
1254 "The `!` type is experimental");
1258 visit::walk_ty(self, ty)
1261 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1262 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1263 if output_ty.node != ast::TyKind::Never {
1264 self.visit_ty(output_ty)
1269 fn visit_expr(&mut self, e: &'a ast::Expr) {
1271 ast::ExprKind::Box(_) => {
1272 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1274 ast::ExprKind::Type(..) => {
1275 gate_feature_post!(&self, type_ascription, e.span,
1276 "type ascription is experimental");
1278 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1279 gate_feature_post!(&self, inclusive_range_syntax,
1281 "inclusive range syntax is experimental");
1283 ast::ExprKind::InPlace(..) => {
1284 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1286 ast::ExprKind::Lit(ref lit) => {
1287 if let ast::LitKind::Int(_, ref ty) = lit.node {
1289 ast::LitIntType::Signed(ast::IntTy::I128) |
1290 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1291 gate_feature_post!(&self, i128_type, e.span,
1292 "128-bit integers are not stable");
1298 ast::ExprKind::Catch(_) => {
1299 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1303 visit::walk_expr(self, e);
1306 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1307 match pattern.node {
1308 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1309 gate_feature_post!(&self, advanced_slice_patterns,
1311 "multiple-element slice matches anywhere \
1312 but at the end of a slice (e.g. \
1313 `[0, ..xs, 0]`) are experimental")
1315 PatKind::Slice(..) => {
1316 gate_feature_post!(&self, slice_patterns,
1318 "slice pattern syntax is experimental");
1320 PatKind::Box(..) => {
1321 gate_feature_post!(&self, box_patterns,
1323 "box pattern syntax is experimental");
1325 PatKind::Range(_, _, RangeEnd::Excluded) => {
1326 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1327 "exclusive range pattern syntax is experimental");
1331 visit::walk_pat(self, pattern)
1334 fn visit_fn(&mut self,
1335 fn_kind: FnKind<'a>,
1336 fn_decl: &'a ast::FnDecl,
1339 // check for const fn declarations
1340 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1342 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
1350 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1351 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1352 self.check_abi(abi, span);
1356 visit::walk_fn(self, fn_kind, fn_decl, span);
1359 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1361 ast::TraitItemKind::Const(..) => {
1362 gate_feature_post!(&self, associated_consts,
1364 "associated constants are experimental")
1366 ast::TraitItemKind::Method(ref sig, ref block) => {
1367 if block.is_none() {
1368 self.check_abi(sig.abi, ti.span);
1370 if sig.constness.node == ast::Constness::Const {
1371 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1374 ast::TraitItemKind::Type(_, Some(_)) => {
1375 gate_feature_post!(&self, associated_type_defaults, ti.span,
1376 "associated type defaults are unstable");
1380 visit::walk_trait_item(self, ti);
1383 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1384 if ii.defaultness == ast::Defaultness::Default {
1385 gate_feature_post!(&self, specialization,
1387 "specialization is unstable");
1391 ast::ImplItemKind::Const(..) => {
1392 gate_feature_post!(&self, associated_consts,
1394 "associated constants are experimental")
1396 ast::ImplItemKind::Method(ref sig, _) => {
1397 if sig.constness.node == ast::Constness::Const {
1398 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1403 visit::walk_impl_item(self, ii);
1406 fn visit_generics(&mut self, g: &'a ast::Generics) {
1407 for t in &g.ty_params {
1408 if !t.attrs.is_empty() {
1409 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1410 "attributes on type parameter bindings are experimental");
1413 visit::walk_generics(self, g)
1416 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1417 if !lifetime_def.attrs.is_empty() {
1418 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1419 "attributes on lifetime bindings are experimental");
1421 visit::walk_lifetime_def(self, lifetime_def)
1425 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1426 let mut features = Features::new();
1428 let mut feature_checker = MutexFeatureChecker::default();
1430 for attr in krate_attrs {
1431 if !attr.check_name("feature") {
1435 match attr.meta_item_list() {
1437 span_err!(span_handler, attr.span, E0555,
1438 "malformed feature attribute, expected #![feature(...)]");
1442 let name = if let Some(word) = mi.word() {
1445 span_err!(span_handler, mi.span, E0556,
1446 "malformed feature, expected just one word");
1450 if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
1451 .find(|& &(n, _, _, _)| name == n) {
1452 *(setter(&mut features)) = true;
1453 feature_checker.collect(&features, mi.span);
1455 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1456 .find(|& &(n, _, _)| name == n)
1457 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1458 .find(|& &(n, _, _)| name == n)) {
1459 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1461 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1462 .find(|& &(n, _, _)| name == n) {
1463 features.declared_stable_lang_features.push((name, mi.span));
1465 features.declared_lib_features.push((name, mi.span));
1472 feature_checker.check(span_handler);
1477 // A collector for mutually-exclusive features and their flag spans
1479 struct MutexFeatureChecker {
1480 proc_macro: Option<Span>,
1481 custom_attribute: Option<Span>,
1484 impl MutexFeatureChecker {
1485 // If this method turns out to be a hotspot due to branching,
1486 // the branching can be eliminated by modifying `setter!()` to set these spans
1487 // only for the features that need to be checked for mutual exclusion.
1488 fn collect(&mut self, features: &Features, span: Span) {
1489 if features.proc_macro {
1490 // If self.proc_macro is None, set to Some(span)
1491 self.proc_macro = self.proc_macro.or(Some(span));
1494 if features.custom_attribute {
1495 self.custom_attribute = self.custom_attribute.or(Some(span));
1499 fn check(self, handler: &Handler) {
1500 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1501 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1502 `#![feature(custom_attribute)] at the same time")
1503 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1511 pub fn check_crate(krate: &ast::Crate,
1513 features: &Features,
1514 plugin_attributes: &[(String, AttributeType)],
1515 unstable: UnstableFeatures) {
1516 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1520 plugin_attributes: plugin_attributes,
1522 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1525 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1526 pub enum UnstableFeatures {
1527 /// Hard errors for unstable features are active, as on
1528 /// beta/stable channels.
1530 /// Allow features to be activated, as on nightly.
1532 /// Errors are bypassed for bootstrapping. This is required any time
1533 /// during the build that feature-related lints are set to warn or above
1534 /// because the build turns on warnings-as-errors and uses lots of unstable
1535 /// features. As a result, this is always required for building Rust itself.
1539 impl UnstableFeatures {
1540 pub fn from_environment() -> UnstableFeatures {
1541 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1542 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1543 // Whether we should enable unstable features for bootstrapping
1544 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1545 match (disable_unstable_features, bootstrap) {
1546 (_, true) => UnstableFeatures::Cheat,
1547 (true, _) => UnstableFeatures::Disallow,
1548 (false, _) => UnstableFeatures::Allow
1552 pub fn is_nightly_build(&self) -> bool {
1554 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1560 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1561 unstable: UnstableFeatures) {
1562 let allow_features = match unstable {
1563 UnstableFeatures::Allow => true,
1564 UnstableFeatures::Disallow => false,
1565 UnstableFeatures::Cheat => true
1567 if !allow_features {
1568 for attr in &krate.attrs {
1569 if attr.check_name("feature") {
1570 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1571 span_err!(span_handler, attr.span, E0554,
1572 "#[feature] may not be used on the {} release channel",