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, RangeSyntax};
33 use errors::{DiagnosticBuilder, Handler, FatalError};
34 use visit::{self, FnKind, Visitor};
36 use symbol::{keywords, Symbol};
42 fn f(features: &mut Features, span: Span) {
43 features.declared_lib_features.push((Symbol::intern("proc_macro"), span));
44 features.proc_macro = true;
46 f as fn(&mut Features, Span)
49 fn f(features: &mut Features, _: Span) {
50 features.$field = true;
52 f as fn(&mut Features, Span)
56 macro_rules! declare_features {
57 ($((active, $feature: ident, $ver: expr, $issue: expr),)+) => {
58 /// Represents active features that are currently being implemented or
59 /// currently being considered for addition/removal.
60 const ACTIVE_FEATURES:
61 &'static [(&'static str, &'static str, Option<u32>, fn(&mut Features, Span))] =
62 &[$((stringify!($feature), $ver, $issue, set!($feature))),+];
64 /// A set of features to be used by later passes.
66 /// `#![feature]` attrs for stable language features, for error reporting
67 pub declared_stable_lang_features: Vec<(Symbol, Span)>,
68 /// `#![feature]` attrs for non-language (library) features
69 pub declared_lib_features: Vec<(Symbol, Span)>,
70 $(pub $feature: bool),+
74 pub fn new() -> Features {
76 declared_stable_lang_features: Vec::new(),
77 declared_lib_features: Vec::new(),
84 ($((removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
85 /// Represents unstable features which have since been removed (it was once Active)
86 const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
87 $((stringify!($feature), $ver, $issue)),+
91 ($((stable_removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
92 /// Represents stable features which have since been removed (it was once Accepted)
93 const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
94 $((stringify!($feature), $ver, $issue)),+
98 ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => {
99 /// Those language feature has since been Accepted (it was once Active)
100 const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
101 $((stringify!($feature), $ver, $issue)),+
106 // If you change this, please modify src/doc/unstable-book as well.
108 // Don't ever remove anything from this list; set them to 'Removed'.
110 // The version numbers here correspond to the version in which the current status
111 // was set. This is most important for knowing when a particular feature became
114 // NB: tools/tidy/src/features.rs parses this information directly out of the
115 // source, so take care when modifying it.
118 (active, asm, "1.0.0", Some(29722)),
119 (active, concat_idents, "1.0.0", Some(29599)),
120 (active, link_args, "1.0.0", Some(29596)),
121 (active, log_syntax, "1.0.0", Some(29598)),
122 (active, non_ascii_idents, "1.0.0", Some(28979)),
123 (active, plugin_registrar, "1.0.0", Some(29597)),
124 (active, thread_local, "1.0.0", Some(29594)),
125 (active, trace_macros, "1.0.0", Some(29598)),
127 // rustc internal, for now:
128 (active, intrinsics, "1.0.0", None),
129 (active, lang_items, "1.0.0", None),
131 (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
132 (active, linkage, "1.0.0", Some(29603)),
133 (active, quote, "1.0.0", Some(29601)),
134 (active, simd, "1.0.0", Some(27731)),
138 (active, rustc_diagnostic_macros, "1.0.0", None),
139 (active, rustc_const_unstable, "1.0.0", None),
140 (active, advanced_slice_patterns, "1.0.0", Some(23121)),
141 (active, box_syntax, "1.0.0", Some(27779)),
142 (active, placement_in_syntax, "1.0.0", Some(27779)),
143 (active, unboxed_closures, "1.0.0", Some(29625)),
145 (active, fundamental, "1.0.0", Some(29635)),
146 (active, main, "1.0.0", Some(29634)),
147 (active, needs_allocator, "1.4.0", Some(27389)),
148 (active, on_unimplemented, "1.0.0", Some(29628)),
149 (active, plugin, "1.0.0", Some(29597)),
150 (active, simd_ffi, "1.0.0", Some(27731)),
151 (active, start, "1.0.0", Some(29633)),
152 (active, structural_match, "1.8.0", Some(31434)),
153 (active, panic_runtime, "1.10.0", Some(32837)),
154 (active, needs_panic_runtime, "1.10.0", Some(32837)),
156 // OIBIT specific features
157 (active, optin_builtin_traits, "1.0.0", Some(13231)),
159 // macro reexport needs more discussion and stabilization
160 (active, macro_reexport, "1.0.0", Some(29638)),
162 // Allows use of #[staged_api]
164 (active, staged_api, "1.0.0", None),
166 // Allows using #![no_core]
167 (active, no_core, "1.3.0", Some(29639)),
169 // Allows using `box` in patterns; RFC 469
170 (active, box_patterns, "1.0.0", Some(29641)),
172 // Allows using the unsafe_destructor_blind_to_params attribute;
174 (active, dropck_parametricity, "1.3.0", Some(28498)),
176 // Allows using the may_dangle attribute; RFC 1327
177 (active, dropck_eyepatch, "1.10.0", Some(34761)),
179 // Allows the use of custom attributes; RFC 572
180 (active, custom_attribute, "1.0.0", Some(29642)),
182 // Allows the use of #[derive(Anything)] as sugar for
183 // #[derive_Anything].
184 (active, custom_derive, "1.0.0", Some(29644)),
186 // Allows the use of rustc_* attributes; RFC 572
187 (active, rustc_attrs, "1.0.0", Some(29642)),
189 // Allows the use of non lexical lifetimes; RFC 2094
190 (active, nll, "1.0.0", Some(44928)),
192 // Allows the use of #[allow_internal_unstable]. This is an
193 // attribute on macro_rules! and can't use the attribute handling
194 // below (it has to be checked before expansion possibly makes
195 // macros disappear).
198 (active, allow_internal_unstable, "1.0.0", None),
200 // Allows the use of #[allow_internal_unsafe]. This is an
201 // attribute on macro_rules! and can't use the attribute handling
202 // below (it has to be checked before expansion possibly makes
203 // macros disappear).
206 (active, allow_internal_unsafe, "1.0.0", None),
208 // #23121. Array patterns have some hazards yet.
209 (active, slice_patterns, "1.0.0", Some(23121)),
211 // Allows the definition of `const fn` functions.
212 (active, const_fn, "1.2.0", Some(24111)),
214 // Allows indexing into constant arrays.
215 (active, const_indexing, "1.4.0", Some(29947)),
217 // Allows using #[prelude_import] on glob `use` items.
220 (active, prelude_import, "1.2.0", None),
222 // Allows default type parameters to influence type inference.
223 (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
225 // Allows associated type defaults
226 (active, associated_type_defaults, "1.2.0", Some(29661)),
228 // allow `repr(simd)`, and importing the various simd intrinsics
229 (active, repr_simd, "1.4.0", Some(27731)),
231 // Allows cfg(target_feature = "...").
232 (active, cfg_target_feature, "1.4.0", Some(29717)),
234 // allow `extern "platform-intrinsic" { ... }`
235 (active, platform_intrinsics, "1.4.0", Some(27731)),
238 // rust runtime internal
239 (active, unwind_attributes, "1.4.0", None),
241 // allow the use of `#[naked]` on functions.
242 (active, naked_functions, "1.9.0", Some(32408)),
244 // allow `#[no_debug]`
245 (active, no_debug, "1.5.0", Some(29721)),
247 // allow `#[omit_gdb_pretty_printer_section]`
249 (active, omit_gdb_pretty_printer_section, "1.5.0", None),
251 // Allows cfg(target_vendor = "...").
252 (active, cfg_target_vendor, "1.5.0", Some(29718)),
254 // Allow attributes on expressions and non-item statements
255 (active, stmt_expr_attributes, "1.6.0", Some(15701)),
257 // allow using type ascription in expressions
258 (active, type_ascription, "1.6.0", Some(23416)),
260 // Allows cfg(target_thread_local)
261 (active, cfg_target_thread_local, "1.7.0", Some(29594)),
264 (active, abi_vectorcall, "1.7.0", None),
267 (active, inclusive_range_syntax, "1.7.0", Some(28237)),
270 (active, exclusive_range_pattern, "1.11.0", Some(37854)),
272 // impl specialization (RFC 1210)
273 (active, specialization, "1.7.0", Some(31844)),
275 // Allows cfg(target_has_atomic = "...").
276 (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
278 // Allows `impl Trait` in function return types.
279 (active, conservative_impl_trait, "1.12.0", Some(34511)),
281 // Allows `impl Trait` in function arguments.
282 (active, universal_impl_trait, "1.23.0", Some(34511)),
285 (active, never_type, "1.13.0", Some(35121)),
287 // Allows all literals in attribute lists and values of key-value pairs.
288 (active, attr_literals, "1.13.0", Some(34981)),
290 // Allows untagged unions `union U { ... }`
291 (active, untagged_unions, "1.13.0", Some(32836)),
293 // Used to identify the `compiler_builtins` crate
295 (active, compiler_builtins, "1.13.0", None),
297 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
298 (active, generic_param_attrs, "1.11.0", Some(34761)),
300 // Allows #[link(..., cfg(..))]
301 (active, link_cfg, "1.14.0", Some(37406)),
303 (active, use_extern_macros, "1.15.0", Some(35896)),
305 // Allows #[target_feature(...)]
306 (active, target_feature, "1.15.0", None),
308 // `extern "ptx-*" fn()`
309 (active, abi_ptx, "1.15.0", None),
312 (active, i128_type, "1.16.0", Some(35118)),
314 // The `repr(i128)` annotation for enums
315 (active, repr128, "1.16.0", Some(35118)),
317 // The `unadjusted` ABI. Perma unstable.
318 (active, abi_unadjusted, "1.16.0", None),
320 // Procedural macros 2.0.
321 (active, proc_macro, "1.16.0", Some(38356)),
323 // Declarative macros 2.0 (`macro`).
324 (active, decl_macro, "1.17.0", Some(39412)),
326 // Allows #[link(kind="static-nobundle"...]
327 (active, static_nobundle, "1.16.0", Some(37403)),
329 // `extern "msp430-interrupt" fn()`
330 (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
332 // Used to identify crates that contain sanitizer runtimes
334 (active, sanitizer_runtime, "1.17.0", None),
336 // Used to identify crates that contain the profiler runtime
338 (active, profiler_runtime, "1.18.0", None),
340 // `extern "x86-interrupt" fn()`
341 (active, abi_x86_interrupt, "1.17.0", Some(40180)),
344 // Allows the `catch {...}` expression
345 (active, catch_expr, "1.17.0", Some(31436)),
347 // Allows `repr(align(u16))` struct attribute (RFC 1358)
348 (active, repr_align, "1.17.0", Some(33626)),
350 // Used to preserve symbols (see llvm.used)
351 (active, used, "1.18.0", Some(40289)),
353 // Allows module-level inline assembly by way of global_asm!()
354 (active, global_asm, "1.18.0", Some(35119)),
356 // Allows overlapping impls of marker traits
357 (active, overlapping_marker_traits, "1.18.0", Some(29864)),
359 // Allows use of the :vis macro fragment specifier
360 (active, macro_vis_matcher, "1.18.0", Some(41022)),
363 (active, abi_thiscall, "1.19.0", None),
365 // Allows a test to fail without failing the whole suite
366 (active, allow_fail, "1.19.0", Some(42219)),
368 // Allows unsized tuple coercion.
369 (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
372 (active, generators, "1.21.0", None),
375 (active, trait_alias, "1.24.0", Some(41517)),
377 // global allocators and their internals
378 (active, global_allocator, "1.20.0", None),
379 (active, allocator_internals, "1.20.0", None),
382 (active, doc_cfg, "1.21.0", Some(43781)),
384 (active, doc_masked, "1.21.0", Some(44027)),
386 (active, doc_spotlight, "1.22.0", Some(45040)),
387 // #[doc(include="some-file")]
388 (active, external_doc, "1.22.0", Some(44732)),
390 // allow `#[must_use]` on functions and comparison operators (RFC 1940)
391 (active, fn_must_use, "1.21.0", Some(43302)),
393 // allow '|' at beginning of match arms (RFC 1925)
394 (active, match_beginning_vert, "1.21.0", Some(44101)),
396 // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
397 (active, non_exhaustive, "1.22.0", Some(44109)),
399 // Copy/Clone closures (RFC 2132)
400 (active, clone_closures, "1.22.0", Some(44490)),
401 (active, copy_closures, "1.22.0", Some(44490)),
403 // allow `'_` placeholder lifetimes
404 (active, underscore_lifetimes, "1.22.0", Some(44524)),
406 // allow `..=` in patterns (RFC 1192)
407 (active, dotdoteq_in_patterns, "1.22.0", Some(28237)),
409 // Default match binding modes (RFC 2005)
410 (active, match_default_bindings, "1.22.0", Some(42640)),
412 // Trait object syntax with `dyn` prefix
413 (active, dyn_trait, "1.22.0", Some(44662)),
415 // `crate` as visibility modifier, synonymous to `pub(crate)`
416 (active, crate_visibility_modifier, "1.23.0", Some(45388)),
419 (active, extern_types, "1.23.0", Some(43467)),
421 // Allow trait methods with arbitrary self types
422 (active, arbitrary_self_types, "1.23.0", Some(44874)),
424 // #![wasm_import_memory] attribute
425 (active, wasm_import_memory, "1.22.0", None),
428 (active, crate_in_paths, "1.23.0", Some(45477)),
430 // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`)
431 (active, in_band_lifetimes, "1.23.0", Some(44524)),
433 // Nested groups in `use` (RFC 2128)
434 (active, use_nested_groups, "1.23.0", Some(44494)),
436 // generic associated types (RFC 1598)
437 (active, generic_associated_types, "1.23.0", Some(44265)),
439 // Resolve absolute paths as paths from other crates
440 (active, extern_absolute_paths, "1.24.0", Some(44660)),
442 // `foo.rs` as an alternative to `foo/mod.rs`
443 (active, non_modrs_mods, "1.24.0", Some(44660)),
445 // Nested `impl Trait`
446 (active, nested_impl_trait, "1.24.0", Some(34511)),
448 // Termination trait in main (RFC 1937)
449 (active, termination_trait, "1.24.0", Some(43301)),
451 // Allows use of the :lifetime macro fragment specifier
452 (active, macro_lifetime_matcher, "1.24.0", Some(46895)),
455 (active, extern_in_paths, "1.23.0", Some(44660)),
459 (removed, import_shadowing, "1.0.0", None),
460 (removed, managed_boxes, "1.0.0", None),
461 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
462 (removed, negate_unsigned, "1.0.0", Some(29645)),
463 (removed, reflect, "1.0.0", Some(27749)),
464 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
465 (removed, opt_out_copy, "1.0.0", None),
466 (removed, quad_precision_float, "1.0.0", None),
467 (removed, struct_inherit, "1.0.0", None),
468 (removed, test_removed_feature, "1.0.0", None),
469 (removed, visible_private_types, "1.0.0", None),
470 (removed, unsafe_no_drop_flag, "1.0.0", None),
471 // Allows using items which are missing stability attributes
473 (removed, unmarked_api, "1.0.0", None),
474 (removed, pushpop_unsafe, "1.2.0", None),
475 (removed, allocator, "1.0.0", None),
479 (stable_removed, no_stack_check, "1.0.0", None),
483 (accepted, associated_types, "1.0.0", None),
484 // allow overloading augmented assignment operations like `a += b`
485 (accepted, augmented_assignments, "1.8.0", Some(28235)),
486 // allow empty structs and enum variants with braces
487 (accepted, braced_empty_structs, "1.8.0", Some(29720)),
488 (accepted, default_type_params, "1.0.0", None),
489 (accepted, globs, "1.0.0", None),
490 (accepted, if_let, "1.0.0", None),
491 // A temporary feature gate used to enable parser extensions needed
492 // to bootstrap fix for #5723.
493 (accepted, issue_5723_bootstrap, "1.0.0", None),
494 (accepted, macro_rules, "1.0.0", None),
495 // Allows using #![no_std]
496 (accepted, no_std, "1.6.0", None),
497 (accepted, slicing_syntax, "1.0.0", None),
498 (accepted, struct_variant, "1.0.0", None),
499 // These are used to test this portion of the compiler, they don't actually
501 (accepted, test_accepted_feature, "1.0.0", None),
502 (accepted, tuple_indexing, "1.0.0", None),
503 // Allows macros to appear in the type position.
504 (accepted, type_macros, "1.13.0", Some(27245)),
505 (accepted, while_let, "1.0.0", None),
506 // Allows `#[deprecated]` attribute
507 (accepted, deprecated, "1.9.0", Some(29935)),
509 (accepted, question_mark, "1.13.0", Some(31436)),
510 // Allows `..` in tuple (struct) patterns
511 (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
512 (accepted, item_like_imports, "1.15.0", Some(35120)),
513 // Allows using `Self` and associated types in struct expressions and patterns.
514 (accepted, more_struct_aliases, "1.16.0", Some(37544)),
515 // elide `'static` lifetimes in `static`s and `const`s
516 (accepted, static_in_const, "1.17.0", Some(35897)),
517 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
518 (accepted, field_init_shorthand, "1.17.0", Some(37340)),
519 // Allows the definition recursive static items.
520 (accepted, static_recursion, "1.17.0", Some(29719)),
521 // pub(restricted) visibilities (RFC 1422)
522 (accepted, pub_restricted, "1.18.0", Some(32409)),
523 // The #![windows_subsystem] attribute
524 (accepted, windows_subsystem, "1.18.0", Some(37499)),
525 // Allows `break {expr}` with a value inside `loop`s.
526 (accepted, loop_break_value, "1.19.0", Some(37339)),
527 // Permits numeric fields in struct expressions and patterns.
528 (accepted, relaxed_adts, "1.19.0", Some(35626)),
529 // Coerces non capturing closures to function pointers
530 (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
531 // Allows attributes on struct literal fields.
532 (accepted, struct_field_attributes, "1.20.0", Some(38814)),
533 // Allows the definition of associated constants in `trait` or `impl`
535 (accepted, associated_consts, "1.20.0", Some(29646)),
536 // Usage of the `compile_error!` macro
537 (accepted, compile_error, "1.20.0", Some(40872)),
538 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
539 (accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
540 // Allow Drop types in constants (RFC 1440)
541 (accepted, drop_types_in_const, "1.22.0", Some(33156)),
542 // Allows the sysV64 ABI to be specified on all platforms
543 // instead of just the platforms on which it is the C ABI
544 (accepted, abi_sysv64, "1.24.0", Some(36167)),
547 // If you change this, please modify src/doc/unstable-book as well. You must
548 // move that documentation into the relevant place in the other docs, and
549 // remove the chapter on the flag.
551 #[derive(PartialEq, Copy, Clone, Debug)]
552 pub enum AttributeType {
553 /// Normal, builtin attribute that is consumed
554 /// by the compiler before the unused_attribute check
557 /// Builtin attribute that may not be consumed by the compiler
558 /// before the unused_attribute check. These attributes
559 /// will be ignored by the unused_attribute lint
562 /// Builtin attribute that is only allowed at the crate level
566 pub enum AttributeGate {
567 /// Is gated by a given feature gate, reason
568 /// and function to check if enabled
569 Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
571 /// Ungated attribute, can be used on all release channels
576 fn is_deprecated(&self) -> bool {
578 Gated(Stability::Deprecated(_), ..) => true,
584 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
587 // Argument is tracking issue link.
588 Deprecated(&'static str),
592 impl ::std::fmt::Debug for AttributeGate {
593 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
595 Gated(ref stab, name, expl, _) =>
596 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
597 Ungated => write!(fmt, "Ungated")
602 macro_rules! cfg_fn {
603 ($field: ident) => {{
604 fn f(features: &Features) -> bool {
607 f as fn(&Features) -> bool
611 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
612 BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
615 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
616 BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
619 // Attributes that have a special meaning to rustc or rustdoc
620 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
623 ("warn", Normal, Ungated),
624 ("allow", Normal, Ungated),
625 ("forbid", Normal, Ungated),
626 ("deny", Normal, Ungated),
628 ("macro_reexport", Normal, Ungated),
629 ("macro_use", Normal, Ungated),
630 ("macro_export", Normal, Ungated),
631 ("plugin_registrar", Normal, Ungated),
633 ("cfg", Normal, Ungated),
634 ("cfg_attr", Normal, Ungated),
635 ("main", Normal, Ungated),
636 ("start", Normal, Ungated),
637 ("test", Normal, Ungated),
638 ("bench", Normal, Ungated),
639 ("simd", Normal, Ungated),
640 ("repr", Normal, Ungated),
641 ("path", Normal, Ungated),
642 ("abi", Normal, Ungated),
643 ("automatically_derived", Normal, Ungated),
644 ("no_mangle", Normal, Ungated),
645 ("no_link", Normal, Ungated),
646 ("derive", Normal, Ungated),
647 ("should_panic", Normal, Ungated),
648 ("ignore", Normal, Ungated),
649 ("no_implicit_prelude", Normal, Ungated),
650 ("reexport_test_harness_main", Normal, Ungated),
651 ("link_args", Normal, Gated(Stability::Unstable,
653 "the `link_args` attribute is experimental and not \
654 portable across platforms, it is recommended to \
655 use `#[link(name = \"foo\")] instead",
656 cfg_fn!(link_args))),
657 ("macro_escape", Normal, Ungated),
660 ("structural_match", Whitelisted, Gated(Stability::Unstable,
662 "the semantics of constant patterns is \
664 cfg_fn!(structural_match))),
667 ("non_exhaustive", Whitelisted, Gated(Stability::Unstable,
669 "non exhaustive is an experimental feature",
670 cfg_fn!(non_exhaustive))),
672 ("plugin", CrateLevel, Gated(Stability::Unstable,
674 "compiler plugins are experimental \
678 ("no_std", CrateLevel, Ungated),
679 ("no_core", CrateLevel, Gated(Stability::Unstable,
681 "no_core is experimental",
683 ("lang", Normal, Gated(Stability::Unstable,
685 "language items are subject to change",
686 cfg_fn!(lang_items))),
687 ("linkage", Whitelisted, Gated(Stability::Unstable,
689 "the `linkage` attribute is experimental \
690 and not portable across platforms",
692 ("thread_local", Whitelisted, Gated(Stability::Unstable,
694 "`#[thread_local]` is an experimental feature, and does \
695 not currently handle destructors. There is no \
696 corresponding `#[task_local]` mapping to the task \
698 cfg_fn!(thread_local))),
700 ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
702 "the `#[rustc_on_unimplemented]` attribute \
703 is an experimental feature",
704 cfg_fn!(on_unimplemented))),
705 ("rustc_const_unstable", Normal, Gated(Stability::Unstable,
706 "rustc_const_unstable",
707 "the `#[rustc_const_unstable]` attribute \
708 is an internal feature",
709 cfg_fn!(rustc_const_unstable))),
710 ("global_allocator", Normal, Gated(Stability::Unstable,
712 "the `#[global_allocator]` attribute is \
713 an experimental feature",
714 cfg_fn!(global_allocator))),
715 ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
716 "allocator_internals",
717 "the `#[default_lib_allocator]` \
718 attribute is an experimental feature",
719 cfg_fn!(allocator_internals))),
720 ("needs_allocator", Normal, Gated(Stability::Unstable,
721 "allocator_internals",
722 "the `#[needs_allocator]` \
723 attribute is an experimental \
725 cfg_fn!(allocator_internals))),
726 ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
728 "the `#[panic_runtime]` attribute is \
729 an experimental feature",
730 cfg_fn!(panic_runtime))),
731 ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
732 "needs_panic_runtime",
733 "the `#[needs_panic_runtime]` \
734 attribute is an experimental \
736 cfg_fn!(needs_panic_runtime))),
737 ("rustc_variance", Normal, Gated(Stability::Unstable,
739 "the `#[rustc_variance]` attribute \
740 is just used for rustc unit tests \
741 and will never be stable",
742 cfg_fn!(rustc_attrs))),
743 ("rustc_regions", Normal, Gated(Stability::Unstable,
745 "the `#[rustc_regions]` attribute \
746 is just used for rustc unit tests \
747 and will never be stable",
748 cfg_fn!(rustc_attrs))),
749 ("rustc_error", Whitelisted, Gated(Stability::Unstable,
751 "the `#[rustc_error]` attribute \
752 is just used for rustc unit tests \
753 and will never be stable",
754 cfg_fn!(rustc_attrs))),
755 ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
757 "the `#[rustc_if_this_changed]` attribute \
758 is just used for rustc unit tests \
759 and will never be stable",
760 cfg_fn!(rustc_attrs))),
761 ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
763 "the `#[rustc_if_this_changed]` attribute \
764 is just used for rustc unit tests \
765 and will never be stable",
766 cfg_fn!(rustc_attrs))),
767 ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
769 "the `#[rustc_dirty]` attribute \
770 is just used for rustc unit tests \
771 and will never be stable",
772 cfg_fn!(rustc_attrs))),
773 ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
775 "the `#[rustc_clean]` attribute \
776 is just used for rustc unit tests \
777 and will never be stable",
778 cfg_fn!(rustc_attrs))),
779 ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
782 is just used for rustc unit tests \
783 and will never be stable",
784 cfg_fn!(rustc_attrs))),
785 ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
788 is just used for rustc unit tests \
789 and will never be stable",
790 cfg_fn!(rustc_attrs))),
791 ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable,
794 is just used for rustc unit tests \
795 and will never be stable",
796 cfg_fn!(rustc_attrs))),
797 ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
799 "internal rustc attributes will never be stable",
800 cfg_fn!(rustc_attrs))),
801 ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
803 "internal rustc attributes will never be stable",
804 cfg_fn!(rustc_attrs))),
805 ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
807 "the `#[rustc_mir]` attribute \
808 is just used for rustc unit tests \
809 and will never be stable",
810 cfg_fn!(rustc_attrs))),
811 ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
813 "the `#[rustc_inherit_overflow_checks]` \
814 attribute is just used to control \
815 overflow checking behavior of several \
816 libcore functions that are inlined \
817 across crates and will never be stable",
818 cfg_fn!(rustc_attrs))),
821 ("nll", Whitelisted, Gated(Stability::Unstable,
823 "Non lexical lifetimes",
825 ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
827 "the `#[compiler_builtins]` attribute is used to \
828 identify the `compiler_builtins` crate which \
829 contains compiler-rt intrinsics and will never be \
831 cfg_fn!(compiler_builtins))),
832 ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
834 "the `#[sanitizer_runtime]` attribute is used to \
835 identify crates that contain the runtime of a \
836 sanitizer and will never be stable",
837 cfg_fn!(sanitizer_runtime))),
838 ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
840 "the `#[profiler_runtime]` attribute is used to \
841 identify the `profiler_builtins` crate which \
842 contains the profiler runtime and will never be \
844 cfg_fn!(profiler_runtime))),
846 ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
847 "allow_internal_unstable",
848 EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
849 cfg_fn!(allow_internal_unstable))),
851 ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
852 "allow_internal_unsafe",
853 EXPLAIN_ALLOW_INTERNAL_UNSAFE,
854 cfg_fn!(allow_internal_unsafe))),
856 ("fundamental", Whitelisted, Gated(Stability::Unstable,
858 "the `#[fundamental]` attribute \
859 is an experimental feature",
860 cfg_fn!(fundamental))),
862 ("proc_macro_derive", Normal, Ungated),
864 ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
866 "internal implementation detail",
867 cfg_fn!(rustc_attrs))),
869 // FIXME: #14408 whitelist docs since rustdoc looks at them
870 ("doc", Whitelisted, Ungated),
872 // FIXME: #14406 these are processed in trans, which happens after the
874 ("cold", Whitelisted, Ungated),
875 ("naked", Whitelisted, Gated(Stability::Unstable,
877 "the `#[naked]` attribute \
878 is an experimental feature",
879 cfg_fn!(naked_functions))),
880 ("target_feature", Whitelisted, Gated(
881 Stability::Unstable, "target_feature",
882 "the `#[target_feature]` attribute is an experimental feature",
883 cfg_fn!(target_feature))),
884 ("export_name", Whitelisted, Ungated),
885 ("inline", Whitelisted, Ungated),
886 ("link", Whitelisted, Ungated),
887 ("link_name", Whitelisted, Ungated),
888 ("link_section", Whitelisted, Ungated),
889 ("no_builtins", Whitelisted, Ungated),
890 ("no_mangle", Whitelisted, Ungated),
891 ("no_debug", Whitelisted, Gated(
892 Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
894 "the `#[no_debug]` attribute was an experimental feature that has been \
895 deprecated due to lack of demand",
897 ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
898 "omit_gdb_pretty_printer_section",
899 "the `#[omit_gdb_pretty_printer_section]` \
900 attribute is just used for the Rust test \
902 cfg_fn!(omit_gdb_pretty_printer_section))),
903 ("unsafe_destructor_blind_to_params",
905 Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
906 "dropck_parametricity",
907 "unsafe_destructor_blind_to_params has been replaced by \
908 may_dangle and will be removed in the future",
909 cfg_fn!(dropck_parametricity))),
912 Gated(Stability::Unstable,
914 "may_dangle has unstable semantics and may be removed in the future",
915 cfg_fn!(dropck_eyepatch))),
916 ("unwind", Whitelisted, Gated(Stability::Unstable,
918 "#[unwind] is experimental",
919 cfg_fn!(unwind_attributes))),
920 ("used", Whitelisted, Gated(
921 Stability::Unstable, "used",
922 "the `#[used]` attribute is an experimental feature",
926 ("prelude_import", Whitelisted, Gated(Stability::Unstable,
928 "`#[prelude_import]` is for use by rustc only",
929 cfg_fn!(prelude_import))),
931 // FIXME: #14407 these are only looked at on-demand so we can't
932 // guarantee they'll have already been checked
933 ("rustc_deprecated", Whitelisted, Ungated),
934 ("must_use", Whitelisted, Ungated),
935 ("stable", Whitelisted, Ungated),
936 ("unstable", Whitelisted, Ungated),
937 ("deprecated", Normal, Ungated),
939 ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
941 "unboxed_closures are still evolving",
942 cfg_fn!(unboxed_closures))),
944 ("windows_subsystem", Whitelisted, Ungated),
946 ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
948 "attribute proc macros are currently unstable",
949 cfg_fn!(proc_macro))),
951 ("proc_macro", Normal, Gated(Stability::Unstable,
953 "function-like proc macros are currently unstable",
954 cfg_fn!(proc_macro))),
956 ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
957 "rustc_derive_registrar",
958 "used internally by rustc",
959 cfg_fn!(rustc_attrs))),
961 ("allow_fail", Normal, Gated(Stability::Unstable,
963 "allow_fail attribute is currently unstable",
964 cfg_fn!(allow_fail))),
966 ("rustc_std_internal_symbol", Whitelisted, Gated(Stability::Unstable,
968 "this is an internal attribute that will \
970 cfg_fn!(rustc_attrs))),
972 // whitelists "identity-like" conversion methods to suggest on type mismatch
973 ("rustc_conversion_suggestion", Whitelisted, Gated(Stability::Unstable,
975 "this is an internal attribute that will \
977 cfg_fn!(rustc_attrs))),
979 ("wasm_import_memory", Whitelisted, Gated(Stability::Unstable,
980 "wasm_import_memory",
981 "wasm_import_memory attribute is currently unstable",
982 cfg_fn!(wasm_import_memory))),
984 // Crate level attributes
985 ("crate_name", CrateLevel, Ungated),
986 ("crate_type", CrateLevel, Ungated),
987 ("crate_id", CrateLevel, Ungated),
988 ("feature", CrateLevel, Ungated),
989 ("no_start", CrateLevel, Ungated),
990 ("no_main", CrateLevel, Ungated),
991 ("no_builtins", CrateLevel, Ungated),
992 ("recursion_limit", CrateLevel, Ungated),
993 ("type_length_limit", CrateLevel, Ungated),
996 // cfg(...)'s that are feature gated
997 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
998 // (name in cfg, feature, function to check if the feature is enabled)
999 ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
1000 ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
1001 ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
1002 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
1005 #[derive(Debug, Eq, PartialEq)]
1006 pub struct GatedCfg {
1012 pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
1013 let name = cfg.name().as_str();
1015 .position(|info| info.0 == name)
1024 pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
1025 let (cfg, feature, has_feature) = GATED_CFGS[self.index];
1026 if !has_feature(features) && !self.span.allows_unstable() {
1027 let explain = format!("`cfg({})` is experimental and subject to change", cfg);
1028 emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
1033 struct Context<'a> {
1034 features: &'a Features,
1035 parse_sess: &'a ParseSess,
1036 plugin_attributes: &'a [(String, AttributeType)],
1039 macro_rules! gate_feature_fn {
1040 ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
1041 let (cx, has_feature, span,
1042 name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
1043 let has_feature: bool = has_feature(&$cx.features);
1044 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
1045 if !has_feature && !span.allows_unstable() {
1046 leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
1052 macro_rules! gate_feature {
1053 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
1054 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
1055 stringify!($feature), $explain, GateStrength::Hard)
1057 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
1058 gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
1059 stringify!($feature), $explain, $level)
1063 impl<'a> Context<'a> {
1064 fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
1065 debug!("check_attribute(attr = {:?})", attr);
1066 let name = unwrap_or!(attr.name(), return).as_str();
1067 for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
1069 if let Gated(_, name, desc, ref has_feature) = *gateage {
1070 gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
1071 } else if name == "doc" {
1072 if let Some(content) = attr.meta_item_list() {
1073 if content.iter().any(|c| c.check_name("include")) {
1074 gate_feature!(self, external_doc, attr.span,
1075 "#[doc(include = \"...\")] is experimental"
1080 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
1084 for &(ref n, ref ty) in self.plugin_attributes {
1085 if attr.path == &**n {
1086 // Plugins can't gate attributes, so we don't check for it
1087 // unlike the code above; we only use this loop to
1088 // short-circuit to avoid the checks below
1089 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
1093 if name.starts_with("rustc_") {
1094 gate_feature!(self, rustc_attrs, attr.span,
1095 "unless otherwise specified, attributes \
1096 with the prefix `rustc_` \
1097 are reserved for internal compiler diagnostics");
1098 } else if name.starts_with("derive_") {
1099 gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
1100 } else if !attr::is_known(attr) {
1101 // Only run the custom attribute lint during regular
1102 // feature gate checking. Macro gating runs
1103 // before the plugin attributes are registered
1104 // so we skip this then
1106 gate_feature!(self, custom_attribute, attr.span,
1107 &format!("The attribute `{}` is currently \
1108 unknown to the compiler and \
1110 added to it in the future",
1117 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
1118 let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
1119 cx.check_attribute(attr, true);
1122 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
1123 ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
1126 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
1127 if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
1129 // FIXME (#28244): enforce that active features have issue numbers
1130 // assert!(issue.is_some())
1133 // search in Accepted, Removed, or Stable Removed features
1134 let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
1135 .find(|t| t.0 == feature);
1137 Some(&(_, _, issue)) => issue,
1138 None => panic!("Feature `{}` is not declared anywhere", feature),
1143 pub enum GateIssue {
1145 Library(Option<u32>)
1148 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1149 pub enum GateStrength {
1150 /// A hard error. (Most feature gates should use this.)
1152 /// Only a warning. (Use this only as backwards-compatibility demands.)
1156 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1158 feature_err(sess, feature, span, issue, explain).emit();
1161 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1162 explain: &str) -> DiagnosticBuilder<'a> {
1163 leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
1166 fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1167 explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
1168 let diag = &sess.span_diagnostic;
1170 let issue = match issue {
1171 GateIssue::Language => find_lang_feature_issue(feature),
1172 GateIssue::Library(lib) => lib,
1175 let explanation = if let Some(n) = issue {
1176 format!("{} (see issue #{})", explain, n)
1181 let mut err = match level {
1182 GateStrength::Hard => diag.struct_span_err(span, &explanation),
1183 GateStrength::Soft => diag.struct_span_warn(span, &explanation),
1186 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1187 if sess.unstable_features.is_nightly_build() {
1188 err.help(&format!("add #![feature({})] to the \
1189 crate attributes to enable",
1193 // If we're on stable and only emitting a "soft" warning, add a note to
1194 // clarify that the feature isn't "on" (rather than being on but
1196 if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
1197 err.help("a nightly build of the compiler is required to enable this feature");
1204 const EXPLAIN_BOX_SYNTAX: &'static str =
1205 "box expression syntax is experimental; you can call `Box::new` instead.";
1207 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1208 "attributes on non-item statements and expressions are experimental.";
1210 pub const EXPLAIN_ASM: &'static str =
1211 "inline assembly is not stable enough for use and is subject to change";
1213 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1214 "`global_asm!` is not stable enough for use and is subject to change";
1216 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1217 "`log_syntax!` is not stable enough for use and is subject to change";
1219 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1220 "`concat_idents` is not stable enough for use and is subject to change";
1222 pub const EXPLAIN_TRACE_MACROS: &'static str =
1223 "`trace_macros` is not stable enough for use and is subject to change";
1224 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1225 "allow_internal_unstable side-steps feature gating and stability checks";
1226 pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
1227 "allow_internal_unsafe side-steps the unsafe_code lint";
1229 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1230 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1232 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1233 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1234 Prefer using procedural macro custom derive.";
1236 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1237 "attributes of the form `#[derive_*]` are reserved for the compiler";
1239 pub const EXPLAIN_VIS_MATCHER: &'static str =
1240 ":vis fragment specifier is experimental and subject to change";
1242 pub const EXPLAIN_LIFETIME_MATCHER: &'static str =
1243 ":lifetime fragment specifier is experimental and subject to change";
1245 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1246 "placement-in expression syntax is experimental and subject to change.";
1248 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1249 "Unsized tuple coercion is not stable enough for use and is subject to change";
1251 struct PostExpansionVisitor<'a> {
1252 context: &'a Context<'a>,
1255 macro_rules! gate_feature_post {
1256 ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1257 let (cx, span) = ($cx, $span);
1258 if !span.allows_unstable() {
1259 gate_feature!(cx.context, $feature, span, $explain)
1262 ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
1263 let (cx, span) = ($cx, $span);
1264 if !span.allows_unstable() {
1265 gate_feature!(cx.context, $feature, span, $explain, $level)
1270 impl<'a> PostExpansionVisitor<'a> {
1271 fn check_abi(&self, abi: Abi, span: Span) {
1273 Abi::RustIntrinsic => {
1274 gate_feature_post!(&self, intrinsics, span,
1275 "intrinsics are subject to change");
1277 Abi::PlatformIntrinsic => {
1278 gate_feature_post!(&self, platform_intrinsics, span,
1279 "platform intrinsics are experimental and possibly buggy");
1281 Abi::Vectorcall => {
1282 gate_feature_post!(&self, abi_vectorcall, span,
1283 "vectorcall is experimental and subject to change");
1286 gate_feature_post!(&self, abi_thiscall, span,
1287 "thiscall is experimental and subject to change");
1290 gate_feature_post!(&self, unboxed_closures, span,
1291 "rust-call ABI is subject to change");
1294 gate_feature_post!(&self, abi_ptx, span,
1295 "PTX ABIs are experimental and subject to change");
1297 Abi::Unadjusted => {
1298 gate_feature_post!(&self, abi_unadjusted, span,
1299 "unadjusted ABI is an implementation detail and perma-unstable");
1301 Abi::Msp430Interrupt => {
1302 gate_feature_post!(&self, abi_msp430_interrupt, span,
1303 "msp430-interrupt ABI is experimental and subject to change");
1305 Abi::X86Interrupt => {
1306 gate_feature_post!(&self, abi_x86_interrupt, span,
1307 "x86-interrupt ABI is experimental and subject to change");
1323 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1324 use ast::MetaItemKind::*;
1325 use ast::NestedMetaItemKind::*;
1329 NameValue(ref lit) => !lit.node.is_str(),
1330 List(ref list) => list.iter().any(|li| {
1332 MetaItem(ref mi) => contains_novel_literal(mi),
1339 // Bans nested `impl Trait`, e.g. `impl Into<impl Debug>`.
1340 // Nested `impl Trait` _is_ allowed in associated type position,
1341 // e.g `impl Iterator<Item=impl Debug>`
1342 struct NestedImplTraitVisitor<'a> {
1343 context: &'a Context<'a>,
1344 is_in_impl_trait: bool,
1347 impl<'a> NestedImplTraitVisitor<'a> {
1348 fn with_impl_trait<F>(&mut self, is_in_impl_trait: bool, f: F)
1349 where F: FnOnce(&mut NestedImplTraitVisitor<'a>)
1351 let old_is_in_impl_trait = self.is_in_impl_trait;
1352 self.is_in_impl_trait = is_in_impl_trait;
1354 self.is_in_impl_trait = old_is_in_impl_trait;
1359 impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
1360 fn visit_ty(&mut self, t: &'a ast::Ty) {
1361 if let ast::TyKind::ImplTrait(_) = t.node {
1362 if self.is_in_impl_trait {
1363 gate_feature_post!(&self, nested_impl_trait, t.span,
1364 "nested `impl Trait` is experimental"
1367 self.with_impl_trait(true, |this| visit::walk_ty(this, t));
1369 visit::walk_ty(self, t);
1372 fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a ast::PathParameters) {
1373 match *path_parameters {
1374 ast::PathParameters::AngleBracketed(ref params) => {
1375 for type_ in ¶ms.types {
1376 self.visit_ty(type_);
1378 for type_binding in ¶ms.bindings {
1379 // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
1380 // are allowed to contain nested `impl Trait`.
1381 self.with_impl_trait(false, |this| visit::walk_ty(this, &type_binding.ty));
1384 ast::PathParameters::Parenthesized(ref params) => {
1385 for type_ in ¶ms.inputs {
1386 self.visit_ty(type_);
1388 if let Some(ref type_) = params.output {
1389 // `-> Foo` syntax is essentially an associated type binding,
1390 // so it is also allowed to contain nested `impl Trait`.
1391 self.with_impl_trait(false, |this| visit::walk_ty(this, type_));
1398 impl<'a> PostExpansionVisitor<'a> {
1399 fn whole_crate_feature_gates(&mut self, krate: &ast::Crate) {
1401 &mut NestedImplTraitVisitor {
1402 context: self.context,
1403 is_in_impl_trait: false,
1406 for &(ident, span) in &*self.context.parse_sess.non_modrs_mods.borrow() {
1407 if !span.allows_unstable() {
1408 let cx = &self.context;
1409 let level = GateStrength::Hard;
1410 let has_feature = cx.features.non_modrs_mods;
1411 let name = "non_modrs_mods";
1412 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}",
1413 name, span, has_feature);
1415 if !has_feature && !span.allows_unstable() {
1416 leveled_feature_err(
1417 cx.parse_sess, name, span, GateIssue::Language,
1418 "mod statements in non-mod.rs files are unstable", level
1420 .help(&format!("on stable builds, rename this file to {}{}mod.rs",
1421 ident, path::MAIN_SEPARATOR))
1429 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1430 fn visit_attribute(&mut self, attr: &ast::Attribute) {
1431 if !attr.span.allows_unstable() {
1432 // check for gated attributes
1433 self.context.check_attribute(attr, false);
1436 if attr.check_name("doc") {
1437 if let Some(content) = attr.meta_item_list() {
1438 if content.len() == 1 && content[0].check_name("cfg") {
1439 gate_feature_post!(&self, doc_cfg, attr.span,
1440 "#[doc(cfg(...))] is experimental"
1442 } else if content.iter().any(|c| c.check_name("masked")) {
1443 gate_feature_post!(&self, doc_masked, attr.span,
1444 "#[doc(masked)] is experimental"
1446 } else if content.iter().any(|c| c.check_name("spotlight")) {
1447 gate_feature_post!(&self, doc_spotlight, attr.span,
1448 "#[doc(spotlight)] is experimental"
1454 if self.context.features.proc_macro && attr::is_known(attr) {
1458 let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1459 if contains_novel_literal(&meta) {
1460 gate_feature_post!(&self, attr_literals, attr.span,
1461 "non-string literals in attributes, or string \
1462 literals in top-level positions, are experimental");
1466 fn visit_name(&mut self, sp: Span, name: ast::Name) {
1467 if !name.as_str().is_ascii() {
1468 gate_feature_post!(&self,
1470 self.context.parse_sess.codemap().def_span(sp),
1471 "non-ascii idents are not fully supported.");
1475 fn visit_item(&mut self, i: &'a ast::Item) {
1477 ast::ItemKind::ExternCrate(_) => {
1478 if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
1479 gate_feature_post!(&self, macro_reexport, attr.span,
1480 "macros reexports are experimental \
1481 and possibly buggy");
1485 ast::ItemKind::ForeignMod(ref foreign_module) => {
1486 self.check_abi(foreign_module.abi, i.span);
1489 ast::ItemKind::Fn(..) => {
1490 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1491 gate_feature_post!(&self, plugin_registrar, i.span,
1492 "compiler plugins are experimental and possibly buggy");
1494 if attr::contains_name(&i.attrs[..], "start") {
1495 gate_feature_post!(&self, start, i.span,
1496 "a #[start] function is an experimental \
1497 feature whose signature may change \
1500 if attr::contains_name(&i.attrs[..], "main") {
1501 gate_feature_post!(&self, main, i.span,
1502 "declaration of a nonstandard #[main] \
1503 function may change over time, for now \
1504 a top-level `fn main()` is required");
1506 if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") {
1507 gate_feature_post!(&self, fn_must_use, attr.span,
1508 "`#[must_use]` on functions is experimental",
1509 GateStrength::Soft);
1513 ast::ItemKind::Struct(..) => {
1514 if let Some(attr) = attr::find_by_name(&i.attrs[..], "simd") {
1515 gate_feature_post!(&self, simd, attr.span,
1516 "SIMD types are experimental and possibly buggy");
1517 self.context.parse_sess.span_diagnostic.span_warn(attr.span,
1518 "the `#[simd]` attribute \
1519 is deprecated, use \
1520 `#[repr(simd)]` instead");
1522 if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
1523 for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1524 if item.check_name("simd") {
1525 gate_feature_post!(&self, repr_simd, attr.span,
1526 "SIMD types are experimental and possibly buggy");
1528 if item.check_name("align") {
1529 gate_feature_post!(&self, repr_align, attr.span,
1530 "the struct `#[repr(align(u16))]` attribute \
1537 ast::ItemKind::TraitAlias(..) => {
1538 gate_feature_post!(&self, trait_alias,
1540 "trait aliases are not yet fully implemented");
1543 ast::ItemKind::AutoImpl(..) => {
1544 gate_feature_post!(&self, optin_builtin_traits,
1546 "auto trait implementations are experimental \
1547 and possibly buggy");
1550 ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
1551 if polarity == ast::ImplPolarity::Negative {
1552 gate_feature_post!(&self, optin_builtin_traits,
1554 "negative trait bounds are not yet fully implemented; \
1555 use marker types for now");
1558 if let ast::Defaultness::Default = defaultness {
1559 gate_feature_post!(&self, specialization,
1561 "specialization is unstable");
1564 for impl_item in impl_items {
1565 if let ast::ImplItemKind::Method(..) = impl_item.node {
1566 if let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") {
1567 gate_feature_post!(&self, fn_must_use, attr.span,
1568 "`#[must_use]` on methods is experimental",
1569 GateStrength::Soft);
1575 ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
1576 gate_feature_post!(&self, optin_builtin_traits,
1578 "auto traits are experimental and possibly buggy");
1581 ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1582 let msg = "`macro` is experimental";
1583 gate_feature_post!(&self, decl_macro, i.span, msg);
1589 visit::walk_item(self, i);
1592 fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1594 ast::ForeignItemKind::Fn(..) |
1595 ast::ForeignItemKind::Static(..) => {
1596 let link_name = attr::first_attr_value_str_by_name(&i.attrs, "link_name");
1597 let links_to_llvm = match link_name {
1598 Some(val) => val.as_str().starts_with("llvm."),
1602 gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1603 "linking to LLVM intrinsics is experimental");
1606 ast::ForeignItemKind::Ty => {
1607 gate_feature_post!(&self, extern_types, i.span,
1608 "extern types are experimental");
1612 visit::walk_foreign_item(self, i)
1615 fn visit_ty(&mut self, ty: &'a ast::Ty) {
1617 ast::TyKind::BareFn(ref bare_fn_ty) => {
1618 self.check_abi(bare_fn_ty.abi, ty.span);
1620 ast::TyKind::Never => {
1621 gate_feature_post!(&self, never_type, ty.span,
1622 "The `!` type is experimental");
1624 ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => {
1625 gate_feature_post!(&self, dyn_trait, ty.span,
1626 "`dyn Trait` syntax is unstable");
1630 visit::walk_ty(self, ty)
1633 fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1634 if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1635 if output_ty.node != ast::TyKind::Never {
1636 self.visit_ty(output_ty)
1641 fn visit_expr(&mut self, e: &'a ast::Expr) {
1643 ast::ExprKind::Box(_) => {
1644 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1646 ast::ExprKind::Type(..) => {
1647 gate_feature_post!(&self, type_ascription, e.span,
1648 "type ascription is experimental");
1650 ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1651 gate_feature_post!(&self, inclusive_range_syntax,
1653 "inclusive range syntax is experimental");
1655 ast::ExprKind::InPlace(..) => {
1656 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1658 ast::ExprKind::Yield(..) => {
1659 gate_feature_post!(&self, generators,
1661 "yield syntax is experimental");
1663 ast::ExprKind::Lit(ref lit) => {
1664 if let ast::LitKind::Int(_, ref ty) = lit.node {
1666 ast::LitIntType::Signed(ast::IntTy::I128) |
1667 ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1668 gate_feature_post!(&self, i128_type, e.span,
1669 "128-bit integers are not stable");
1675 ast::ExprKind::Catch(_) => {
1676 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1680 visit::walk_expr(self, e);
1683 fn visit_arm(&mut self, arm: &'a ast::Arm) {
1684 if let Some(span) = arm.beginning_vert {
1685 gate_feature_post!(&self, match_beginning_vert,
1687 "Use of a '|' at the beginning of a match arm is experimental")
1689 visit::walk_arm(self, arm)
1692 fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1693 match pattern.node {
1694 PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1695 gate_feature_post!(&self, advanced_slice_patterns,
1697 "multiple-element slice matches anywhere \
1698 but at the end of a slice (e.g. \
1699 `[0, ..xs, 0]`) are experimental")
1701 PatKind::Slice(..) => {
1702 gate_feature_post!(&self, slice_patterns,
1704 "slice pattern syntax is experimental");
1706 PatKind::Box(..) => {
1707 gate_feature_post!(&self, box_patterns,
1709 "box pattern syntax is experimental");
1711 PatKind::Range(_, _, RangeEnd::Excluded) => {
1712 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1713 "exclusive range pattern syntax is experimental");
1715 PatKind::Range(_, _, RangeEnd::Included(RangeSyntax::DotDotEq)) => {
1716 gate_feature_post!(&self, dotdoteq_in_patterns, pattern.span,
1717 "`..=` syntax in patterns is experimental");
1721 visit::walk_pat(self, pattern)
1724 fn visit_fn(&mut self,
1725 fn_kind: FnKind<'a>,
1726 fn_decl: &'a ast::FnDecl,
1729 // check for const fn declarations
1730 if let FnKind::ItemFn(_, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1732 gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1734 // stability of const fn methods are covered in
1735 // visit_trait_item and visit_impl_item below; this is
1736 // because default methods don't pass through this
1740 FnKind::ItemFn(_, _, _, abi, _, _) |
1741 FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1742 self.check_abi(abi, span);
1746 visit::walk_fn(self, fn_kind, fn_decl, span);
1749 fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1751 ast::TraitItemKind::Method(ref sig, ref block) => {
1752 if block.is_none() {
1753 self.check_abi(sig.abi, ti.span);
1755 if sig.constness.node == ast::Constness::Const {
1756 gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1759 ast::TraitItemKind::Type(_, ref default) => {
1760 // We use two if statements instead of something like match guards so that both
1761 // of these errors can be emitted if both cases apply.
1762 if default.is_some() {
1763 gate_feature_post!(&self, associated_type_defaults, ti.span,
1764 "associated type defaults are unstable");
1766 if ti.generics.is_parameterized() {
1767 gate_feature_post!(&self, generic_associated_types, ti.span,
1768 "generic associated types are unstable");
1773 visit::walk_trait_item(self, ti);
1776 fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1777 if ii.defaultness == ast::Defaultness::Default {
1778 gate_feature_post!(&self, specialization,
1780 "specialization is unstable");
1784 ast::ImplItemKind::Method(ref sig, _) => {
1785 if sig.constness.node == ast::Constness::Const {
1786 gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1789 ast::ImplItemKind::Type(_) if ii.generics.is_parameterized() => {
1790 gate_feature_post!(&self, generic_associated_types, ii.span,
1791 "generic associated types are unstable");
1795 visit::walk_impl_item(self, ii);
1798 fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) {
1799 for segment in &path.segments {
1800 if segment.identifier.name == keywords::Crate.name() {
1801 gate_feature_post!(&self, crate_in_paths, segment.span,
1802 "`crate` in paths is experimental");
1803 } else if segment.identifier.name == keywords::Extern.name() {
1804 gate_feature_post!(&self, extern_in_paths, segment.span,
1805 "`extern` in paths is experimental");
1809 visit::walk_path(self, path);
1812 fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, nested: bool) {
1814 match use_tree.kind {
1815 ast::UseTreeKind::Simple(_) => {
1816 if use_tree.prefix.segments.len() != 1 {
1817 gate_feature_post!(&self, use_nested_groups, use_tree.span,
1818 "paths in `use` groups are experimental");
1821 ast::UseTreeKind::Glob => {
1822 gate_feature_post!(&self, use_nested_groups, use_tree.span,
1823 "glob imports in `use` groups are experimental");
1825 ast::UseTreeKind::Nested(_) => {
1826 gate_feature_post!(&self, use_nested_groups, use_tree.span,
1827 "nested groups in `use` are experimental");
1832 visit::walk_use_tree(self, use_tree, id);
1835 fn visit_vis(&mut self, vis: &'a ast::Visibility) {
1836 if let ast::Visibility::Crate(span, ast::CrateSugar::JustCrate) = *vis {
1837 gate_feature_post!(&self, crate_visibility_modifier, span,
1838 "`crate` visibility modifier is experimental");
1840 visit::walk_vis(self, vis);
1843 fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
1844 let (attrs, explain) = match *param {
1845 ast::GenericParam::Lifetime(ref ld) =>
1846 (&ld.attrs, "attributes on lifetime bindings are experimental"),
1847 ast::GenericParam::Type(ref t) =>
1848 (&t.attrs, "attributes on type parameter bindings are experimental"),
1851 if !attrs.is_empty() {
1852 gate_feature_post!(&self, generic_param_attrs, attrs[0].span, explain);
1855 visit::walk_generic_param(self, param)
1858 fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
1859 if lt.ident.name == "'_" {
1860 gate_feature_post!(&self, underscore_lifetimes, lt.span,
1861 "underscore lifetimes are unstable");
1863 visit::walk_lifetime(self, lt)
1867 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1868 let mut features = Features::new();
1870 let mut feature_checker = FeatureChecker::default();
1872 for attr in krate_attrs {
1873 if !attr.check_name("feature") {
1877 match attr.meta_item_list() {
1879 span_err!(span_handler, attr.span, E0555,
1880 "malformed feature attribute, expected #![feature(...)]");
1884 let name = if let Some(word) = mi.word() {
1887 span_err!(span_handler, mi.span, E0556,
1888 "malformed feature, expected just one word");
1892 if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1893 .find(|& &(n, _, _, _)| name == n) {
1894 set(&mut features, mi.span);
1895 feature_checker.collect(&features, mi.span);
1897 else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1898 .find(|& &(n, _, _)| name == n)
1899 .or_else(|| STABLE_REMOVED_FEATURES.iter()
1900 .find(|& &(n, _, _)| name == n)) {
1901 span_err!(span_handler, mi.span, E0557, "feature has been removed");
1903 else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1904 .find(|& &(n, _, _)| name == n) {
1905 features.declared_stable_lang_features.push((name, mi.span));
1907 features.declared_lib_features.push((name, mi.span));
1914 feature_checker.check(span_handler);
1919 /// A collector for mutually exclusive and interdependent features and their flag spans.
1921 struct FeatureChecker {
1922 proc_macro: Option<Span>,
1923 custom_attribute: Option<Span>,
1924 copy_closures: Option<Span>,
1925 clone_closures: Option<Span>,
1928 impl FeatureChecker {
1929 // If this method turns out to be a hotspot due to branching,
1930 // the branching can be eliminated by modifying `set!()` to set these spans
1931 // only for the features that need to be checked for mutual exclusion.
1932 fn collect(&mut self, features: &Features, span: Span) {
1933 if features.proc_macro {
1934 // If self.proc_macro is None, set to Some(span)
1935 self.proc_macro = self.proc_macro.or(Some(span));
1938 if features.custom_attribute {
1939 self.custom_attribute = self.custom_attribute.or(Some(span));
1942 if features.copy_closures {
1943 self.copy_closures = self.copy_closures.or(Some(span));
1946 if features.clone_closures {
1947 self.clone_closures = self.clone_closures.or(Some(span));
1951 fn check(self, handler: &Handler) {
1952 if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1953 handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1954 `#![feature(custom_attribute)] at the same time")
1955 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1961 if let (Some(span), None) = (self.copy_closures, self.clone_closures) {
1962 handler.struct_span_err(span, "`#![feature(copy_closures)]` can only be used with \
1963 `#![feature(clone_closures)]`")
1964 .span_note(span, "`#![feature(copy_closures)]` declared here")
1972 pub fn check_crate(krate: &ast::Crate,
1974 features: &Features,
1975 plugin_attributes: &[(String, AttributeType)],
1976 unstable: UnstableFeatures) {
1977 maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1983 let visitor = &mut PostExpansionVisitor { context: &ctx };
1984 visitor.whole_crate_feature_gates(krate);
1985 visit::walk_crate(visitor, krate);
1988 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1989 pub enum UnstableFeatures {
1990 /// Hard errors for unstable features are active, as on
1991 /// beta/stable channels.
1993 /// Allow features to be activated, as on nightly.
1995 /// Errors are bypassed for bootstrapping. This is required any time
1996 /// during the build that feature-related lints are set to warn or above
1997 /// because the build turns on warnings-as-errors and uses lots of unstable
1998 /// features. As a result, this is always required for building Rust itself.
2002 impl UnstableFeatures {
2003 pub fn from_environment() -> UnstableFeatures {
2004 // Whether this is a feature-staged build, i.e. on the beta or stable channel
2005 let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
2006 // Whether we should enable unstable features for bootstrapping
2007 let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
2008 match (disable_unstable_features, bootstrap) {
2009 (_, true) => UnstableFeatures::Cheat,
2010 (true, _) => UnstableFeatures::Disallow,
2011 (false, _) => UnstableFeatures::Allow
2015 pub fn is_nightly_build(&self) -> bool {
2017 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
2023 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
2024 unstable: UnstableFeatures) {
2025 let allow_features = match unstable {
2026 UnstableFeatures::Allow => true,
2027 UnstableFeatures::Disallow => false,
2028 UnstableFeatures::Cheat => true
2030 if !allow_features {
2031 for attr in &krate.attrs {
2032 if attr.check_name("feature") {
2033 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
2034 span_err!(span_handler, attr.span, E0554,
2035 "#![feature] may not be used on the {} release channel",