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, allocator, "1.0.0", Some(27389)),
141 (active, fundamental, "1.0.0", Some(29635)),
142 (active, main, "1.0.0", Some(29634)),
143 (active, needs_allocator, "1.4.0", Some(27389)),
144 (active, on_unimplemented, "1.0.0", Some(29628)),
145 (active, plugin, "1.0.0", Some(29597)),
146 (active, simd_ffi, "1.0.0", Some(27731)),
147 (active, start, "1.0.0", Some(29633)),
148 (active, structural_match, "1.8.0", Some(31434)),
149 (active, panic_runtime, "1.10.0", Some(32837)),
150 (active, needs_panic_runtime, "1.10.0", Some(32837)),
152 // OIBIT specific features
153 (active, optin_builtin_traits, "1.0.0", Some(13231)),
155 // macro reexport needs more discussion and stabilization
156 (active, macro_reexport, "1.0.0", Some(29638)),
158 // Allows use of #[staged_api]
160 (active, staged_api, "1.0.0", None),
162 // Allows using #![no_core]
163 (active, no_core, "1.3.0", Some(29639)),
165 // Allows using `box` in patterns; RFC 469
166 (active, box_patterns, "1.0.0", Some(29641)),
168 // Allows using the unsafe_destructor_blind_to_params attribute;
170 (active, dropck_parametricity, "1.3.0", Some(28498)),
172 // Allows using the may_dangle attribute; RFC 1327
173 (active, dropck_eyepatch, "1.10.0", Some(34761)),
175 // Allows the use of custom attributes; RFC 572
176 (active, custom_attribute, "1.0.0", Some(29642)),
178 // Allows the use of #[derive(Anything)] as sugar for
179 // #[derive_Anything].
180 (active, custom_derive, "1.0.0", Some(29644)),
182 // Allows the use of rustc_* attributes; RFC 572
183 (active, rustc_attrs, "1.0.0", Some(29642)),
185 // Allows the use of #[allow_internal_unstable]. This is an
186 // attribute on macro_rules! and can't use the attribute handling
187 // below (it has to be checked before expansion possibly makes
188 // macros disappear).
191 (active, allow_internal_unstable, "1.0.0", None),
193 // #23121. Array patterns have some hazards yet.
194 (active, slice_patterns, "1.0.0", Some(23121)),
196 // Allows the definition of associated constants in `trait` or `impl`
198 (active, associated_consts, "1.0.0", Some(29646)),
200 // Allows the definition of `const fn` functions.
201 (active, const_fn, "1.2.0", Some(24111)),
203 // Allows indexing into constant arrays.
204 (active, const_indexing, "1.4.0", Some(29947)),
206 // Allows using #[prelude_import] on glob `use` items.
209 (active, prelude_import, "1.2.0", None),
211 // Allows default type parameters to influence type inference.
212 (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
214 // Allows associated type defaults
215 (active, associated_type_defaults, "1.2.0", Some(29661)),
217 // allow `repr(simd)`, and importing the various simd intrinsics
218 (active, repr_simd, "1.4.0", Some(27731)),
220 // Allows cfg(target_feature = "...").
221 (active, cfg_target_feature, "1.4.0", Some(29717)),
223 // allow `extern "platform-intrinsic" { ... }`
224 (active, platform_intrinsics, "1.4.0", Some(27731)),
227 // rust runtime internal
228 (active, unwind_attributes, "1.4.0", None),
230 // allow the use of `#[naked]` on functions.
231 (active, naked_functions, "1.9.0", Some(32408)),
233 // allow `#[no_debug]`
234 (active, no_debug, "1.5.0", Some(29721)),
236 // allow `#[omit_gdb_pretty_printer_section]`
238 (active, omit_gdb_pretty_printer_section, "1.5.0", None),
240 // Allows cfg(target_vendor = "...").
241 (active, cfg_target_vendor, "1.5.0", Some(29718)),
243 // Allow attributes on expressions and non-item statements
244 (active, stmt_expr_attributes, "1.6.0", Some(15701)),
246 // allow using type ascription in expressions
247 (active, type_ascription, "1.6.0", Some(23416)),
249 // Allows cfg(target_thread_local)
250 (active, cfg_target_thread_local, "1.7.0", Some(29594)),
253 (active, abi_vectorcall, "1.7.0", None),
256 (active, inclusive_range_syntax, "1.7.0", Some(28237)),
259 (active, exclusive_range_pattern, "1.11.0", Some(37854)),
261 // impl specialization (RFC 1210)
262 (active, specialization, "1.7.0", Some(31844)),
264 // Allow Drop types in statics/const functions (RFC 1440)
265 (active, drop_types_in_const, "1.9.0", Some(33156)),
267 // Allows cfg(target_has_atomic = "...").
268 (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
270 // Allows `impl Trait` in function return types.
271 (active, conservative_impl_trait, "1.12.0", Some(34511)),
274 (active, never_type, "1.13.0", Some(35121)),
276 // Allows all literals in attribute lists and values of key-value pairs.
277 (active, attr_literals, "1.13.0", Some(34981)),
279 // Allows the sysV64 ABI to be specified on all platforms
280 // instead of just the platforms on which it is the C ABI
281 (active, abi_sysv64, "1.13.0", Some(36167)),
283 // Allows untagged unions `union U { ... }`
284 (active, untagged_unions, "1.13.0", Some(32836)),
286 // Used to identify the `compiler_builtins` crate
288 (active, compiler_builtins, "1.13.0", None),
290 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
291 (active, generic_param_attrs, "1.11.0", Some(34761)),
293 // Allows #[link(..., cfg(..))]
294 (active, link_cfg, "1.14.0", Some(37406)),
296 (active, use_extern_macros, "1.15.0", Some(35896)),
298 // Allows #[target_feature(...)]
299 (active, target_feature, "1.15.0", None),
301 // `extern "ptx-*" fn()`
302 (active, abi_ptx, "1.15.0", None),
305 (active, i128_type, "1.16.0", Some(35118)),
307 // The `unadjusted` ABI. Perma unstable.
308 (active, abi_unadjusted, "1.16.0", None),
310 // Procedural macros 2.0.
311 (active, proc_macro, "1.16.0", Some(38356)),
313 // Declarative macros 2.0 (`macro`).
314 (active, decl_macro, "1.17.0", Some(39412)),
316 // Allows #[link(kind="static-nobundle"...]
317 (active, static_nobundle, "1.16.0", Some(37403)),
319 // `extern "msp430-interrupt" fn()`
320 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
322 // Used to identify crates that contain sanitizer runtimes
324 (active, sanitizer_runtime, "1.17.0", None),
326 // Used to identify crates that contain the profiler runtime
328 (active, profiler_runtime, "1.18.0", None),
330 // `extern "x86-interrupt" fn()`
331 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
334 // Allows the `catch {...}` expression
335 (active, catch_expr, "1.17.0", Some(31436)),
337 // Allows `repr(align(u16))` struct attribute (RFC 1358)
338 (active, repr_align, "1.17.0", Some(33626)),
340 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
341 (active, rvalue_static_promotion, "1.15.1", Some(38865)),
343 // Used to preserve symbols (see llvm.used)
344 (active, used, "1.18.0", Some(40289)),
346 // Allows module-level inline assembly by way of global_asm!()
347 (active, global_asm, "1.18.0", Some(35119)),
349 // Allows overlapping impls of marker traits
350 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
352 // Allows use of the :vis macro fragment specifier
353 (active, macro_vis_matcher, "1.18.0", Some(41022)),
356 (active, abi_thiscall, "1.19.0", None),
358 // Allows a test to fail without failing the whole suite
359 (active, allow_fail, "1.19.0", Some(42219)),
361 // Allows unsized tuple coercion.
362 (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
366 (removed, import_shadowing, "1.0.0", None),
367 (removed, managed_boxes, "1.0.0", None),
368 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
369 (removed, negate_unsigned, "1.0.0", Some(29645)),
370 (removed, reflect, "1.0.0", Some(27749)),
371 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
372 (removed, opt_out_copy, "1.0.0", None),
373 (removed, quad_precision_float, "1.0.0", None),
374 (removed, struct_inherit, "1.0.0", None),
375 (removed, test_removed_feature, "1.0.0", None),
376 (removed, visible_private_types, "1.0.0", None),
377 (removed, unsafe_no_drop_flag, "1.0.0", None),
378 // Allows using items which are missing stability attributes
380 (removed, unmarked_api, "1.0.0", None),
381 (removed, pushpop_unsafe, "1.2.0", None),
385 (stable_removed, no_stack_check, "1.0.0", None),
389 (accepted, associated_types, "1.0.0", None),
390 // allow overloading augmented assignment operations like `a += b`
391 (accepted, augmented_assignments, "1.8.0", Some(28235)),
392 // allow empty structs and enum variants with braces
393 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
394 (accepted, default_type_params, "1.0.0", None),
395 (accepted, globs, "1.0.0", None),
396 (accepted, if_let, "1.0.0", None),
397 // A temporary feature gate used to enable parser extensions needed
398 // to bootstrap fix for #5723.
399 (accepted, issue_5723_bootstrap, "1.0.0", None),
400 (accepted, macro_rules, "1.0.0", None),
401 // Allows using #![no_std]
402 (accepted, no_std, "1.6.0", None),
403 (accepted, slicing_syntax, "1.0.0", None),
404 (accepted, struct_variant, "1.0.0", None),
405 // These are used to test this portion of the compiler, they don't actually
407 (accepted, test_accepted_feature, "1.0.0", None),
408 (accepted, tuple_indexing, "1.0.0", None),
409 // Allows macros to appear in the type position.
410 (accepted, type_macros, "1.13.0", Some(27245)),
411 (accepted, while_let, "1.0.0", None),
412 // Allows `#[deprecated]` attribute
413 (accepted, deprecated, "1.9.0", Some(29935)),
415 (accepted, question_mark, "1.13.0", Some(31436)),
416 // Allows `..` in tuple (struct) patterns
417 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
418 (accepted, item_like_imports, "1.15.0", Some(35120)),
419 // Allows using `Self` and associated types in struct expressions and patterns.
420 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
421 // elide `'static` lifetimes in `static`s and `const`s
422 (accepted, static_in_const, "1.17.0", Some(35897)),
423 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
424 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
425 // Allows the definition recursive static items.
426 (accepted, static_recursion, "1.17.0", Some(29719)),
427 // pub(restricted) visibilities (RFC 1422)
428 (accepted, pub_restricted, "1.18.0", Some(32409)),
429 // The #![windows_subsystem] attribute
430 (accepted, windows_subsystem, "1.18.0", Some(37499)),
431 // Allows `break {expr}` with a value inside `loop`s.
432 (accepted, loop_break_value, "1.19.0", Some(37339)),
433 // Permits numeric fields in struct expressions and patterns.
434 (accepted, relaxed_adts, "1.19.0", Some(35626)),
435 // Coerces non capturing closures to function pointers
436 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
437 // Allows attributes on struct literal fields.
438 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
441 // If you change this, please modify src/doc/unstable-book as well. You must
442 // move that documentation into the relevant place in the other docs, and
443 // remove the chapter on the flag.
445 #[derive(PartialEq, Copy, Clone, Debug)]
446 pub enum AttributeType {
447 /// Normal, builtin attribute that is consumed
448 /// by the compiler before the unused_attribute check
451 /// Builtin attribute that may not be consumed by the compiler
452 /// before the unused_attribute check. These attributes
453 /// will be ignored by the unused_attribute lint
456 /// Builtin attribute that is only allowed at the crate level
460 pub enum AttributeGate {
461 /// Is gated by a given feature gate, reason
462 /// and function to check if enabled
463 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
465 /// Ungated attribute, can be used on all release channels
470 fn is_deprecated(&self) -> bool {
472 Gated(Stability::Deprecated(_), ..) => true,
478 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
481 // Argument is tracking issue link.
482 Deprecated(&'static str),
486 impl ::std::fmt::Debug for AttributeGate {
487 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
489 Gated(ref stab, name, expl, _) =>
490 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
491 Ungated => write!(fmt, "Ungated")
496 macro_rules! cfg_fn {
497 ($field: ident) => {{
498 fn f(features: &Features) -> bool {
501 f as fn(&Features) -> bool
505 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
506 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
509 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
510 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
513 // Attributes that have a special meaning to rustc or rustdoc
514 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
517 ("warn", Normal, Ungated),
518 ("allow", Normal, Ungated),
519 ("forbid", Normal, Ungated),
520 ("deny", Normal, Ungated),
522 ("macro_reexport", Normal, Ungated),
523 ("macro_use", Normal, Ungated),
524 ("macro_export", Normal, Ungated),
525 ("plugin_registrar", Normal, Ungated),
527 ("cfg", Normal, Ungated),
528 ("cfg_attr", Normal, Ungated),
529 ("main", Normal, Ungated),
530 ("start", Normal, Ungated),
531 ("test", Normal, Ungated),
532 ("bench", Normal, Ungated),
533 ("simd", Normal, Ungated),
534 ("repr", Normal, Ungated),
535 ("path", Normal, Ungated),
536 ("abi", Normal, Ungated),
537 ("automatically_derived", Normal, Ungated),
538 ("no_mangle", Normal, Ungated),
539 ("no_link", Normal, Ungated),
540 ("derive", Normal, Ungated),
541 ("should_panic", Normal, Ungated),
542 ("ignore", Normal, Ungated),
543 ("no_implicit_prelude", Normal, Ungated),
544 ("reexport_test_harness_main", Normal, Ungated),
545 ("link_args", Normal, Ungated),
546 ("macro_escape", Normal, Ungated),
549 ("structural_match", Whitelisted, Gated(Stability::Unstable,
551 "the semantics of constant patterns is \
553 cfg_fn!(structural_match))),
555 ("plugin", CrateLevel, Gated(Stability::Unstable,
557 "compiler plugins are experimental \
561 ("no_std", CrateLevel, Ungated),
562 ("no_core", CrateLevel, Gated(Stability::Unstable,
564 "no_core is experimental",
566 ("lang", Normal, Gated(Stability::Unstable,
568 "language items are subject to change",
569 cfg_fn!(lang_items))),
570 ("linkage", Whitelisted, Gated(Stability::Unstable,
572 "the `linkage` attribute is experimental \
573 and not portable across platforms",
575 ("thread_local", Whitelisted, Gated(Stability::Unstable,
577 "`#[thread_local]` is an experimental feature, and does \
578 not currently handle destructors. There is no \
579 corresponding `#[task_local]` mapping to the task \
581 cfg_fn!(thread_local))),
583 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
585 "the `#[rustc_on_unimplemented]` attribute \
586 is an experimental feature",
587 cfg_fn!(on_unimplemented))),
588 ("allocator", Whitelisted, Gated(Stability::Unstable,
590 "the `#[allocator]` attribute is an experimental feature",
591 cfg_fn!(allocator))),
592 ("needs_allocator", Normal, Gated(Stability::Unstable,
594 "the `#[needs_allocator]` \
595 attribute is an experimental \
597 cfg_fn!(needs_allocator))),
598 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
600 "the `#[panic_runtime]` attribute is \
601 an experimental feature",
602 cfg_fn!(panic_runtime))),
603 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
604 "needs_panic_runtime",
605 "the `#[needs_panic_runtime]` \
606 attribute is an experimental \
608 cfg_fn!(needs_panic_runtime))),
609 ("rustc_variance", Normal, Gated(Stability::Unstable,
611 "the `#[rustc_variance]` attribute \
612 is just used for rustc unit tests \
613 and will never be stable",
614 cfg_fn!(rustc_attrs))),
615 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
617 "the `#[rustc_error]` attribute \
618 is just used for rustc unit tests \
619 and will never be stable",
620 cfg_fn!(rustc_attrs))),
621 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
623 "the `#[rustc_if_this_changed]` attribute \
624 is just used for rustc unit tests \
625 and will never be stable",
626 cfg_fn!(rustc_attrs))),
627 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
629 "the `#[rustc_if_this_changed]` attribute \
630 is just used for rustc unit tests \
631 and will never be stable",
632 cfg_fn!(rustc_attrs))),
633 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
635 "the `#[rustc_dirty]` attribute \
636 is just used for rustc unit tests \
637 and will never be stable",
638 cfg_fn!(rustc_attrs))),
639 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
641 "the `#[rustc_clean]` attribute \
642 is just used for rustc unit tests \
643 and will never be stable",
644 cfg_fn!(rustc_attrs))),
645 ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
647 "the `#[rustc_metadata_dirty]` attribute \
648 is just used for rustc unit tests \
649 and will never be stable",
650 cfg_fn!(rustc_attrs))),
651 ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
653 "the `#[rustc_metadata_clean]` attribute \
654 is just used for rustc unit tests \
655 and will never be stable",
656 cfg_fn!(rustc_attrs))),
657 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
660 is just used for rustc unit tests \
661 and will never be stable",
662 cfg_fn!(rustc_attrs))),
663 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
666 is just used for rustc unit tests \
667 and will never be stable",
668 cfg_fn!(rustc_attrs))),
669 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
671 "internal rustc attributes will never be stable",
672 cfg_fn!(rustc_attrs))),
673 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
675 "internal rustc attributes will never be stable",
676 cfg_fn!(rustc_attrs))),
677 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
679 "the `#[rustc_mir]` attribute \
680 is just used for rustc unit tests \
681 and will never be stable",
682 cfg_fn!(rustc_attrs))),
683 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
685 "the `#[rustc_inherit_overflow_checks]` \
686 attribute is just used to control \
687 overflow checking behavior of several \
688 libcore functions that are inlined \
689 across crates and will never be stable",
690 cfg_fn!(rustc_attrs))),
691 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
693 "the `#[compiler_builtins]` attribute is used to \
694 identify the `compiler_builtins` crate which \
695 contains compiler-rt intrinsics and will never be \
697 cfg_fn!(compiler_builtins))),
698 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
700 "the `#[sanitizer_runtime]` attribute is used to \
701 identify crates that contain the runtime of a \
702 sanitizer and will never be stable",
703 cfg_fn!(sanitizer_runtime))),
704 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
706 "the `#[profiler_runtime]` attribute is used to \
707 identify the `profiler_builtins` crate which \
708 contains the profiler runtime and will never be \
710 cfg_fn!(profiler_runtime))),
712 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
713 "allow_internal_unstable",
714 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
715 cfg_fn!(allow_internal_unstable))),
717 ("fundamental", Whitelisted, Gated(Stability::Unstable,
719 "the `#[fundamental]` attribute \
720 is an experimental feature",
721 cfg_fn!(fundamental))),
723 ("proc_macro_derive", Normal, Ungated),
725 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
727 "internal implementation detail",
728 cfg_fn!(rustc_attrs))),
730 // FIXME: #14408 whitelist docs since rustdoc looks at them
731 ("doc", Whitelisted, Ungated),
733 // FIXME: #14406 these are processed in trans, which happens after the
735 ("cold", Whitelisted, Ungated),
736 ("naked", Whitelisted, Gated(Stability::Unstable,
738 "the `#[naked]` attribute \
739 is an experimental feature",
740 cfg_fn!(naked_functions))),
741 ("target_feature", Whitelisted, Gated(
742 Stability::Unstable, "target_feature",
743 "the `#[target_feature]` attribute is an experimental feature",
744 cfg_fn!(target_feature))),
745 ("export_name", Whitelisted, Ungated),
746 ("inline", Whitelisted, Ungated),
747 ("link", Whitelisted, Ungated),
748 ("link_name", Whitelisted, Ungated),
749 ("link_section", Whitelisted, Ungated),
750 ("no_builtins", Whitelisted, Ungated),
751 ("no_mangle", Whitelisted, Ungated),
752 ("no_debug", Whitelisted, Gated(
753 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
755 "the `#[no_debug]` attribute is an experimental feature",
757 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
758 "omit_gdb_pretty_printer_section",
759 "the `#[omit_gdb_pretty_printer_section]` \
760 attribute is just used for the Rust test \
762 cfg_fn!(omit_gdb_pretty_printer_section))),
763 ("unsafe_destructor_blind_to_params",
765 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
766 "dropck_parametricity",
767 "unsafe_destructor_blind_to_params has been replaced by \
768 may_dangle and will be removed in the future",
769 cfg_fn!(dropck_parametricity))),
772 Gated(Stability::Unstable,
774 "may_dangle has unstable semantics and may be removed in the future",
775 cfg_fn!(dropck_eyepatch))),
776 ("unwind", Whitelisted, Gated(Stability::Unstable,
778 "#[unwind] is experimental",
779 cfg_fn!(unwind_attributes))),
780 ("used", Whitelisted, Gated(
781 Stability::Unstable, "used",
782 "the `#[used]` attribute is an experimental feature",
786 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
788 "`#[prelude_import]` is for use by rustc only",
789 cfg_fn!(prelude_import))),
791 // FIXME: #14407 these are only looked at on-demand so we can't
792 // guarantee they'll have already been checked
793 ("rustc_deprecated", Whitelisted, Ungated),
794 ("must_use", Whitelisted, Ungated),
795 ("stable", Whitelisted, Ungated),
796 ("unstable", Whitelisted, Ungated),
797 ("deprecated", Normal, Ungated),
799 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
801 "unboxed_closures are still evolving",
802 cfg_fn!(unboxed_closures))),
804 ("windows_subsystem", Whitelisted, Ungated),
806 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
808 "attribute proc macros are currently unstable",
809 cfg_fn!(proc_macro))),
811 ("proc_macro", Normal, Gated(Stability::Unstable,
813 "function-like proc macros are currently unstable",
814 cfg_fn!(proc_macro))),
816 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
817 "rustc_derive_registrar",
818 "used internally by rustc",
819 cfg_fn!(rustc_attrs))),
821 ("allow_fail", Normal, Gated(Stability::Unstable,
823 "allow_fail attribute is currently unstable",
824 cfg_fn!(allow_fail))),
826 // Crate level attributes
827 ("crate_name", CrateLevel, Ungated),
828 ("crate_type", CrateLevel, Ungated),
829 ("crate_id", CrateLevel, Ungated),
830 ("feature", CrateLevel, Ungated),
831 ("no_start", CrateLevel, Ungated),
832 ("no_main", CrateLevel, Ungated),
833 ("no_builtins", CrateLevel, Ungated),
834 ("recursion_limit", CrateLevel, Ungated),
835 ("type_length_limit", CrateLevel, Ungated),
838 // cfg(...)'s that are feature gated
839 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
840 // (name in cfg, feature, function to check if the feature is enabled)
841 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
842 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
843 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
844 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
847 #[derive(Debug, Eq, PartialEq)]
848 pub struct GatedCfg {
854 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
855 let name = cfg.name().as_str();
857 .position(|info| info.0 == name)
866 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
867 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
868 if !has_feature(features) && !self.span.allows_unstable() {
869 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
870 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
876 features: &'a Features,
877 parse_sess: &'a ParseSess,
878 plugin_attributes: &'a [(String, AttributeType)],
881 macro_rules! gate_feature_fn {
882 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
883 let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
884 let has_feature: bool = has_feature(&$cx.features);
885 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
886 if !has_feature && !span.allows_unstable() {
887 emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
892 macro_rules! gate_feature {
893 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
894 gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
898 impl<'a> Context<'a> {
899 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
900 debug!("check_attribute(attr = {:?})", attr);
901 let name = unwrap_or!(attr.name(), return).as_str();
902 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
904 if let Gated(_, name, desc, ref has_feature) = *gateage {
905 gate_feature_fn!(self, has_feature, attr.span, name, desc);
907 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
911 for &(ref n, ref ty) in self.plugin_attributes {
912 if attr.path == &**n {
913 // Plugins can't gate attributes, so we don't check for it
914 // unlike the code above; we only use this loop to
915 // short-circuit to avoid the checks below
916 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
920 if name.starts_with("rustc_") {
921 gate_feature!(self, rustc_attrs, attr.span,
922 "unless otherwise specified, attributes \
923 with the prefix `rustc_` \
924 are reserved for internal compiler diagnostics");
925 } else if name.starts_with("derive_") {
926 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
927 } else if !attr::is_known(attr) {
928 // Only run the custom attribute lint during regular
929 // feature gate checking. Macro gating runs
930 // before the plugin attributes are registered
931 // so we skip this then
933 gate_feature!(self, custom_attribute, attr.span,
934 &format!("The attribute `{}` is currently \
935 unknown to the compiler and \
937 added to it in the future",
944 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
945 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
946 cx.check_attribute(attr, true);
949 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
950 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
953 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
954 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
956 // FIXME (#28244): enforce that active features have issue numbers
957 // assert!(issue.is_some())
960 // search in Accepted, Removed, or Stable Removed features
961 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
962 .find(|t| t.0 == feature);
964 Some(&(_, _, issue)) => issue,
965 None => panic!("Feature `{}` is not declared anywhere", feature),
975 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
977 feature_err(sess, feature, span, issue, explain).emit();
980 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
981 explain: &str) -> DiagnosticBuilder<'a> {
982 let diag = &sess.span_diagnostic;
984 let issue = match issue {
985 GateIssue::Language => find_lang_feature_issue(feature),
986 GateIssue::Library(lib) => lib,
989 let mut err = if let Some(n) = issue {
990 diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
992 diag.struct_span_err(span, explain)
995 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
996 if sess.unstable_features.is_nightly_build() {
997 err.help(&format!("add #![feature({})] to the \
998 crate attributes to enable",
1005 const EXPLAIN_BOX_SYNTAX: &'static str =
1006 "box expression syntax is experimental; you can call `Box::new` instead.";
1008 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1009 "attributes on non-item statements and expressions are experimental.";
1011 pub const EXPLAIN_ASM: &'static str =
1012 "inline assembly is not stable enough for use and is subject to change";
1014 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1015 "`global_asm!` is not stable enough for use and is subject to change";
1017 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1018 "`log_syntax!` is not stable enough for use and is subject to change";
1020 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1021 "`concat_idents` is not stable enough for use and is subject to change";
1023 pub const EXPLAIN_COMPILE_ERROR: &'static str =
1024 "`compile_error` is not stable enough for use and is subject to change";
1026 pub const EXPLAIN_TRACE_MACROS: &'static str =
1027 "`trace_macros` is not stable enough for use and is subject to change";
1028 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1029 "allow_internal_unstable side-steps feature gating and stability checks";
1031 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1032 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1034 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1035 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1036 Prefer using procedural macro custom derive.";
1038 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1039 "attributes of the form `#[derive_*]` are reserved for the compiler";
1041 pub const EXPLAIN_VIS_MATCHER: &'static str =
1042 ":vis fragment specifier is experimental and subject to change";
1044 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1045 "placement-in expression syntax is experimental and subject to change.";
1047 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1048 "Unsized tuple coercion is not stable enough for use and is subject to change";
1050 struct PostExpansionVisitor<'a> {
1051 context: &'a Context<'a>,
1054 macro_rules! gate_feature_post {
1055 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1056 let (cx, span) = ($cx, $span);
1057 if !span.allows_unstable() {
1058 gate_feature!(cx.context, $feature, span, $explain)
1063 impl<'a> PostExpansionVisitor<'a> {
1064 fn check_abi(&self, abi: Abi, span: Span) {
1066 Abi::RustIntrinsic => {
1067 gate_feature_post!(&self, intrinsics, span,
1068 "intrinsics are subject to change");
1070 Abi::PlatformIntrinsic => {
1071 gate_feature_post!(&self, platform_intrinsics, span,
1072 "platform intrinsics are experimental and possibly buggy");
1074 Abi::Vectorcall => {
1075 gate_feature_post!(&self, abi_vectorcall, span,
1076 "vectorcall is experimental and subject to change");
1079 gate_feature_post!(&self, abi_thiscall, span,
1080 "thiscall is experimental and subject to change");
1083 gate_feature_post!(&self, unboxed_closures, span,
1084 "rust-call ABI is subject to change");
1087 gate_feature_post!(&self, abi_sysv64, span,
1088 "sysv64 ABI is experimental and subject to change");
1091 gate_feature_post!(&self, abi_ptx, span,
1092 "PTX ABIs are experimental and subject to change");
1094 Abi::Unadjusted => {
1095 gate_feature_post!(&self, abi_unadjusted, span,
1096 "unadjusted ABI is an implementation detail and perma-unstable");
1098 Abi::Msp430Interrupt => {
1099 gate_feature_post!(&self, abi_msp430_interrupt, span,
1100 "msp430-interrupt ABI is experimental and subject to change");
1102 Abi::X86Interrupt => {
1103 gate_feature_post!(&self, abi_x86_interrupt, span,
1104 "x86-interrupt ABI is experimental and subject to change");
1119 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1120 use ast::MetaItemKind::*;
1121 use ast::NestedMetaItemKind::*;
1125 NameValue(ref lit) => !lit.node.is_str(),
1126 List(ref list) => list.iter().any(|li| {
1128 MetaItem(ref mi) => contains_novel_literal(mi),
1135 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1136 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1137 if !attr.span.allows_unstable() {
1138 // check for gated attributes
1139 self.context.check_attribute(attr, false);
1142 if self.context.features.proc_macro && attr::is_known(attr) {
1146 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1147 if contains_novel_literal(&meta) {
1148 gate_feature_post!(&self, attr_literals, attr.span,
1149 "non-string literals in attributes, or string \
1150 literals in top-level positions, are experimental");
1154 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1155 if !name.as_str().is_ascii() {
1156 gate_feature_post!(&self, non_ascii_idents, sp,
1157 "non-ascii idents are not fully supported.");
1161 fn visit_item(&mut self, i: &'a ast::Item) {
1163 ast::ItemKind::ExternCrate(_) => {
1164 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1165 gate_feature_post!(&self, macro_reexport, i.span,
1166 "macros reexports are experimental \
1167 and possibly buggy");
1171 ast::ItemKind::ForeignMod(ref foreign_module) => {
1172 if attr::contains_name(&i.attrs[..], "link_args") {
1173 gate_feature_post!(&self, link_args, i.span,
1174 "the `link_args` attribute is not portable \
1175 across platforms, it is recommended to \
1176 use `#[link(name = \"foo\")]` instead")
1178 self.check_abi(foreign_module.abi, i.span);
1181 ast::ItemKind::Fn(..) => {
1182 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1183 gate_feature_post!(&self, plugin_registrar, i.span,
1184 "compiler plugins are experimental and possibly buggy");
1186 if attr::contains_name(&i.attrs[..], "start") {
1187 gate_feature_post!(&self, start, i.span,
1188 "a #[start] function is an experimental \
1189 feature whose signature may change \
1192 if attr::contains_name(&i.attrs[..], "main") {
1193 gate_feature_post!(&self, main, i.span,
1194 "declaration of a nonstandard #[main] \
1195 function may change over time, for now \
1196 a top-level `fn main()` is required");
1200 ast::ItemKind::Struct(..) => {
1201 if attr::contains_name(&i.attrs[..], "simd") {
1202 gate_feature_post!(&self, simd, i.span,
1203 "SIMD types are experimental and possibly buggy");
1204 self.context.parse_sess.span_diagnostic.span_warn(i.span,
1205 "the `#[simd]` attribute \
1206 is deprecated, use \
1207 `#[repr(simd)]` instead");
1209 for attr in &i.attrs {
1210 if attr.path == "repr" {
1211 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1212 if item.check_name("simd") {
1213 gate_feature_post!(&self, repr_simd, i.span,
1214 "SIMD types are experimental \
1215 and possibly buggy");
1218 if item.check_name("align") {
1219 gate_feature_post!(&self, repr_align, i.span,
1220 "the struct `#[repr(align(u16))]` attribute \
1228 ast::ItemKind::DefaultImpl(..) => {
1229 gate_feature_post!(&self, optin_builtin_traits,
1231 "default trait implementations are experimental \
1232 and possibly buggy");
1235 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1236 if polarity == ast::ImplPolarity::Negative {
1237 gate_feature_post!(&self, optin_builtin_traits,
1239 "negative trait bounds are not yet fully implemented; \
1240 use marker types for now");
1243 if let ast::Defaultness::Default = defaultness {
1244 gate_feature_post!(&self, specialization,
1246 "specialization is unstable");
1250 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1251 let msg = "`macro` is experimental";
1252 gate_feature_post!(&self, decl_macro, i.span, msg);
1258 visit::walk_item(self, i);
1261 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1262 let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1263 Some(val) => val.as_str().starts_with("llvm."),
1267 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1268 "linking to LLVM intrinsics is experimental");
1271 visit::walk_foreign_item(self, i)
1274 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1276 ast::TyKind::BareFn(ref bare_fn_ty) => {
1277 self.check_abi(bare_fn_ty.abi, ty.span);
1279 ast::TyKind::ImplTrait(..) => {
1280 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1281 "`impl Trait` is experimental");
1283 ast::TyKind::Never => {
1284 gate_feature_post!(&self, never_type, ty.span,
1285 "The `!` type is experimental");
1289 visit::walk_ty(self, ty)
1292 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1293 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1294 if output_ty.node != ast::TyKind::Never {
1295 self.visit_ty(output_ty)
1300 fn visit_expr(&mut self, e: &'a ast::Expr) {
1302 ast::ExprKind::Box(_) => {
1303 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1305 ast::ExprKind::Type(..) => {
1306 gate_feature_post!(&self, type_ascription, e.span,
1307 "type ascription is experimental");
1309 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1310 gate_feature_post!(&self, inclusive_range_syntax,
1312 "inclusive range syntax is experimental");
1314 ast::ExprKind::InPlace(..) => {
1315 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1317 ast::ExprKind::Lit(ref lit) => {
1318 if let ast::LitKind::Int(_, ref ty) = lit.node {
1320 ast::LitIntType::Signed(ast::IntTy::I128) |
1321 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1322 gate_feature_post!(&self, i128_type, e.span,
1323 "128-bit integers are not stable");
1329 ast::ExprKind::Catch(_) => {
1330 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1334 visit::walk_expr(self, e);
1337 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1338 match pattern.node {
1339 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1340 gate_feature_post!(&self, advanced_slice_patterns,
1342 "multiple-element slice matches anywhere \
1343 but at the end of a slice (e.g. \
1344 `[0, ..xs, 0]`) are experimental")
1346 PatKind::Slice(..) => {
1347 gate_feature_post!(&self, slice_patterns,
1349 "slice pattern syntax is experimental");
1351 PatKind::Box(..) => {
1352 gate_feature_post!(&self, box_patterns,
1354 "box pattern syntax is experimental");
1356 PatKind::Range(_, _, RangeEnd::Excluded) => {
1357 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1358 "exclusive range pattern syntax is experimental");
1362 visit::walk_pat(self, pattern)
1365 fn visit_fn(&mut self,
1366 fn_kind: FnKind<'a>,
1367 fn_decl: &'a ast::FnDecl,
1370 // check for const fn declarations
1371 if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1373 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1375 // stability of const fn methods are covered in
1376 // visit_trait_item and visit_impl_item below; this is
1377 // because default methods don't pass through this
1381 FnKind::ItemFn(_, _, _, _, abi, _, _) |
1382 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1383 self.check_abi(abi, span);
1387 visit::walk_fn(self, fn_kind, fn_decl, span);
1390 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1392 ast::TraitItemKind::Const(..) => {
1393 gate_feature_post!(&self, associated_consts,
1395 "associated constants are experimental")
1397 ast::TraitItemKind::Method(ref sig, ref block) => {
1398 if block.is_none() {
1399 self.check_abi(sig.abi, ti.span);
1401 if sig.constness.node == ast::Constness::Const {
1402 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1405 ast::TraitItemKind::Type(_, Some(_)) => {
1406 gate_feature_post!(&self, associated_type_defaults, ti.span,
1407 "associated type defaults are unstable");
1411 visit::walk_trait_item(self, ti);
1414 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1415 if ii.defaultness == ast::Defaultness::Default {
1416 gate_feature_post!(&self, specialization,
1418 "specialization is unstable");
1422 ast::ImplItemKind::Const(..) => {
1423 gate_feature_post!(&self, associated_consts,
1425 "associated constants are experimental")
1427 ast::ImplItemKind::Method(ref sig, _) => {
1428 if sig.constness.node == ast::Constness::Const {
1429 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1434 visit::walk_impl_item(self, ii);
1437 fn visit_generics(&mut self, g: &'a ast::Generics) {
1438 for t in &g.ty_params {
1439 if !t.attrs.is_empty() {
1440 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1441 "attributes on type parameter bindings are experimental");
1444 visit::walk_generics(self, g)
1447 fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1448 if !lifetime_def.attrs.is_empty() {
1449 gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1450 "attributes on lifetime bindings are experimental");
1452 visit::walk_lifetime_def(self, lifetime_def)
1456 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1457 let mut features = Features::new();
1459 let mut feature_checker = MutexFeatureChecker::default();
1461 for attr in krate_attrs {
1462 if !attr.check_name("feature") {
1466 match attr.meta_item_list() {
1468 span_err!(span_handler, attr.span, E0555,
1469 "malformed feature attribute, expected #![feature(...)]");
1473 let name = if let Some(word) = mi.word() {
1476 span_err!(span_handler, mi.span, E0556,
1477 "malformed feature, expected just one word");
1481 if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
1482 .find(|& &(n, _, _, _)| name == n) {
1483 *(setter(&mut features)) = true;
1484 feature_checker.collect(&features, mi.span);
1486 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1487 .find(|& &(n, _, _)| name == n)
1488 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1489 .find(|& &(n, _, _)| name == n)) {
1490 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1492 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1493 .find(|& &(n, _, _)| name == n) {
1494 features.declared_stable_lang_features.push((name, mi.span));
1496 features.declared_lib_features.push((name, mi.span));
1503 feature_checker.check(span_handler);
1508 // A collector for mutually-exclusive features and their flag spans
1510 struct MutexFeatureChecker {
1511 proc_macro: Option<Span>,
1512 custom_attribute: Option<Span>,
1515 impl MutexFeatureChecker {
1516 // If this method turns out to be a hotspot due to branching,
1517 // the branching can be eliminated by modifying `setter!()` to set these spans
1518 // only for the features that need to be checked for mutual exclusion.
1519 fn collect(&mut self, features: &Features, span: Span) {
1520 if features.proc_macro {
1521 // If self.proc_macro is None, set to Some(span)
1522 self.proc_macro = self.proc_macro.or(Some(span));
1525 if features.custom_attribute {
1526 self.custom_attribute = self.custom_attribute.or(Some(span));
1530 fn check(self, handler: &Handler) {
1531 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1532 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1533 `#![feature(custom_attribute)] at the same time")
1534 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1542 pub fn check_crate(krate: &ast::Crate,
1544 features: &Features,
1545 plugin_attributes: &[(String, AttributeType)],
1546 unstable: UnstableFeatures) {
1547 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1551 plugin_attributes: plugin_attributes,
1553 visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1556 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1557 pub enum UnstableFeatures {
1558 /// Hard errors for unstable features are active, as on
1559 /// beta/stable channels.
1561 /// Allow features to be activated, as on nightly.
1563 /// Errors are bypassed for bootstrapping. This is required any time
1564 /// during the build that feature-related lints are set to warn or above
1565 /// because the build turns on warnings-as-errors and uses lots of unstable
1566 /// features. As a result, this is always required for building Rust itself.
1570 impl UnstableFeatures {
1571 pub fn from_environment() -> UnstableFeatures {
1572 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1573 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1574 // Whether we should enable unstable features for bootstrapping
1575 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1576 match (disable_unstable_features, bootstrap) {
1577 (_, true) => UnstableFeatures::Cheat,
1578 (true, _) => UnstableFeatures::Disallow,
1579 (false, _) => UnstableFeatures::Allow
1583 pub fn is_nightly_build(&self) -> bool {
1585 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1591 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1592 unstable: UnstableFeatures) {
1593 let allow_features = match unstable {
1594 UnstableFeatures::Allow => true,
1595 UnstableFeatures::Disallow => false,
1596 UnstableFeatures::Cheat => true
1598 if !allow_features {
1599 for attr in &krate.attrs {
1600 if attr.check_name("feature") {
1601 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1602 span_err!(span_handler, attr.span, E0554,
1603 "#[feature] may not be used on the {} release channel",