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, span: Span) {
44 features.declared_lib_features.push((Symbol::intern("proc_macro"), span));
45 features.proc_macro = true;
47 f as fn(&mut Features, Span)
50 fn f(features: &mut Features, _: Span) {
51 features.$field = true;
53 f as fn(&mut Features, Span)
57 macro_rules! declare_features {
58 ($((active, $feature: ident, $ver: expr, $issue: expr),)+) => {
59 /// Represents active features that are currently being implemented or
60 /// currently being considered for addition/removal.
61 const ACTIVE_FEATURES:
62 &'static [(&'static str, &'static str, Option<u32>, fn(&mut Features, Span))] =
63 &[$((stringify!($feature), $ver, $issue, set!($feature))),+];
65 /// A set of features to be used by later passes.
67 /// #![feature] attrs for stable language features, for error reporting
68 pub declared_stable_lang_features: Vec<(Symbol, Span)>,
69 /// #![feature] attrs for non-language (library) features
70 pub declared_lib_features: Vec<(Symbol, Span)>,
71 $(pub $feature: bool),+
75 pub fn new() -> Features {
77 declared_stable_lang_features: Vec::new(),
78 declared_lib_features: Vec::new(),
85 ($((removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
86 /// Represents unstable features which have since been removed (it was once Active)
87 const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
88 $((stringify!($feature), $ver, $issue)),+
92 ($((stable_removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
93 /// Represents stable features which have since been removed (it was once Accepted)
94 const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
95 $((stringify!($feature), $ver, $issue)),+
99 ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => {
100 /// Those language feature has since been Accepted (it was once Active)
101 const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
102 $((stringify!($feature), $ver, $issue)),+
107 // If you change this, please modify src/doc/unstable-book as well.
109 // Don't ever remove anything from this list; set them to 'Removed'.
111 // The version numbers here correspond to the version in which the current status
112 // was set. This is most important for knowing when a particular feature became
115 // NB: The featureck.py script parses this information directly out of the source
116 // so take care when modifying it.
119 (active, asm, "1.0.0", Some(29722)),
120 (active, compile_error, "1.20.0", Some(40872)),
121 (active, concat_idents, "1.0.0", Some(29599)),
122 (active, link_args, "1.0.0", Some(29596)),
123 (active, log_syntax, "1.0.0", Some(29598)),
124 (active, non_ascii_idents, "1.0.0", Some(28979)),
125 (active, plugin_registrar, "1.0.0", Some(29597)),
126 (active, thread_local, "1.0.0", Some(29594)),
127 (active, trace_macros, "1.0.0", Some(29598)),
129 // rustc internal, for now:
130 (active, intrinsics, "1.0.0", None),
131 (active, lang_items, "1.0.0", None),
133 (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
134 (active, linkage, "1.0.0", Some(29603)),
135 (active, quote, "1.0.0", Some(29601)),
136 (active, simd, "1.0.0", Some(27731)),
140 (active, rustc_diagnostic_macros, "1.0.0", None),
141 (active, advanced_slice_patterns, "1.0.0", Some(23121)),
142 (active, box_syntax, "1.0.0", Some(27779)),
143 (active, placement_in_syntax, "1.0.0", Some(27779)),
144 (active, unboxed_closures, "1.0.0", Some(29625)),
146 (active, fundamental, "1.0.0", Some(29635)),
147 (active, main, "1.0.0", Some(29634)),
148 (active, needs_allocator, "1.4.0", Some(27389)),
149 (active, on_unimplemented, "1.0.0", Some(29628)),
150 (active, plugin, "1.0.0", Some(29597)),
151 (active, simd_ffi, "1.0.0", Some(27731)),
152 (active, start, "1.0.0", Some(29633)),
153 (active, structural_match, "1.8.0", Some(31434)),
154 (active, panic_runtime, "1.10.0", Some(32837)),
155 (active, needs_panic_runtime, "1.10.0", Some(32837)),
157 // OIBIT specific features
158 (active, optin_builtin_traits, "1.0.0", Some(13231)),
160 // macro reexport needs more discussion and stabilization
161 (active, macro_reexport, "1.0.0", Some(29638)),
163 // Allows use of #[staged_api]
165 (active, staged_api, "1.0.0", None),
167 // Allows using #![no_core]
168 (active, no_core, "1.3.0", Some(29639)),
170 // Allows using `box` in patterns; RFC 469
171 (active, box_patterns, "1.0.0", Some(29641)),
173 // Allows using the unsafe_destructor_blind_to_params attribute;
175 (active, dropck_parametricity, "1.3.0", Some(28498)),
177 // Allows using the may_dangle attribute; RFC 1327
178 (active, dropck_eyepatch, "1.10.0", Some(34761)),
180 // Allows the use of custom attributes; RFC 572
181 (active, custom_attribute, "1.0.0", Some(29642)),
183 // Allows the use of #[derive(Anything)] as sugar for
184 // #[derive_Anything].
185 (active, custom_derive, "1.0.0", Some(29644)),
187 // Allows the use of rustc_* attributes; RFC 572
188 (active, rustc_attrs, "1.0.0", Some(29642)),
190 // Allows the use of #[allow_internal_unstable]. This is an
191 // attribute on macro_rules! and can't use the attribute handling
192 // below (it has to be checked before expansion possibly makes
193 // macros disappear).
196 (active, allow_internal_unstable, "1.0.0", None),
198 // #23121. Array patterns have some hazards yet.
199 (active, slice_patterns, "1.0.0", Some(23121)),
201 // Allows the definition of `const fn` functions.
202 (active, const_fn, "1.2.0", Some(24111)),
204 // Allows indexing into constant arrays.
205 (active, const_indexing, "1.4.0", Some(29947)),
207 // Allows using #[prelude_import] on glob `use` items.
210 (active, prelude_import, "1.2.0", None),
212 // Allows default type parameters to influence type inference.
213 (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
215 // Allows associated type defaults
216 (active, associated_type_defaults, "1.2.0", Some(29661)),
218 // allow `repr(simd)`, and importing the various simd intrinsics
219 (active, repr_simd, "1.4.0", Some(27731)),
221 // Allows cfg(target_feature = "...").
222 (active, cfg_target_feature, "1.4.0", Some(29717)),
224 // allow `extern "platform-intrinsic" { ... }`
225 (active, platform_intrinsics, "1.4.0", Some(27731)),
228 // rust runtime internal
229 (active, unwind_attributes, "1.4.0", None),
231 // allow the use of `#[naked]` on functions.
232 (active, naked_functions, "1.9.0", Some(32408)),
234 // allow `#[no_debug]`
235 (active, no_debug, "1.5.0", Some(29721)),
237 // allow `#[omit_gdb_pretty_printer_section]`
239 (active, omit_gdb_pretty_printer_section, "1.5.0", None),
241 // Allows cfg(target_vendor = "...").
242 (active, cfg_target_vendor, "1.5.0", Some(29718)),
244 // Allow attributes on expressions and non-item statements
245 (active, stmt_expr_attributes, "1.6.0", Some(15701)),
247 // allow using type ascription in expressions
248 (active, type_ascription, "1.6.0", Some(23416)),
250 // Allows cfg(target_thread_local)
251 (active, cfg_target_thread_local, "1.7.0", Some(29594)),
254 (active, abi_vectorcall, "1.7.0", None),
257 (active, inclusive_range_syntax, "1.7.0", Some(28237)),
260 (active, exclusive_range_pattern, "1.11.0", Some(37854)),
262 // impl specialization (RFC 1210)
263 (active, specialization, "1.7.0", Some(31844)),
265 // Allow Drop types in statics/const functions (RFC 1440)
266 (active, drop_types_in_const, "1.9.0", Some(33156)),
268 // Allows cfg(target_has_atomic = "...").
269 (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
271 // Allows `impl Trait` in function return types.
272 (active, conservative_impl_trait, "1.12.0", Some(34511)),
275 (active, never_type, "1.13.0", Some(35121)),
277 // Allows all literals in attribute lists and values of key-value pairs.
278 (active, attr_literals, "1.13.0", Some(34981)),
280 // Allows the sysV64 ABI to be specified on all platforms
281 // instead of just the platforms on which it is the C ABI
282 (active, abi_sysv64, "1.13.0", Some(36167)),
284 // Allows untagged unions `union U { ... }`
285 (active, untagged_unions, "1.13.0", Some(32836)),
287 // Used to identify the `compiler_builtins` crate
289 (active, compiler_builtins, "1.13.0", None),
291 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
292 (active, generic_param_attrs, "1.11.0", Some(34761)),
294 // Allows #[link(..., cfg(..))]
295 (active, link_cfg, "1.14.0", Some(37406)),
297 (active, use_extern_macros, "1.15.0", Some(35896)),
299 // Allows #[target_feature(...)]
300 (active, target_feature, "1.15.0", None),
302 // `extern "ptx-*" fn()`
303 (active, abi_ptx, "1.15.0", None),
306 (active, i128_type, "1.16.0", Some(35118)),
308 // The `unadjusted` ABI. Perma unstable.
309 (active, abi_unadjusted, "1.16.0", None),
311 // Procedural macros 2.0.
312 (active, proc_macro, "1.16.0", Some(38356)),
314 // Declarative macros 2.0 (`macro`).
315 (active, decl_macro, "1.17.0", Some(39412)),
317 // Allows #[link(kind="static-nobundle"...]
318 (active, static_nobundle, "1.16.0", Some(37403)),
320 // `extern "msp430-interrupt" fn()`
321 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
323 // Used to identify crates that contain sanitizer runtimes
325 (active, sanitizer_runtime, "1.17.0", None),
327 // Used to identify crates that contain the profiler runtime
329 (active, profiler_runtime, "1.18.0", None),
331 // `extern "x86-interrupt" fn()`
332 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
335 // Allows the `catch {...}` expression
336 (active, catch_expr, "1.17.0", Some(31436)),
338 // Allows `repr(align(u16))` struct attribute (RFC 1358)
339 (active, repr_align, "1.17.0", Some(33626)),
341 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
342 (active, rvalue_static_promotion, "1.15.1", Some(38865)),
344 // Used to preserve symbols (see llvm.used)
345 (active, used, "1.18.0", Some(40289)),
347 // Allows module-level inline assembly by way of global_asm!()
348 (active, global_asm, "1.18.0", Some(35119)),
350 // Allows overlapping impls of marker traits
351 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
353 // Allows use of the :vis macro fragment specifier
354 (active, macro_vis_matcher, "1.18.0", Some(41022)),
357 (active, abi_thiscall, "1.19.0", None),
359 // Allows a test to fail without failing the whole suite
360 (active, allow_fail, "1.19.0", Some(42219)),
362 // Allows unsized tuple coercion.
363 (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
365 // global allocators and their internals
366 (active, global_allocator, "1.20.0", None),
367 (active, allocator_internals, "1.20.0", None),
371 (removed, import_shadowing, "1.0.0", None),
372 (removed, managed_boxes, "1.0.0", None),
373 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
374 (removed, negate_unsigned, "1.0.0", Some(29645)),
375 (removed, reflect, "1.0.0", Some(27749)),
376 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
377 (removed, opt_out_copy, "1.0.0", None),
378 (removed, quad_precision_float, "1.0.0", None),
379 (removed, struct_inherit, "1.0.0", None),
380 (removed, test_removed_feature, "1.0.0", None),
381 (removed, visible_private_types, "1.0.0", None),
382 (removed, unsafe_no_drop_flag, "1.0.0", None),
383 // Allows using items which are missing stability attributes
385 (removed, unmarked_api, "1.0.0", None),
386 (removed, pushpop_unsafe, "1.2.0", None),
387 (removed, allocator, "1.0.0", None),
391 (stable_removed, no_stack_check, "1.0.0", None),
395 (accepted, associated_types, "1.0.0", None),
396 // allow overloading augmented assignment operations like `a += b`
397 (accepted, augmented_assignments, "1.8.0", Some(28235)),
398 // allow empty structs and enum variants with braces
399 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
400 (accepted, default_type_params, "1.0.0", None),
401 (accepted, globs, "1.0.0", None),
402 (accepted, if_let, "1.0.0", None),
403 // A temporary feature gate used to enable parser extensions needed
404 // to bootstrap fix for #5723.
405 (accepted, issue_5723_bootstrap, "1.0.0", None),
406 (accepted, macro_rules, "1.0.0", None),
407 // Allows using #![no_std]
408 (accepted, no_std, "1.6.0", None),
409 (accepted, slicing_syntax, "1.0.0", None),
410 (accepted, struct_variant, "1.0.0", None),
411 // These are used to test this portion of the compiler, they don't actually
413 (accepted, test_accepted_feature, "1.0.0", None),
414 (accepted, tuple_indexing, "1.0.0", None),
415 // Allows macros to appear in the type position.
416 (accepted, type_macros, "1.13.0", Some(27245)),
417 (accepted, while_let, "1.0.0", None),
418 // Allows `#[deprecated]` attribute
419 (accepted, deprecated, "1.9.0", Some(29935)),
421 (accepted, question_mark, "1.13.0", Some(31436)),
422 // Allows `..` in tuple (struct) patterns
423 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
424 (accepted, item_like_imports, "1.15.0", Some(35120)),
425 // Allows using `Self` and associated types in struct expressions and patterns.
426 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
427 // elide `'static` lifetimes in `static`s and `const`s
428 (accepted, static_in_const, "1.17.0", Some(35897)),
429 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
430 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
431 // Allows the definition recursive static items.
432 (accepted, static_recursion, "1.17.0", Some(29719)),
433 // pub(restricted) visibilities (RFC 1422)
434 (accepted, pub_restricted, "1.18.0", Some(32409)),
435 // The #![windows_subsystem] attribute
436 (accepted, windows_subsystem, "1.18.0", Some(37499)),
437 // Allows `break {expr}` with a value inside `loop`s.
438 (accepted, loop_break_value, "1.19.0", Some(37339)),
439 // Permits numeric fields in struct expressions and patterns.
440 (accepted, relaxed_adts, "1.19.0", Some(35626)),
441 // Coerces non capturing closures to function pointers
442 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
443 // Allows attributes on struct literal fields.
444 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
445 // Allows the definition of associated constants in `trait` or `impl`
447 (accepted, associated_consts, "1.20.0", Some(29646)),
450 // If you change this, please modify src/doc/unstable-book as well. You must
451 // move that documentation into the relevant place in the other docs, and
452 // remove the chapter on the flag.
454 #[derive(PartialEq, Copy, Clone, Debug)]
455 pub enum AttributeType {
456 /// Normal, builtin attribute that is consumed
457 /// by the compiler before the unused_attribute check
460 /// Builtin attribute that may not be consumed by the compiler
461 /// before the unused_attribute check. These attributes
462 /// will be ignored by the unused_attribute lint
465 /// Builtin attribute that is only allowed at the crate level
469 pub enum AttributeGate {
470 /// Is gated by a given feature gate, reason
471 /// and function to check if enabled
472 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
474 /// Ungated attribute, can be used on all release channels
479 fn is_deprecated(&self) -> bool {
481 Gated(Stability::Deprecated(_), ..) => true,
487 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
490 // Argument is tracking issue link.
491 Deprecated(&'static str),
495 impl ::std::fmt::Debug for AttributeGate {
496 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
498 Gated(ref stab, name, expl, _) =>
499 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
500 Ungated => write!(fmt, "Ungated")
505 macro_rules! cfg_fn {
506 ($field: ident) => {{
507 fn f(features: &Features) -> bool {
510 f as fn(&Features) -> bool
514 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
515 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
518 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
519 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
522 // Attributes that have a special meaning to rustc or rustdoc
523 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
526 ("warn", Normal, Ungated),
527 ("allow", Normal, Ungated),
528 ("forbid", Normal, Ungated),
529 ("deny", Normal, Ungated),
531 ("macro_reexport", Normal, Ungated),
532 ("macro_use", Normal, Ungated),
533 ("macro_export", Normal, Ungated),
534 ("plugin_registrar", Normal, Ungated),
536 ("cfg", Normal, Ungated),
537 ("cfg_attr", Normal, Ungated),
538 ("main", Normal, Ungated),
539 ("start", Normal, Ungated),
540 ("test", Normal, Ungated),
541 ("bench", Normal, Ungated),
542 ("simd", Normal, Ungated),
543 ("repr", Normal, Ungated),
544 ("path", Normal, Ungated),
545 ("abi", Normal, Ungated),
546 ("automatically_derived", Normal, Ungated),
547 ("no_mangle", Normal, Ungated),
548 ("no_link", Normal, Ungated),
549 ("derive", Normal, Ungated),
550 ("should_panic", Normal, Ungated),
551 ("ignore", Normal, Ungated),
552 ("no_implicit_prelude", Normal, Ungated),
553 ("reexport_test_harness_main", Normal, Ungated),
554 ("link_args", Normal, Ungated),
555 ("macro_escape", Normal, Ungated),
558 ("structural_match", Whitelisted, Gated(Stability::Unstable,
560 "the semantics of constant patterns is \
562 cfg_fn!(structural_match))),
564 ("plugin", CrateLevel, Gated(Stability::Unstable,
566 "compiler plugins are experimental \
570 ("no_std", CrateLevel, Ungated),
571 ("no_core", CrateLevel, Gated(Stability::Unstable,
573 "no_core is experimental",
575 ("lang", Normal, Gated(Stability::Unstable,
577 "language items are subject to change",
578 cfg_fn!(lang_items))),
579 ("linkage", Whitelisted, Gated(Stability::Unstable,
581 "the `linkage` attribute is experimental \
582 and not portable across platforms",
584 ("thread_local", Whitelisted, Gated(Stability::Unstable,
586 "`#[thread_local]` is an experimental feature, and does \
587 not currently handle destructors. There is no \
588 corresponding `#[task_local]` mapping to the task \
590 cfg_fn!(thread_local))),
592 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
594 "the `#[rustc_on_unimplemented]` attribute \
595 is an experimental feature",
596 cfg_fn!(on_unimplemented))),
597 ("global_allocator", Normal, Gated(Stability::Unstable,
599 "the `#[global_allocator]` attribute is \
600 an experimental feature",
601 cfg_fn!(global_allocator))),
602 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
603 "allocator_internals",
604 "the `#[default_lib_allocator]` \
605 attribute is an experimental feature",
606 cfg_fn!(allocator_internals))),
607 ("needs_allocator", Normal, Gated(Stability::Unstable,
608 "allocator_internals",
609 "the `#[needs_allocator]` \
610 attribute is an experimental \
612 cfg_fn!(allocator_internals))),
613 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
615 "the `#[panic_runtime]` attribute is \
616 an experimental feature",
617 cfg_fn!(panic_runtime))),
618 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
619 "needs_panic_runtime",
620 "the `#[needs_panic_runtime]` \
621 attribute is an experimental \
623 cfg_fn!(needs_panic_runtime))),
624 ("rustc_variance", Normal, Gated(Stability::Unstable,
626 "the `#[rustc_variance]` attribute \
627 is just used for rustc unit tests \
628 and will never be stable",
629 cfg_fn!(rustc_attrs))),
630 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
632 "the `#[rustc_error]` attribute \
633 is just used for rustc unit tests \
634 and will never be stable",
635 cfg_fn!(rustc_attrs))),
636 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
638 "the `#[rustc_if_this_changed]` attribute \
639 is just used for rustc unit tests \
640 and will never be stable",
641 cfg_fn!(rustc_attrs))),
642 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
644 "the `#[rustc_if_this_changed]` attribute \
645 is just used for rustc unit tests \
646 and will never be stable",
647 cfg_fn!(rustc_attrs))),
648 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
650 "the `#[rustc_dirty]` attribute \
651 is just used for rustc unit tests \
652 and will never be stable",
653 cfg_fn!(rustc_attrs))),
654 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
656 "the `#[rustc_clean]` attribute \
657 is just used for rustc unit tests \
658 and will never be stable",
659 cfg_fn!(rustc_attrs))),
660 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
662 "the `#[rustc_metadata_dirty]` attribute \
663 is just used for rustc unit tests \
664 and will never be stable",
665 cfg_fn!(rustc_attrs))),
666 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
668 "the `#[rustc_metadata_clean]` attribute \
669 is just used for rustc unit tests \
670 and will never be stable",
671 cfg_fn!(rustc_attrs))),
672 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
675 is just used for rustc unit tests \
676 and will never be stable",
677 cfg_fn!(rustc_attrs))),
678 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
681 is just used for rustc unit tests \
682 and will never be stable",
683 cfg_fn!(rustc_attrs))),
684 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
686 "internal rustc attributes will never be stable",
687 cfg_fn!(rustc_attrs))),
688 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
690 "internal rustc attributes will never be stable",
691 cfg_fn!(rustc_attrs))),
692 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
694 "the `#[rustc_mir]` attribute \
695 is just used for rustc unit tests \
696 and will never be stable",
697 cfg_fn!(rustc_attrs))),
698 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
700 "the `#[rustc_inherit_overflow_checks]` \
701 attribute is just used to control \
702 overflow checking behavior of several \
703 libcore functions that are inlined \
704 across crates and will never be stable",
705 cfg_fn!(rustc_attrs))),
706 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
708 "the `#[compiler_builtins]` attribute is used to \
709 identify the `compiler_builtins` crate which \
710 contains compiler-rt intrinsics and will never be \
712 cfg_fn!(compiler_builtins))),
713 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
715 "the `#[sanitizer_runtime]` attribute is used to \
716 identify crates that contain the runtime of a \
717 sanitizer and will never be stable",
718 cfg_fn!(sanitizer_runtime))),
719 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
721 "the `#[profiler_runtime]` attribute is used to \
722 identify the `profiler_builtins` crate which \
723 contains the profiler runtime and will never be \
725 cfg_fn!(profiler_runtime))),
727 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
728 "allow_internal_unstable",
729 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
730 cfg_fn!(allow_internal_unstable))),
732 ("fundamental", Whitelisted, Gated(Stability::Unstable,
734 "the `#[fundamental]` attribute \
735 is an experimental feature",
736 cfg_fn!(fundamental))),
738 ("proc_macro_derive", Normal, Ungated),
740 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
742 "internal implementation detail",
743 cfg_fn!(rustc_attrs))),
745 // FIXME: #14408 whitelist docs since rustdoc looks at them
746 ("doc", Whitelisted, Ungated),
748 // FIXME: #14406 these are processed in trans, which happens after the
750 ("cold", Whitelisted, Ungated),
751 ("naked", Whitelisted, Gated(Stability::Unstable,
753 "the `#[naked]` attribute \
754 is an experimental feature",
755 cfg_fn!(naked_functions))),
756 ("target_feature", Whitelisted, Gated(
757 Stability::Unstable, "target_feature",
758 "the `#[target_feature]` attribute is an experimental feature",
759 cfg_fn!(target_feature))),
760 ("export_name", Whitelisted, Ungated),
761 ("inline", Whitelisted, Ungated),
762 ("link", Whitelisted, Ungated),
763 ("link_name", Whitelisted, Ungated),
764 ("link_section", Whitelisted, Ungated),
765 ("no_builtins", Whitelisted, Ungated),
766 ("no_mangle", Whitelisted, Ungated),
767 ("no_debug", Whitelisted, Gated(
768 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
770 "the `#[no_debug]` attribute is an experimental feature",
772 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
773 "omit_gdb_pretty_printer_section",
774 "the `#[omit_gdb_pretty_printer_section]` \
775 attribute is just used for the Rust test \
777 cfg_fn!(omit_gdb_pretty_printer_section))),
778 ("unsafe_destructor_blind_to_params",
780 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
781 "dropck_parametricity",
782 "unsafe_destructor_blind_to_params has been replaced by \
783 may_dangle and will be removed in the future",
784 cfg_fn!(dropck_parametricity))),
787 Gated(Stability::Unstable,
789 "may_dangle has unstable semantics and may be removed in the future",
790 cfg_fn!(dropck_eyepatch))),
791 ("unwind", Whitelisted, Gated(Stability::Unstable,
793 "#[unwind] is experimental",
794 cfg_fn!(unwind_attributes))),
795 ("used", Whitelisted, Gated(
796 Stability::Unstable, "used",
797 "the `#[used]` attribute is an experimental feature",
801 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
803 "`#[prelude_import]` is for use by rustc only",
804 cfg_fn!(prelude_import))),
806 // FIXME: #14407 these are only looked at on-demand so we can't
807 // guarantee they'll have already been checked
808 ("rustc_deprecated", Whitelisted, Ungated),
809 ("must_use", Whitelisted, Ungated),
810 ("stable", Whitelisted, Ungated),
811 ("unstable", Whitelisted, Ungated),
812 ("deprecated", Normal, Ungated),
814 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
816 "unboxed_closures are still evolving",
817 cfg_fn!(unboxed_closures))),
819 ("windows_subsystem", Whitelisted, Ungated),
821 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
823 "attribute proc macros are currently unstable",
824 cfg_fn!(proc_macro))),
826 ("proc_macro", Normal, Gated(Stability::Unstable,
828 "function-like proc macros are currently unstable",
829 cfg_fn!(proc_macro))),
831 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
832 "rustc_derive_registrar",
833 "used internally by rustc",
834 cfg_fn!(rustc_attrs))),
836 ("allow_fail", Normal, Gated(Stability::Unstable,
838 "allow_fail attribute is currently unstable",
839 cfg_fn!(allow_fail))),
841 // Crate level attributes
842 ("crate_name", CrateLevel, Ungated),
843 ("crate_type", CrateLevel, Ungated),
844 ("crate_id", CrateLevel, Ungated),
845 ("feature", CrateLevel, Ungated),
846 ("no_start", CrateLevel, Ungated),
847 ("no_main", CrateLevel, Ungated),
848 ("no_builtins", CrateLevel, Ungated),
849 ("recursion_limit", CrateLevel, Ungated),
850 ("type_length_limit", CrateLevel, Ungated),
853 // cfg(...)'s that are feature gated
854 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
855 // (name in cfg, feature, function to check if the feature is enabled)
856 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
857 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
858 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
859 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
862 #[derive(Debug, Eq, PartialEq)]
863 pub struct GatedCfg {
869 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
870 let name = cfg.name().as_str();
872 .position(|info| info.0 == name)
881 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
882 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
883 if !has_feature(features) && !self.span.allows_unstable() {
884 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
885 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
891 features: &'a Features,
892 parse_sess: &'a ParseSess,
893 plugin_attributes: &'a [(String, AttributeType)],
896 macro_rules! gate_feature_fn {
897 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
898 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
899 let has_feature: bool = has_feature(&$cx.features);
900 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
901 if !has_feature && !span.allows_unstable() {
902 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
907 macro_rules! gate_feature {
908 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
909 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
913 impl<'a> Context<'a> {
914 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
915 debug!("check_attribute(attr = {:?})", attr);
916 let name = unwrap_or!(attr.name(), return).as_str();
917 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
919 if let Gated(_, name, desc, ref has_feature) = *gateage {
920 gate_feature_fn!(self, has_feature, attr.span, name, desc);
922 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
926 for &(ref n, ref ty) in self.plugin_attributes {
927 if attr.path == &**n {
928 // Plugins can't gate attributes, so we don't check for it
929 // unlike the code above; we only use this loop to
930 // short-circuit to avoid the checks below
931 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
935 if name.starts_with("rustc_") {
936 gate_feature!(self, rustc_attrs, attr.span,
937 "unless otherwise specified, attributes \
938 with the prefix `rustc_` \
939 are reserved for internal compiler diagnostics");
940 } else if name.starts_with("derive_") {
941 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
942 } else if !attr::is_known(attr) {
943 // Only run the custom attribute lint during regular
944 // feature gate checking. Macro gating runs
945 // before the plugin attributes are registered
946 // so we skip this then
948 gate_feature!(self, custom_attribute, attr.span,
949 &format!("The attribute `{}` is currently \
950 unknown to the compiler and \
952 added to it in the future",
959 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
960 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
961 cx.check_attribute(attr, true);
964 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
965 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
968 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
969 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
971 // FIXME (#28244): enforce that active features have issue numbers
972 // assert!(issue.is_some())
975 // search in Accepted, Removed, or Stable Removed features
976 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
977 .find(|t| t.0 == feature);
979 Some(&(_, _, issue)) => issue,
980 None => panic!("Feature `{}` is not declared anywhere", feature),
990 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
992 feature_err(sess, feature, span, issue, explain).emit();
995 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
996 explain: &str) -> DiagnosticBuilder<'a> {
997 let diag = &sess.span_diagnostic;
999 let issue = match issue {
1000 GateIssue::Language => find_lang_feature_issue(feature),
1001 GateIssue::Library(lib) => lib,
1004 let mut err = if let Some(n) = issue {
1005 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
1007 diag.struct_span_err(span, explain)
1010 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1011 if sess.unstable_features.is_nightly_build() {
1012 err.help(&format!("add #![feature({})] to the \
1013 crate attributes to enable",
1020 const EXPLAIN_BOX_SYNTAX: &'static str =
1021 "box expression syntax is experimental; you can call `Box::new` instead.";
1023 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1024 "attributes on non-item statements and expressions are experimental.";
1026 pub const EXPLAIN_ASM: &'static str =
1027 "inline assembly is not stable enough for use and is subject to change";
1029 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1030 "`global_asm!` is not stable enough for use and is subject to change";
1032 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1033 "`log_syntax!` is not stable enough for use and is subject to change";
1035 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1036 "`concat_idents` is not stable enough for use and is subject to change";
1038 pub const EXPLAIN_COMPILE_ERROR: &'static str =
1039 "`compile_error` is not stable enough for use and is subject to change";
1041 pub const EXPLAIN_TRACE_MACROS: &'static str =
1042 "`trace_macros` is not stable enough for use and is subject to change";
1043 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1044 "allow_internal_unstable side-steps feature gating and stability checks";
1046 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1047 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1049 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1050 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1051 Prefer using procedural macro custom derive.";
1053 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1054 "attributes of the form `#[derive_*]` are reserved for the compiler";
1056 pub const EXPLAIN_VIS_MATCHER: &'static str =
1057 ":vis fragment specifier is experimental and subject to change";
1059 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1060 "placement-in expression syntax is experimental and subject to change.";
1062 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1063 "Unsized tuple coercion is not stable enough for use and is subject to change";
1065 struct PostExpansionVisitor<'a> {
1066 context: &'a Context<'a>,
1069 macro_rules! gate_feature_post {
1070 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1071 let (cx, span) = ($cx, $span);
1072 if !span.allows_unstable() {
1073 gate_feature!(cx.context, $feature, span, $explain)
1078 impl<'a> PostExpansionVisitor<'a> {
1079 fn check_abi(&self, abi: Abi, span: Span) {
1081 Abi::RustIntrinsic => {
1082 gate_feature_post!(&self, intrinsics, span,
1083 "intrinsics are subject to change");
1085 Abi::PlatformIntrinsic => {
1086 gate_feature_post!(&self, platform_intrinsics, span,
1087 "platform intrinsics are experimental and possibly buggy");
1089 Abi::Vectorcall => {
1090 gate_feature_post!(&self, abi_vectorcall, span,
1091 "vectorcall is experimental and subject to change");
1094 gate_feature_post!(&self, abi_thiscall, span,
1095 "thiscall is experimental and subject to change");
1098 gate_feature_post!(&self, unboxed_closures, span,
1099 "rust-call ABI is subject to change");
1102 gate_feature_post!(&self, abi_sysv64, span,
1103 "sysv64 ABI is experimental and subject to change");
1106 gate_feature_post!(&self, abi_ptx, span,
1107 "PTX ABIs are experimental and subject to change");
1109 Abi::Unadjusted => {
1110 gate_feature_post!(&self, abi_unadjusted, span,
1111 "unadjusted ABI is an implementation detail and perma-unstable");
1113 Abi::Msp430Interrupt => {
1114 gate_feature_post!(&self, abi_msp430_interrupt, span,
1115 "msp430-interrupt ABI is experimental and subject to change");
1117 Abi::X86Interrupt => {
1118 gate_feature_post!(&self, abi_x86_interrupt, span,
1119 "x86-interrupt ABI is experimental and subject to change");
1134 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1135 use ast::MetaItemKind::*;
1136 use ast::NestedMetaItemKind::*;
1140 NameValue(ref lit) => !lit.node.is_str(),
1141 List(ref list) => list.iter().any(|li| {
1143 MetaItem(ref mi) => contains_novel_literal(mi),
1150 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1151 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1152 if !attr.span.allows_unstable() {
1153 // check for gated attributes
1154 self.context.check_attribute(attr, false);
1157 if self.context.features.proc_macro && attr::is_known(attr) {
1161 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1162 if contains_novel_literal(&meta) {
1163 gate_feature_post!(&self, attr_literals, attr.span,
1164 "non-string literals in attributes, or string \
1165 literals in top-level positions, are experimental");
1169 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1170 if !name.as_str().is_ascii() {
1171 gate_feature_post!(&self, non_ascii_idents, sp,
1172 "non-ascii idents are not fully supported.");
1176 fn visit_item(&mut self, i: &'a ast::Item) {
1178 ast::ItemKind::ExternCrate(_) => {
1179 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1180 gate_feature_post!(&self, macro_reexport, i.span,
1181 "macros reexports are experimental \
1182 and possibly buggy");
1186 ast::ItemKind::ForeignMod(ref foreign_module) => {
1187 if attr::contains_name(&i.attrs[..], "link_args") {
1188 gate_feature_post!(&self, link_args, i.span,
1189 "the `link_args` attribute is not portable \
1190 across platforms, it is recommended to \
1191 use `#[link(name = \"foo\")]` instead")
1193 self.check_abi(foreign_module.abi, i.span);
1196 ast::ItemKind::Fn(..) => {
1197 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1198 gate_feature_post!(&self, plugin_registrar, i.span,
1199 "compiler plugins are experimental and possibly buggy");
1201 if attr::contains_name(&i.attrs[..], "start") {
1202 gate_feature_post!(&self, start, i.span,
1203 "a #[start] function is an experimental \
1204 feature whose signature may change \
1207 if attr::contains_name(&i.attrs[..], "main") {
1208 gate_feature_post!(&self, main, i.span,
1209 "declaration of a nonstandard #[main] \
1210 function may change over time, for now \
1211 a top-level `fn main()` is required");
1215 ast::ItemKind::Struct(..) => {
1216 if attr::contains_name(&i.attrs[..], "simd") {
1217 gate_feature_post!(&self, simd, i.span,
1218 "SIMD types are experimental and possibly buggy");
1219 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1220 "the `#[simd]` attribute \
1221 is deprecated, use \
1222 `#[repr(simd)]` instead");
1224 for attr in &i.attrs {
1225 if attr.path == "repr" {
1226 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1227 if item.check_name("simd") {
1228 gate_feature_post!(&self, repr_simd, i.span,
1229 "SIMD types are experimental \
1230 and possibly buggy");
1233 if item.check_name("align") {
1234 gate_feature_post!(&self, repr_align, i.span,
1235 "the struct `#[repr(align(u16))]` attribute \
1243 ast::ItemKind::DefaultImpl(..) => {
1244 gate_feature_post!(&self, optin_builtin_traits,
1246 "default trait implementations are experimental \
1247 and possibly buggy");
1250 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1251 if polarity == ast::ImplPolarity::Negative {
1252 gate_feature_post!(&self, optin_builtin_traits,
1254 "negative trait bounds are not yet fully implemented; \
1255 use marker types for now");
1258 if let ast::Defaultness::Default = defaultness {
1259 gate_feature_post!(&self, specialization,
1261 "specialization is unstable");
1265 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1266 let msg = "`macro` is experimental";
1267 gate_feature_post!(&self, decl_macro, i.span, msg);
1273 visit::walk_item(self, i);
1276 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1277 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1278 Some(val) => val.as_str().starts_with("llvm."),
1282 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1283 "linking to LLVM intrinsics is experimental");
1286 visit::walk_foreign_item(self, i)
1289 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1291 ast::TyKind::BareFn(ref bare_fn_ty) => {
1292 self.check_abi(bare_fn_ty.abi, ty.span);
1294 ast::TyKind::ImplTrait(..) => {
1295 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1296 "`impl Trait` is experimental");
1298 ast::TyKind::Never => {
1299 gate_feature_post!(&self, never_type, ty.span,
1300 "The `!` type is experimental");
1304 visit::walk_ty(self, ty)
1307 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1308 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1309 if output_ty.node != ast::TyKind::Never {
1310 self.visit_ty(output_ty)
1315 fn visit_expr(&mut self, e: &'a ast::Expr) {
1317 ast::ExprKind::Box(_) => {
1318 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1320 ast::ExprKind::Type(..) => {
1321 gate_feature_post!(&self, type_ascription, e.span,
1322 "type ascription is experimental");
1324 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1325 gate_feature_post!(&self, inclusive_range_syntax,
1327 "inclusive range syntax is experimental");
1329 ast::ExprKind::InPlace(..) => {
1330 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1332 ast::ExprKind::Lit(ref lit) => {
1333 if let ast::LitKind::Int(_, ref ty) = lit.node {
1335 ast::LitIntType::Signed(ast::IntTy::I128) |
1336 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1337 gate_feature_post!(&self, i128_type, e.span,
1338 "128-bit integers are not stable");
1344 ast::ExprKind::Catch(_) => {
1345 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1349 visit::walk_expr(self, e);
1352 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1353 match pattern.node {
1354 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1355 gate_feature_post!(&self, advanced_slice_patterns,
1357 "multiple-element slice matches anywhere \
1358 but at the end of a slice (e.g. \
1359 `[0, ..xs, 0]`) are experimental")
1361 PatKind::Slice(..) => {
1362 gate_feature_post!(&self, slice_patterns,
1364 "slice pattern syntax is experimental");
1366 PatKind::Box(..) => {
1367 gate_feature_post!(&self, box_patterns,
1369 "box pattern syntax is experimental");
1371 PatKind::Range(_, _, RangeEnd::Excluded) => {
1372 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1373 "exclusive range pattern syntax is experimental");
1377 visit::walk_pat(self, pattern)
1380 fn visit_fn(&mut self,
1381 fn_kind: FnKind<'a>,
1382 fn_decl: &'a ast::FnDecl,
1385 // check for const fn declarations
1386 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1388 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1390 // stability of const fn methods are covered in
1391 // visit_trait_item and visit_impl_item below; this is
1392 // because default methods don't pass through this
1396 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1397 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1398 self.check_abi(abi, span);
1402 visit::walk_fn(self, fn_kind, fn_decl, span);
1405 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
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::Method(ref sig, _) => {
1433 if sig.constness.node == ast::Constness::Const {
1434 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1439 visit::walk_impl_item(self, ii);
1442 fn visit_generics(&mut self, g: &'a ast::Generics) {
1443 for t in &g.ty_params {
1444 if !t.attrs.is_empty() {
1445 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1446 "attributes on type parameter bindings are experimental");
1449 visit::walk_generics(self, g)
1452 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1453 if !lifetime_def.attrs.is_empty() {
1454 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1455 "attributes on lifetime bindings are experimental");
1457 visit::walk_lifetime_def(self, lifetime_def)
1461 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1462 let mut features = Features::new();
1464 let mut feature_checker = MutexFeatureChecker::default();
1466 for attr in krate_attrs {
1467 if !attr.check_name("feature") {
1471 match attr.meta_item_list() {
1473 span_err!(span_handler, attr.span, E0555,
1474 "malformed feature attribute, expected #![feature(...)]");
1478 let name = if let Some(word) = mi.word() {
1481 span_err!(span_handler, mi.span, E0556,
1482 "malformed feature, expected just one word");
1486 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1487 .find(|& &(n, _, _, _)| name == n) {
1488 set(&mut features, mi.span);
1489 feature_checker.collect(&features, mi.span);
1491 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1492 .find(|& &(n, _, _)| name == n)
1493 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1494 .find(|& &(n, _, _)| name == n)) {
1495 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1497 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1498 .find(|& &(n, _, _)| name == n) {
1499 features.declared_stable_lang_features.push((name, mi.span));
1501 features.declared_lib_features.push((name, mi.span));
1508 feature_checker.check(span_handler);
1513 // A collector for mutually-exclusive features and their flag spans
1515 struct MutexFeatureChecker {
1516 proc_macro: Option<Span>,
1517 custom_attribute: Option<Span>,
1520 impl MutexFeatureChecker {
1521 // If this method turns out to be a hotspot due to branching,
1522 // the branching can be eliminated by modifying `set!()` to set these spans
1523 // only for the features that need to be checked for mutual exclusion.
1524 fn collect(&mut self, features: &Features, span: Span) {
1525 if features.proc_macro {
1526 // If self.proc_macro is None, set to Some(span)
1527 self.proc_macro = self.proc_macro.or(Some(span));
1530 if features.custom_attribute {
1531 self.custom_attribute = self.custom_attribute.or(Some(span));
1535 fn check(self, handler: &Handler) {
1536 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1537 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1538 `#![feature(custom_attribute)] at the same time")
1539 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1547 pub fn check_crate(krate: &ast::Crate,
1549 features: &Features,
1550 plugin_attributes: &[(String, AttributeType)],
1551 unstable: UnstableFeatures) {
1552 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1556 plugin_attributes: plugin_attributes,
1558 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1561 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1562 pub enum UnstableFeatures {
1563 /// Hard errors for unstable features are active, as on
1564 /// beta/stable channels.
1566 /// Allow features to be activated, as on nightly.
1568 /// Errors are bypassed for bootstrapping. This is required any time
1569 /// during the build that feature-related lints are set to warn or above
1570 /// because the build turns on warnings-as-errors and uses lots of unstable
1571 /// features. As a result, this is always required for building Rust itself.
1575 impl UnstableFeatures {
1576 pub fn from_environment() -> UnstableFeatures {
1577 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1578 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1579 // Whether we should enable unstable features for bootstrapping
1580 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1581 match (disable_unstable_features, bootstrap) {
1582 (_, true) => UnstableFeatures::Cheat,
1583 (true, _) => UnstableFeatures::Disallow,
1584 (false, _) => UnstableFeatures::Allow
1588 pub fn is_nightly_build(&self) -> bool {
1590 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1596 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1597 unstable: UnstableFeatures) {
1598 let allow_features = match unstable {
1599 UnstableFeatures::Allow => true,
1600 UnstableFeatures::Disallow => false,
1601 UnstableFeatures::Cheat => true
1603 if !allow_features {
1604 for attr in &krate.attrs {
1605 if attr.check_name("feature") {
1606 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1607 span_err!(span_handler, attr.span, E0554,
1608 "#[feature] may not be used on the {} release channel",