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, compile_error, "1.20.0", Some(40872)),
115 (active, concat_idents, "1.0.0", Some(29599)),
116 (active, link_args, "1.0.0", Some(29596)),
117 (active, log_syntax, "1.0.0", Some(29598)),
118 (active, non_ascii_idents, "1.0.0", Some(28979)),
119 (active, plugin_registrar, "1.0.0", Some(29597)),
120 (active, thread_local, "1.0.0", Some(29594)),
121 (active, trace_macros, "1.0.0", Some(29598)),
123 // rustc internal, for now:
124 (active, intrinsics, "1.0.0", None),
125 (active, lang_items, "1.0.0", None),
127 (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
128 (active, linkage, "1.0.0", Some(29603)),
129 (active, quote, "1.0.0", Some(29601)),
130 (active, simd, "1.0.0", Some(27731)),
134 (active, rustc_diagnostic_macros, "1.0.0", None),
135 (active, advanced_slice_patterns, "1.0.0", Some(23121)),
136 (active, box_syntax, "1.0.0", Some(27779)),
137 (active, placement_in_syntax, "1.0.0", Some(27779)),
138 (active, unboxed_closures, "1.0.0", Some(29625)),
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),
309 // Procedural macros 2.0.
310 (active, proc_macro, "1.16.0", Some(38356)),
312 // Declarative macros 2.0 (`macro`).
313 (active, decl_macro, "1.17.0", Some(39412)),
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 // Used to identify crates that contain the profiler runtime
327 (active, profiler_runtime, "1.18.0", None),
329 // `extern "x86-interrupt" fn()`
330 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
333 // Allows the `catch {...}` expression
334 (active, catch_expr, "1.17.0", Some(31436)),
336 // Allows `repr(align(u16))` struct attribute (RFC 1358)
337 (active, repr_align, "1.17.0", Some(33626)),
339 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
340 (active, rvalue_static_promotion, "1.15.1", Some(38865)),
342 // Used to preserve symbols (see llvm.used)
343 (active, used, "1.18.0", Some(40289)),
345 // Allows module-level inline assembly by way of global_asm!()
346 (active, global_asm, "1.18.0", Some(35119)),
348 // Allows overlapping impls of marker traits
349 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
351 // Allows use of the :vis macro fragment specifier
352 (active, macro_vis_matcher, "1.18.0", Some(41022)),
355 (active, abi_thiscall, "1.19.0", None),
357 // Allows a test to fail without failing the whole suite
358 (active, allow_fail, "1.19.0", Some(42219)),
360 // Allows unsized tuple coercion.
361 (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
363 // global allocators and their internals
364 (active, global_allocator, "1.20.0", None),
365 (active, allocator_internals, "1.20.0", None),
369 (removed, import_shadowing, "1.0.0", None),
370 (removed, managed_boxes, "1.0.0", None),
371 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
372 (removed, negate_unsigned, "1.0.0", Some(29645)),
373 (removed, reflect, "1.0.0", Some(27749)),
374 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
375 (removed, opt_out_copy, "1.0.0", None),
376 (removed, quad_precision_float, "1.0.0", None),
377 (removed, struct_inherit, "1.0.0", None),
378 (removed, test_removed_feature, "1.0.0", None),
379 (removed, visible_private_types, "1.0.0", None),
380 (removed, unsafe_no_drop_flag, "1.0.0", None),
381 // Allows using items which are missing stability attributes
383 (removed, unmarked_api, "1.0.0", None),
384 (removed, pushpop_unsafe, "1.2.0", None),
385 (removed, allocator, "1.0.0", None),
389 (stable_removed, no_stack_check, "1.0.0", None),
393 (accepted, associated_types, "1.0.0", None),
394 // allow overloading augmented assignment operations like `a += b`
395 (accepted, augmented_assignments, "1.8.0", Some(28235)),
396 // allow empty structs and enum variants with braces
397 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
398 (accepted, default_type_params, "1.0.0", None),
399 (accepted, globs, "1.0.0", None),
400 (accepted, if_let, "1.0.0", None),
401 // A temporary feature gate used to enable parser extensions needed
402 // to bootstrap fix for #5723.
403 (accepted, issue_5723_bootstrap, "1.0.0", None),
404 (accepted, macro_rules, "1.0.0", None),
405 // Allows using #![no_std]
406 (accepted, no_std, "1.6.0", None),
407 (accepted, slicing_syntax, "1.0.0", None),
408 (accepted, struct_variant, "1.0.0", None),
409 // These are used to test this portion of the compiler, they don't actually
411 (accepted, test_accepted_feature, "1.0.0", None),
412 (accepted, tuple_indexing, "1.0.0", None),
413 // Allows macros to appear in the type position.
414 (accepted, type_macros, "1.13.0", Some(27245)),
415 (accepted, while_let, "1.0.0", None),
416 // Allows `#[deprecated]` attribute
417 (accepted, deprecated, "1.9.0", Some(29935)),
419 (accepted, question_mark, "1.13.0", Some(31436)),
420 // Allows `..` in tuple (struct) patterns
421 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
422 (accepted, item_like_imports, "1.15.0", Some(35120)),
423 // Allows using `Self` and associated types in struct expressions and patterns.
424 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
425 // elide `'static` lifetimes in `static`s and `const`s
426 (accepted, static_in_const, "1.17.0", Some(35897)),
427 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
428 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
429 // Allows the definition recursive static items.
430 (accepted, static_recursion, "1.17.0", Some(29719)),
431 // pub(restricted) visibilities (RFC 1422)
432 (accepted, pub_restricted, "1.18.0", Some(32409)),
433 // The #![windows_subsystem] attribute
434 (accepted, windows_subsystem, "1.18.0", Some(37499)),
435 // Allows `break {expr}` with a value inside `loop`s.
436 (accepted, loop_break_value, "1.19.0", Some(37339)),
437 // Permits numeric fields in struct expressions and patterns.
438 (accepted, relaxed_adts, "1.19.0", Some(35626)),
439 // Coerces non capturing closures to function pointers
440 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
441 // Allows attributes on struct literal fields.
442 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
445 // If you change this, please modify src/doc/unstable-book as well. You must
446 // move that documentation into the relevant place in the other docs, and
447 // remove the chapter on the flag.
449 #[derive(PartialEq, Copy, Clone, Debug)]
450 pub enum AttributeType {
451 /// Normal, builtin attribute that is consumed
452 /// by the compiler before the unused_attribute check
455 /// Builtin attribute that may not be consumed by the compiler
456 /// before the unused_attribute check. These attributes
457 /// will be ignored by the unused_attribute lint
460 /// Builtin attribute that is only allowed at the crate level
464 pub enum AttributeGate {
465 /// Is gated by a given feature gate, reason
466 /// and function to check if enabled
467 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
469 /// Ungated attribute, can be used on all release channels
474 fn is_deprecated(&self) -> bool {
476 Gated(Stability::Deprecated(_), ..) => true,
482 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
485 // Argument is tracking issue link.
486 Deprecated(&'static str),
490 impl ::std::fmt::Debug for AttributeGate {
491 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
493 Gated(ref stab, name, expl, _) =>
494 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
495 Ungated => write!(fmt, "Ungated")
500 macro_rules! cfg_fn {
501 ($field: ident) => {{
502 fn f(features: &Features) -> bool {
505 f as fn(&Features) -> bool
509 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
510 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
513 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
514 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
517 // Attributes that have a special meaning to rustc or rustdoc
518 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
521 ("warn", Normal, Ungated),
522 ("allow", Normal, Ungated),
523 ("forbid", Normal, Ungated),
524 ("deny", Normal, Ungated),
526 ("macro_reexport", Normal, Ungated),
527 ("macro_use", Normal, Ungated),
528 ("macro_export", Normal, Ungated),
529 ("plugin_registrar", Normal, Ungated),
531 ("cfg", Normal, Ungated),
532 ("cfg_attr", Normal, Ungated),
533 ("main", Normal, Ungated),
534 ("start", Normal, Ungated),
535 ("test", Normal, Ungated),
536 ("bench", Normal, Ungated),
537 ("simd", Normal, Ungated),
538 ("repr", Normal, Ungated),
539 ("path", Normal, Ungated),
540 ("abi", Normal, Ungated),
541 ("automatically_derived", Normal, Ungated),
542 ("no_mangle", Normal, Ungated),
543 ("no_link", Normal, Ungated),
544 ("derive", Normal, Ungated),
545 ("should_panic", Normal, Ungated),
546 ("ignore", Normal, Ungated),
547 ("no_implicit_prelude", Normal, Ungated),
548 ("reexport_test_harness_main", Normal, Ungated),
549 ("link_args", Normal, Ungated),
550 ("macro_escape", Normal, Ungated),
553 ("structural_match", Whitelisted, Gated(Stability::Unstable,
555 "the semantics of constant patterns is \
557 cfg_fn!(structural_match))),
559 ("plugin", CrateLevel, Gated(Stability::Unstable,
561 "compiler plugins are experimental \
565 ("no_std", CrateLevel, Ungated),
566 ("no_core", CrateLevel, Gated(Stability::Unstable,
568 "no_core is experimental",
570 ("lang", Normal, Gated(Stability::Unstable,
572 "language items are subject to change",
573 cfg_fn!(lang_items))),
574 ("linkage", Whitelisted, Gated(Stability::Unstable,
576 "the `linkage` attribute is experimental \
577 and not portable across platforms",
579 ("thread_local", Whitelisted, Gated(Stability::Unstable,
581 "`#[thread_local]` is an experimental feature, and does \
582 not currently handle destructors. There is no \
583 corresponding `#[task_local]` mapping to the task \
585 cfg_fn!(thread_local))),
587 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
589 "the `#[rustc_on_unimplemented]` attribute \
590 is an experimental feature",
591 cfg_fn!(on_unimplemented))),
592 ("global_allocator", Normal, Gated(Stability::Unstable,
594 "the `#[global_allocator]` attribute is \
595 an experimental feature",
596 cfg_fn!(global_allocator))),
597 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
598 "allocator_internals",
599 "the `#[default_lib_allocator]` \
600 attribute is an experimental feature",
601 cfg_fn!(allocator_internals))),
602 ("needs_allocator", Normal, Gated(Stability::Unstable,
603 "allocator_internals",
604 "the `#[needs_allocator]` \
605 attribute is an experimental \
607 cfg_fn!(allocator_internals))),
608 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
610 "the `#[panic_runtime]` attribute is \
611 an experimental feature",
612 cfg_fn!(panic_runtime))),
613 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
614 "needs_panic_runtime",
615 "the `#[needs_panic_runtime]` \
616 attribute is an experimental \
618 cfg_fn!(needs_panic_runtime))),
619 ("rustc_variance", Normal, Gated(Stability::Unstable,
621 "the `#[rustc_variance]` attribute \
622 is just used for rustc unit tests \
623 and will never be stable",
624 cfg_fn!(rustc_attrs))),
625 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
627 "the `#[rustc_error]` attribute \
628 is just used for rustc unit tests \
629 and will never be stable",
630 cfg_fn!(rustc_attrs))),
631 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
633 "the `#[rustc_if_this_changed]` attribute \
634 is just used for rustc unit tests \
635 and will never be stable",
636 cfg_fn!(rustc_attrs))),
637 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
639 "the `#[rustc_if_this_changed]` attribute \
640 is just used for rustc unit tests \
641 and will never be stable",
642 cfg_fn!(rustc_attrs))),
643 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
645 "the `#[rustc_dirty]` attribute \
646 is just used for rustc unit tests \
647 and will never be stable",
648 cfg_fn!(rustc_attrs))),
649 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
651 "the `#[rustc_clean]` attribute \
652 is just used for rustc unit tests \
653 and will never be stable",
654 cfg_fn!(rustc_attrs))),
655 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
657 "the `#[rustc_metadata_dirty]` attribute \
658 is just used for rustc unit tests \
659 and will never be stable",
660 cfg_fn!(rustc_attrs))),
661 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
663 "the `#[rustc_metadata_clean]` attribute \
664 is just used for rustc unit tests \
665 and will never be stable",
666 cfg_fn!(rustc_attrs))),
667 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
670 is just used for rustc unit tests \
671 and will never be stable",
672 cfg_fn!(rustc_attrs))),
673 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
676 is just used for rustc unit tests \
677 and will never be stable",
678 cfg_fn!(rustc_attrs))),
679 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
681 "internal rustc attributes will never be stable",
682 cfg_fn!(rustc_attrs))),
683 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
685 "internal rustc attributes will never be stable",
686 cfg_fn!(rustc_attrs))),
687 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
689 "the `#[rustc_mir]` attribute \
690 is just used for rustc unit tests \
691 and will never be stable",
692 cfg_fn!(rustc_attrs))),
693 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
695 "the `#[rustc_inherit_overflow_checks]` \
696 attribute is just used to control \
697 overflow checking behavior of several \
698 libcore functions that are inlined \
699 across crates and will never be stable",
700 cfg_fn!(rustc_attrs))),
701 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
703 "the `#[compiler_builtins]` attribute is used to \
704 identify the `compiler_builtins` crate which \
705 contains compiler-rt intrinsics and will never be \
707 cfg_fn!(compiler_builtins))),
708 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
710 "the `#[sanitizer_runtime]` attribute is used to \
711 identify crates that contain the runtime of a \
712 sanitizer and will never be stable",
713 cfg_fn!(sanitizer_runtime))),
714 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
716 "the `#[profiler_runtime]` attribute is used to \
717 identify the `profiler_builtins` crate which \
718 contains the profiler runtime and will never be \
720 cfg_fn!(profiler_runtime))),
722 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
723 "allow_internal_unstable",
724 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
725 cfg_fn!(allow_internal_unstable))),
727 ("fundamental", Whitelisted, Gated(Stability::Unstable,
729 "the `#[fundamental]` attribute \
730 is an experimental feature",
731 cfg_fn!(fundamental))),
733 ("proc_macro_derive", Normal, Ungated),
735 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
737 "internal implementation detail",
738 cfg_fn!(rustc_attrs))),
740 // FIXME: #14408 whitelist docs since rustdoc looks at them
741 ("doc", Whitelisted, Ungated),
743 // FIXME: #14406 these are processed in trans, which happens after the
745 ("cold", Whitelisted, Ungated),
746 ("naked", Whitelisted, Gated(Stability::Unstable,
748 "the `#[naked]` attribute \
749 is an experimental feature",
750 cfg_fn!(naked_functions))),
751 ("target_feature", Whitelisted, Gated(
752 Stability::Unstable, "target_feature",
753 "the `#[target_feature]` attribute is an experimental feature",
754 cfg_fn!(target_feature))),
755 ("export_name", Whitelisted, Ungated),
756 ("inline", Whitelisted, Ungated),
757 ("link", Whitelisted, Ungated),
758 ("link_name", Whitelisted, Ungated),
759 ("link_section", Whitelisted, Ungated),
760 ("no_builtins", Whitelisted, Ungated),
761 ("no_mangle", Whitelisted, Ungated),
762 ("no_debug", Whitelisted, Gated(
763 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
765 "the `#[no_debug]` attribute is an experimental feature",
767 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
768 "omit_gdb_pretty_printer_section",
769 "the `#[omit_gdb_pretty_printer_section]` \
770 attribute is just used for the Rust test \
772 cfg_fn!(omit_gdb_pretty_printer_section))),
773 ("unsafe_destructor_blind_to_params",
775 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
776 "dropck_parametricity",
777 "unsafe_destructor_blind_to_params has been replaced by \
778 may_dangle and will be removed in the future",
779 cfg_fn!(dropck_parametricity))),
782 Gated(Stability::Unstable,
784 "may_dangle has unstable semantics and may be removed in the future",
785 cfg_fn!(dropck_eyepatch))),
786 ("unwind", Whitelisted, Gated(Stability::Unstable,
788 "#[unwind] is experimental",
789 cfg_fn!(unwind_attributes))),
790 ("used", Whitelisted, Gated(
791 Stability::Unstable, "used",
792 "the `#[used]` attribute is an experimental feature",
796 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
798 "`#[prelude_import]` is for use by rustc only",
799 cfg_fn!(prelude_import))),
801 // FIXME: #14407 these are only looked at on-demand so we can't
802 // guarantee they'll have already been checked
803 ("rustc_deprecated", Whitelisted, Ungated),
804 ("must_use", Whitelisted, Ungated),
805 ("stable", Whitelisted, Ungated),
806 ("unstable", Whitelisted, Ungated),
807 ("deprecated", Normal, Ungated),
809 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
811 "unboxed_closures are still evolving",
812 cfg_fn!(unboxed_closures))),
814 ("windows_subsystem", Whitelisted, Ungated),
816 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
818 "attribute proc macros are currently unstable",
819 cfg_fn!(proc_macro))),
821 ("proc_macro", Normal, Gated(Stability::Unstable,
823 "function-like proc macros are currently unstable",
824 cfg_fn!(proc_macro))),
826 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
827 "rustc_derive_registrar",
828 "used internally by rustc",
829 cfg_fn!(rustc_attrs))),
831 ("allow_fail", Normal, Gated(Stability::Unstable,
833 "allow_fail attribute is currently unstable",
834 cfg_fn!(allow_fail))),
836 // Crate level attributes
837 ("crate_name", CrateLevel, Ungated),
838 ("crate_type", CrateLevel, Ungated),
839 ("crate_id", CrateLevel, Ungated),
840 ("feature", CrateLevel, Ungated),
841 ("no_start", CrateLevel, Ungated),
842 ("no_main", CrateLevel, Ungated),
843 ("no_builtins", CrateLevel, Ungated),
844 ("recursion_limit", CrateLevel, Ungated),
845 ("type_length_limit", CrateLevel, Ungated),
848 // cfg(...)'s that are feature gated
849 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
850 // (name in cfg, feature, function to check if the feature is enabled)
851 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
852 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
853 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
854 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
857 #[derive(Debug, Eq, PartialEq)]
858 pub struct GatedCfg {
864 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
865 let name = cfg.name().as_str();
867 .position(|info| info.0 == name)
876 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
877 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
878 if !has_feature(features) && !self.span.allows_unstable() {
879 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
880 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
886 features: &'a Features,
887 parse_sess: &'a ParseSess,
888 plugin_attributes: &'a [(String, AttributeType)],
891 macro_rules! gate_feature_fn {
892 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
893 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
894 let has_feature: bool = has_feature(&$cx.features);
895 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
896 if !has_feature && !span.allows_unstable() {
897 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
902 macro_rules! gate_feature {
903 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
904 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
908 impl<'a> Context<'a> {
909 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
910 debug!("check_attribute(attr = {:?})", attr);
911 let name = unwrap_or!(attr.name(), return).as_str();
912 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
914 if let Gated(_, name, desc, ref has_feature) = *gateage {
915 gate_feature_fn!(self, has_feature, attr.span, name, desc);
917 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
921 for &(ref n, ref ty) in self.plugin_attributes {
922 if attr.path == &**n {
923 // Plugins can't gate attributes, so we don't check for it
924 // unlike the code above; we only use this loop to
925 // short-circuit to avoid the checks below
926 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
930 if name.starts_with("rustc_") {
931 gate_feature!(self, rustc_attrs, attr.span,
932 "unless otherwise specified, attributes \
933 with the prefix `rustc_` \
934 are reserved for internal compiler diagnostics");
935 } else if name.starts_with("derive_") {
936 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
937 } else if !attr::is_known(attr) {
938 // Only run the custom attribute lint during regular
939 // feature gate checking. Macro gating runs
940 // before the plugin attributes are registered
941 // so we skip this then
943 gate_feature!(self, custom_attribute, attr.span,
944 &format!("The attribute `{}` is currently \
945 unknown to the compiler and \
947 added to it in the future",
954 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
955 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
956 cx.check_attribute(attr, true);
959 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
960 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
963 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
964 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
966 // FIXME (#28244): enforce that active features have issue numbers
967 // assert!(issue.is_some())
970 // search in Accepted, Removed, or Stable Removed features
971 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
972 .find(|t| t.0 == feature);
974 Some(&(_, _, issue)) => issue,
975 None => panic!("Feature `{}` is not declared anywhere", feature),
985 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
987 feature_err(sess, feature, span, issue, explain).emit();
990 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
991 explain: &str) -> DiagnosticBuilder<'a> {
992 let diag = &sess.span_diagnostic;
994 let issue = match issue {
995 GateIssue::Language => find_lang_feature_issue(feature),
996 GateIssue::Library(lib) => lib,
999 let mut err = if let Some(n) = issue {
1000 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
1002 diag.struct_span_err(span, explain)
1005 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1006 if sess.unstable_features.is_nightly_build() {
1007 err.help(&format!("add #![feature({})] to the \
1008 crate attributes to enable",
1015 const EXPLAIN_BOX_SYNTAX: &'static str =
1016 "box expression syntax is experimental; you can call `Box::new` instead.";
1018 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1019 "attributes on non-item statements and expressions are experimental.";
1021 pub const EXPLAIN_ASM: &'static str =
1022 "inline assembly is not stable enough for use and is subject to change";
1024 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1025 "`global_asm!` is not stable enough for use and is subject to change";
1027 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1028 "`log_syntax!` is not stable enough for use and is subject to change";
1030 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1031 "`concat_idents` is not stable enough for use and is subject to change";
1033 pub const EXPLAIN_COMPILE_ERROR: &'static str =
1034 "`compile_error` is not stable enough for use and is subject to change";
1036 pub const EXPLAIN_TRACE_MACROS: &'static str =
1037 "`trace_macros` is not stable enough for use and is subject to change";
1038 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1039 "allow_internal_unstable side-steps feature gating and stability checks";
1041 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1042 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1044 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1045 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1046 Prefer using procedural macro custom derive.";
1048 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1049 "attributes of the form `#[derive_*]` are reserved for the compiler";
1051 pub const EXPLAIN_VIS_MATCHER: &'static str =
1052 ":vis fragment specifier is experimental and subject to change";
1054 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1055 "placement-in expression syntax is experimental and subject to change.";
1057 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1058 "Unsized tuple coercion is not stable enough for use and is subject to change";
1060 struct PostExpansionVisitor<'a> {
1061 context: &'a Context<'a>,
1064 macro_rules! gate_feature_post {
1065 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1066 let (cx, span) = ($cx, $span);
1067 if !span.allows_unstable() {
1068 gate_feature!(cx.context, $feature, span, $explain)
1073 impl<'a> PostExpansionVisitor<'a> {
1074 fn check_abi(&self, abi: Abi, span: Span) {
1076 Abi::RustIntrinsic => {
1077 gate_feature_post!(&self, intrinsics, span,
1078 "intrinsics are subject to change");
1080 Abi::PlatformIntrinsic => {
1081 gate_feature_post!(&self, platform_intrinsics, span,
1082 "platform intrinsics are experimental and possibly buggy");
1084 Abi::Vectorcall => {
1085 gate_feature_post!(&self, abi_vectorcall, span,
1086 "vectorcall is experimental and subject to change");
1089 gate_feature_post!(&self, abi_thiscall, span,
1090 "thiscall is experimental and subject to change");
1093 gate_feature_post!(&self, unboxed_closures, span,
1094 "rust-call ABI is subject to change");
1097 gate_feature_post!(&self, abi_sysv64, span,
1098 "sysv64 ABI is experimental and subject to change");
1101 gate_feature_post!(&self, abi_ptx, span,
1102 "PTX ABIs are experimental and subject to change");
1104 Abi::Unadjusted => {
1105 gate_feature_post!(&self, abi_unadjusted, span,
1106 "unadjusted ABI is an implementation detail and perma-unstable");
1108 Abi::Msp430Interrupt => {
1109 gate_feature_post!(&self, abi_msp430_interrupt, span,
1110 "msp430-interrupt ABI is experimental and subject to change");
1112 Abi::X86Interrupt => {
1113 gate_feature_post!(&self, abi_x86_interrupt, span,
1114 "x86-interrupt ABI is experimental and subject to change");
1129 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1130 use ast::MetaItemKind::*;
1131 use ast::NestedMetaItemKind::*;
1135 NameValue(ref lit) => !lit.node.is_str(),
1136 List(ref list) => list.iter().any(|li| {
1138 MetaItem(ref mi) => contains_novel_literal(mi),
1145 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1146 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1147 if !attr.span.allows_unstable() {
1148 // check for gated attributes
1149 self.context.check_attribute(attr, false);
1152 if self.context.features.proc_macro && attr::is_known(attr) {
1156 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1157 if contains_novel_literal(&meta) {
1158 gate_feature_post!(&self, attr_literals, attr.span,
1159 "non-string literals in attributes, or string \
1160 literals in top-level positions, are experimental");
1164 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1165 if !name.as_str().is_ascii() {
1166 gate_feature_post!(&self, non_ascii_idents, sp,
1167 "non-ascii idents are not fully supported.");
1171 fn visit_item(&mut self, i: &'a ast::Item) {
1173 ast::ItemKind::ExternCrate(_) => {
1174 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1175 gate_feature_post!(&self, macro_reexport, i.span,
1176 "macros reexports are experimental \
1177 and possibly buggy");
1181 ast::ItemKind::ForeignMod(ref foreign_module) => {
1182 if attr::contains_name(&i.attrs[..], "link_args") {
1183 gate_feature_post!(&self, link_args, i.span,
1184 "the `link_args` attribute is not portable \
1185 across platforms, it is recommended to \
1186 use `#[link(name = \"foo\")]` instead")
1188 self.check_abi(foreign_module.abi, i.span);
1191 ast::ItemKind::Fn(..) => {
1192 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1193 gate_feature_post!(&self, plugin_registrar, i.span,
1194 "compiler plugins are experimental and possibly buggy");
1196 if attr::contains_name(&i.attrs[..], "start") {
1197 gate_feature_post!(&self, start, i.span,
1198 "a #[start] function is an experimental \
1199 feature whose signature may change \
1202 if attr::contains_name(&i.attrs[..], "main") {
1203 gate_feature_post!(&self, main, i.span,
1204 "declaration of a nonstandard #[main] \
1205 function may change over time, for now \
1206 a top-level `fn main()` is required");
1210 ast::ItemKind::Struct(..) => {
1211 if attr::contains_name(&i.attrs[..], "simd") {
1212 gate_feature_post!(&self, simd, i.span,
1213 "SIMD types are experimental and possibly buggy");
1214 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1215 "the `#[simd]` attribute \
1216 is deprecated, use \
1217 `#[repr(simd)]` instead");
1219 for attr in &i.attrs {
1220 if attr.path == "repr" {
1221 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1222 if item.check_name("simd") {
1223 gate_feature_post!(&self, repr_simd, i.span,
1224 "SIMD types are experimental \
1225 and possibly buggy");
1228 if item.check_name("align") {
1229 gate_feature_post!(&self, repr_align, i.span,
1230 "the struct `#[repr(align(u16))]` attribute \
1238 ast::ItemKind::DefaultImpl(..) => {
1239 gate_feature_post!(&self, optin_builtin_traits,
1241 "default trait implementations are experimental \
1242 and possibly buggy");
1245 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1246 if polarity == ast::ImplPolarity::Negative {
1247 gate_feature_post!(&self, optin_builtin_traits,
1249 "negative trait bounds are not yet fully implemented; \
1250 use marker types for now");
1253 if let ast::Defaultness::Default = defaultness {
1254 gate_feature_post!(&self, specialization,
1256 "specialization is unstable");
1260 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1261 let msg = "`macro` is experimental";
1262 gate_feature_post!(&self, decl_macro, i.span, msg);
1268 visit::walk_item(self, i);
1271 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1272 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1273 Some(val) => val.as_str().starts_with("llvm."),
1277 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1278 "linking to LLVM intrinsics is experimental");
1281 visit::walk_foreign_item(self, i)
1284 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1286 ast::TyKind::BareFn(ref bare_fn_ty) => {
1287 self.check_abi(bare_fn_ty.abi, ty.span);
1289 ast::TyKind::ImplTrait(..) => {
1290 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1291 "`impl Trait` is experimental");
1293 ast::TyKind::Never => {
1294 gate_feature_post!(&self, never_type, ty.span,
1295 "The `!` type is experimental");
1299 visit::walk_ty(self, ty)
1302 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1303 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1304 if output_ty.node != ast::TyKind::Never {
1305 self.visit_ty(output_ty)
1310 fn visit_expr(&mut self, e: &'a ast::Expr) {
1312 ast::ExprKind::Box(_) => {
1313 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1315 ast::ExprKind::Type(..) => {
1316 gate_feature_post!(&self, type_ascription, e.span,
1317 "type ascription is experimental");
1319 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1320 gate_feature_post!(&self, inclusive_range_syntax,
1322 "inclusive range syntax is experimental");
1324 ast::ExprKind::InPlace(..) => {
1325 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1327 ast::ExprKind::Lit(ref lit) => {
1328 if let ast::LitKind::Int(_, ref ty) = lit.node {
1330 ast::LitIntType::Signed(ast::IntTy::I128) |
1331 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1332 gate_feature_post!(&self, i128_type, e.span,
1333 "128-bit integers are not stable");
1339 ast::ExprKind::Catch(_) => {
1340 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1344 visit::walk_expr(self, e);
1347 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1348 match pattern.node {
1349 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1350 gate_feature_post!(&self, advanced_slice_patterns,
1352 "multiple-element slice matches anywhere \
1353 but at the end of a slice (e.g. \
1354 `[0, ..xs, 0]`) are experimental")
1356 PatKind::Slice(..) => {
1357 gate_feature_post!(&self, slice_patterns,
1359 "slice pattern syntax is experimental");
1361 PatKind::Box(..) => {
1362 gate_feature_post!(&self, box_patterns,
1364 "box pattern syntax is experimental");
1366 PatKind::Range(_, _, RangeEnd::Excluded) => {
1367 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1368 "exclusive range pattern syntax is experimental");
1372 visit::walk_pat(self, pattern)
1375 fn visit_fn(&mut self,
1376 fn_kind: FnKind<'a>,
1377 fn_decl: &'a ast::FnDecl,
1380 // check for const fn declarations
1381 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1383 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1385 // stability of const fn methods are covered in
1386 // visit_trait_item and visit_impl_item below; this is
1387 // because default methods don't pass through this
1391 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1392 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1393 self.check_abi(abi, span);
1397 visit::walk_fn(self, fn_kind, fn_decl, span);
1400 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1402 ast::TraitItemKind::Const(..) => {
1403 gate_feature_post!(&self, associated_consts,
1405 "associated constants are experimental")
1407 ast::TraitItemKind::Method(ref sig, ref block) => {
1408 if block.is_none() {
1409 self.check_abi(sig.abi, ti.span);
1411 if sig.constness.node == ast::Constness::Const {
1412 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1415 ast::TraitItemKind::Type(_, Some(_)) => {
1416 gate_feature_post!(&self, associated_type_defaults, ti.span,
1417 "associated type defaults are unstable");
1421 visit::walk_trait_item(self, ti);
1424 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1425 if ii.defaultness == ast::Defaultness::Default {
1426 gate_feature_post!(&self, specialization,
1428 "specialization is unstable");
1432 ast::ImplItemKind::Const(..) => {
1433 gate_feature_post!(&self, associated_consts,
1435 "associated constants are experimental")
1437 ast::ImplItemKind::Method(ref sig, _) => {
1438 if sig.constness.node == ast::Constness::Const {
1439 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1444 visit::walk_impl_item(self, ii);
1447 fn visit_generics(&mut self, g: &'a ast::Generics) {
1448 for t in &g.ty_params {
1449 if !t.attrs.is_empty() {
1450 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1451 "attributes on type parameter bindings are experimental");
1454 visit::walk_generics(self, g)
1457 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1458 if !lifetime_def.attrs.is_empty() {
1459 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1460 "attributes on lifetime bindings are experimental");
1462 visit::walk_lifetime_def(self, lifetime_def)
1466 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1467 let mut features = Features::new();
1469 let mut feature_checker = MutexFeatureChecker::default();
1471 for attr in krate_attrs {
1472 if !attr.check_name("feature") {
1476 match attr.meta_item_list() {
1478 span_err!(span_handler, attr.span, E0555,
1479 "malformed feature attribute, expected #![feature(...)]");
1483 let name = if let Some(word) = mi.word() {
1486 span_err!(span_handler, mi.span, E0556,
1487 "malformed feature, expected just one word");
1491 if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
1492 .find(|& &(n, _, _, _)| name == n) {
1493 *(setter(&mut features)) = true;
1494 feature_checker.collect(&features, mi.span);
1496 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1497 .find(|& &(n, _, _)| name == n)
1498 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1499 .find(|& &(n, _, _)| name == n)) {
1500 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1502 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1503 .find(|& &(n, _, _)| name == n) {
1504 features.declared_stable_lang_features.push((name, mi.span));
1506 features.declared_lib_features.push((name, mi.span));
1513 feature_checker.check(span_handler);
1518 // A collector for mutually-exclusive features and their flag spans
1520 struct MutexFeatureChecker {
1521 proc_macro: Option<Span>,
1522 custom_attribute: Option<Span>,
1525 impl MutexFeatureChecker {
1526 // If this method turns out to be a hotspot due to branching,
1527 // the branching can be eliminated by modifying `setter!()` to set these spans
1528 // only for the features that need to be checked for mutual exclusion.
1529 fn collect(&mut self, features: &Features, span: Span) {
1530 if features.proc_macro {
1531 // If self.proc_macro is None, set to Some(span)
1532 self.proc_macro = self.proc_macro.or(Some(span));
1535 if features.custom_attribute {
1536 self.custom_attribute = self.custom_attribute.or(Some(span));
1540 fn check(self, handler: &Handler) {
1541 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1542 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1543 `#![feature(custom_attribute)] at the same time")
1544 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1552 pub fn check_crate(krate: &ast::Crate,
1554 features: &Features,
1555 plugin_attributes: &[(String, AttributeType)],
1556 unstable: UnstableFeatures) {
1557 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1561 plugin_attributes: plugin_attributes,
1563 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1566 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1567 pub enum UnstableFeatures {
1568 /// Hard errors for unstable features are active, as on
1569 /// beta/stable channels.
1571 /// Allow features to be activated, as on nightly.
1573 /// Errors are bypassed for bootstrapping. This is required any time
1574 /// during the build that feature-related lints are set to warn or above
1575 /// because the build turns on warnings-as-errors and uses lots of unstable
1576 /// features. As a result, this is always required for building Rust itself.
1580 impl UnstableFeatures {
1581 pub fn from_environment() -> UnstableFeatures {
1582 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1583 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1584 // Whether we should enable unstable features for bootstrapping
1585 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1586 match (disable_unstable_features, bootstrap) {
1587 (_, true) => UnstableFeatures::Cheat,
1588 (true, _) => UnstableFeatures::Disallow,
1589 (false, _) => UnstableFeatures::Allow
1593 pub fn is_nightly_build(&self) -> bool {
1595 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1601 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1602 unstable: UnstableFeatures) {
1603 let allow_features = match unstable {
1604 UnstableFeatures::Allow => true,
1605 UnstableFeatures::Disallow => false,
1606 UnstableFeatures::Cheat => true
1608 if !allow_features {
1609 for attr in &krate.attrs {
1610 if attr.check_name("feature") {
1611 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1612 span_err!(span_handler, attr.span, E0554,
1613 "#[feature] may not be used on the {} release channel",