1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 //! This module implements the gating necessary for preventing certain compiler
14 //! features from being used by default. This module will crawl a pre-expanded
15 //! AST to ensure that there are no features which are used that are not
18 //! Features are enabled in programs via the crate-level attributes of
19 //! `#![feature(...)]` with a comma-separated list of features.
21 //! For the purpose of future feature-tracking, once code for detection of feature
22 //! gate usage is added, *do not remove it again* even once the feature
25 use self::AttributeType
::*;
26 use self::AttributeGate
::*;
29 use ast
::{self, NodeId, PatKind, RangeEnd}
;
33 use errors
::{DiagnosticBuilder, Handler, FatalError}
;
34 use visit
::{self, FnKind, Visitor}
;
38 use std
::ascii
::AsciiExt
;
43 fn f(features
: &mut Features
) -> &mut bool
{
46 f
as fn(&mut Features
) -> &mut bool
50 macro_rules
! declare_features
{
51 ($
((active
, $feature
: ident
, $ver
: expr
, $issue
: expr
),)+) => {
52 /// Represents active features that are currently being implemented or
53 /// currently being considered for addition/removal.
54 const ACTIVE_FEATURES
: &'
static [(&'
static str, &'
static str,
55 Option
<u32>, fn(&mut Features
) -> &mut bool
)] = &[
56 $
((stringify
!($feature
), $ver
, $issue
, setter
!($feature
))),+
59 /// A set of features to be used by later passes.
61 /// #![feature] attrs for stable language features, for error reporting
62 pub declared_stable_lang_features
: Vec
<(Symbol
, Span
)>,
63 /// #![feature] attrs for non-language (library) features
64 pub declared_lib_features
: Vec
<(Symbol
, Span
)>,
65 $
(pub $feature
: bool
),+
69 pub fn new() -> Features
{
71 declared_stable_lang_features
: Vec
::new(),
72 declared_lib_features
: Vec
::new(),
79 ($
((removed
, $feature
: ident
, $ver
: expr
, $issue
: expr
),)+) => {
80 /// Represents unstable features which have since been removed (it was once Active)
81 const REMOVED_FEATURES
: &'
static [(&'
static str, &'
static str, Option
<u32>)] = &[
82 $
((stringify
!($feature
), $ver
, $issue
)),+
86 ($
((stable_removed
, $feature
: ident
, $ver
: expr
, $issue
: expr
),)+) => {
87 /// Represents stable features which have since been removed (it was once Accepted)
88 const STABLE_REMOVED_FEATURES
: &'
static [(&'
static str, &'
static str, Option
<u32>)] = &[
89 $
((stringify
!($feature
), $ver
, $issue
)),+
93 ($
((accepted
, $feature
: ident
, $ver
: expr
, $issue
: expr
),)+) => {
94 /// Those language feature has since been Accepted (it was once Active)
95 const ACCEPTED_FEATURES
: &'
static [(&'
static str, &'
static str, Option
<u32>)] = &[
96 $
((stringify
!($feature
), $ver
, $issue
)),+
101 // If you change this, please modify src/doc/unstable-book as well.
103 // Don't ever remove anything from this list; set them to 'Removed'.
105 // The version numbers here correspond to the version in which the current status
106 // was set. This is most important for knowing when a particular feature became
109 // NB: The featureck.py script parses this information directly out of the source
110 // so take care when modifying it.
113 (active
, asm
, "1.0.0", Some(29722)),
114 (active
, concat_idents
, "1.0.0", Some(29599)),
115 (active
, link_args
, "1.0.0", Some(29596)),
116 (active
, log_syntax
, "1.0.0", Some(29598)),
117 (active
, non_ascii_idents
, "1.0.0", Some(28979)),
118 (active
, plugin_registrar
, "1.0.0", Some(29597)),
119 (active
, thread_local
, "1.0.0", Some(29594)),
120 (active
, trace_macros
, "1.0.0", Some(29598)),
122 // rustc internal, for now:
123 (active
, intrinsics
, "1.0.0", None
),
124 (active
, lang_items
, "1.0.0", None
),
126 (active
, link_llvm_intrinsics
, "1.0.0", Some(29602)),
127 (active
, linkage
, "1.0.0", Some(29603)),
128 (active
, quote
, "1.0.0", Some(29601)),
129 (active
, simd
, "1.0.0", Some(27731)),
133 (active
, rustc_diagnostic_macros
, "1.0.0", None
),
134 (active
, advanced_slice_patterns
, "1.0.0", Some(23121)),
135 (active
, box_syntax
, "1.0.0", Some(27779)),
136 (active
, placement_in_syntax
, "1.0.0", Some(27779)),
137 (active
, unboxed_closures
, "1.0.0", Some(29625)),
139 (active
, allocator
, "1.0.0", Some(27389)),
140 (active
, fundamental
, "1.0.0", Some(29635)),
141 (active
, main
, "1.0.0", Some(29634)),
142 (active
, needs_allocator
, "1.4.0", Some(27389)),
143 (active
, on_unimplemented
, "1.0.0", Some(29628)),
144 (active
, plugin
, "1.0.0", Some(29597)),
145 (active
, simd_ffi
, "1.0.0", Some(27731)),
146 (active
, start
, "1.0.0", Some(29633)),
147 (active
, structural_match
, "1.8.0", Some(31434)),
148 (active
, panic_runtime
, "1.10.0", Some(32837)),
149 (active
, needs_panic_runtime
, "1.10.0", Some(32837)),
151 // OIBIT specific features
152 (active
, optin_builtin_traits
, "1.0.0", Some(13231)),
154 // macro reexport needs more discussion and stabilization
155 (active
, macro_reexport
, "1.0.0", Some(29638)),
157 // Allows use of #[staged_api]
159 (active
, staged_api
, "1.0.0", None
),
161 // Allows using #![no_core]
162 (active
, no_core
, "1.3.0", Some(29639)),
164 // Allows using `box` in patterns; RFC 469
165 (active
, box_patterns
, "1.0.0", Some(29641)),
167 // Allows using the unsafe_destructor_blind_to_params attribute;
169 (active
, dropck_parametricity
, "1.3.0", Some(28498)),
171 // Allows using the may_dangle attribute; RFC 1327
172 (active
, dropck_eyepatch
, "1.10.0", Some(34761)),
174 // Allows the use of custom attributes; RFC 572
175 (active
, custom_attribute
, "1.0.0", Some(29642)),
177 // Allows the use of #[derive(Anything)] as sugar for
178 // #[derive_Anything].
179 (active
, custom_derive
, "1.0.0", Some(29644)),
181 // Allows the use of rustc_* attributes; RFC 572
182 (active
, rustc_attrs
, "1.0.0", Some(29642)),
184 // Allows the use of #[allow_internal_unstable]. This is an
185 // attribute on macro_rules! and can't use the attribute handling
186 // below (it has to be checked before expansion possibly makes
187 // macros disappear).
190 (active
, allow_internal_unstable
, "1.0.0", None
),
192 // #23121. Array patterns have some hazards yet.
193 (active
, slice_patterns
, "1.0.0", Some(23121)),
195 // Allows the definition of associated constants in `trait` or `impl`
197 (active
, associated_consts
, "1.0.0", Some(29646)),
199 // Allows the definition of `const fn` functions.
200 (active
, const_fn
, "1.2.0", Some(24111)),
202 // Allows indexing into constant arrays.
203 (active
, const_indexing
, "1.4.0", Some(29947)),
205 // Allows using #[prelude_import] on glob `use` items.
208 (active
, prelude_import
, "1.2.0", None
),
210 // Allows default type parameters to influence type inference.
211 (active
, default_type_parameter_fallback
, "1.3.0", Some(27336)),
213 // Allows associated type defaults
214 (active
, associated_type_defaults
, "1.2.0", Some(29661)),
216 // allow `repr(simd)`, and importing the various simd intrinsics
217 (active
, repr_simd
, "1.4.0", Some(27731)),
219 // Allows cfg(target_feature = "...").
220 (active
, cfg_target_feature
, "1.4.0", Some(29717)),
222 // allow `extern "platform-intrinsic" { ... }`
223 (active
, platform_intrinsics
, "1.4.0", Some(27731)),
226 // rust runtime internal
227 (active
, unwind_attributes
, "1.4.0", None
),
229 // allow the use of `#[naked]` on functions.
230 (active
, naked_functions
, "1.9.0", Some(32408)),
232 // allow `#[no_debug]`
233 (active
, no_debug
, "1.5.0", Some(29721)),
235 // allow `#[omit_gdb_pretty_printer_section]`
237 (active
, omit_gdb_pretty_printer_section
, "1.5.0", None
),
239 // Allows cfg(target_vendor = "...").
240 (active
, cfg_target_vendor
, "1.5.0", Some(29718)),
242 // Allow attributes on expressions and non-item statements
243 (active
, stmt_expr_attributes
, "1.6.0", Some(15701)),
245 // allow using type ascription in expressions
246 (active
, type_ascription
, "1.6.0", Some(23416)),
248 // Allows cfg(target_thread_local)
249 (active
, cfg_target_thread_local
, "1.7.0", Some(29594)),
252 (active
, abi_vectorcall
, "1.7.0", None
),
255 (active
, inclusive_range_syntax
, "1.7.0", Some(28237)),
258 (active
, exclusive_range_pattern
, "1.11.0", Some(37854)),
260 // impl specialization (RFC 1210)
261 (active
, specialization
, "1.7.0", Some(31844)),
263 // Allow Drop types in statics/const functions (RFC 1440)
264 (active
, drop_types_in_const
, "1.9.0", Some(33156)),
266 // Allows cfg(target_has_atomic = "...").
267 (active
, cfg_target_has_atomic
, "1.9.0", Some(32976)),
269 // Allows `impl Trait` in function return types.
270 (active
, conservative_impl_trait
, "1.12.0", Some(34511)),
272 // Permits numeric fields in struct expressions and patterns.
273 (active
, relaxed_adts
, "1.12.0", Some(35626)),
276 (active
, never_type
, "1.13.0", Some(35121)),
278 // Allows all literals in attribute lists and values of key-value pairs.
279 (active
, attr_literals
, "1.13.0", Some(34981)),
281 // Allows the sysV64 ABI to be specified on all platforms
282 // instead of just the platforms on which it is the C ABI
283 (active
, abi_sysv64
, "1.13.0", Some(36167)),
285 // Allows untagged unions `union U { ... }`
286 (active
, untagged_unions
, "1.13.0", Some(32836)),
288 // Used to identify the `compiler_builtins` crate
290 (active
, compiler_builtins
, "1.13.0", None
),
292 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
293 (active
, generic_param_attrs
, "1.11.0", Some(34761)),
295 // Allows #[link(..., cfg(..))]
296 (active
, link_cfg
, "1.14.0", Some(37406)),
298 (active
, use_extern_macros
, "1.15.0", Some(35896)),
300 // Allows `break {expr}` with a value inside `loop`s.
301 (active
, loop_break_value
, "1.14.0", Some(37339)),
303 // Allows #[target_feature(...)]
304 (active
, target_feature
, "1.15.0", None
),
306 // `extern "ptx-*" fn()`
307 (active
, abi_ptx
, "1.15.0", None
),
310 (active
, i128_type
, "1.16.0", Some(35118)),
312 // The `unadjusted` ABI. Perma unstable.
313 (active
, abi_unadjusted
, "1.16.0", None
),
316 (active
, proc_macro
, "1.16.0", Some(38356)),
318 // Allows attributes on struct literal fields.
319 (active
, struct_field_attributes
, "1.16.0", Some(38814)),
321 // Allows #[link(kind="static-nobundle"...]
322 (active
, static_nobundle
, "1.16.0", Some(37403)),
324 // `extern "msp430-interrupt" fn()`
325 (active
, abi_msp430_interrupt
, "1.16.0", Some(38487)),
327 // Coerces non capturing closures to function pointers
328 (active
, closure_to_fn_coercion
, "1.17.0", Some(39817)),
330 // Used to identify crates that contain sanitizer runtimes
332 (active
, sanitizer_runtime
, "1.17.0", None
),
334 // `extern "x86-interrupt" fn()`
335 (active
, abi_x86_interrupt
, "1.17.0", Some(40180)),
338 // Allows the `catch {...}` expression
339 (active
, catch_expr
, "1.17.0", Some(31436)),
341 // Allows `repr(align(u16))` struct attribute (RFC 1358)
342 (active
, repr_align
, "1.17.0", Some(33626)),
344 // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
345 (active
, rvalue_static_promotion
, "1.15.1", Some(38865)),
347 // Used to preserve symbols (see llvm.used)
348 (active
, used
, "1.18.0", Some(40289)),
350 // Allows module-level inline assembly by way of global_asm!()
351 (active
, global_asm
, "1.18.0", Some(35119)),
353 // Allows overlapping impls of marker traits
354 (active
, overlapping_marker_traits
, "1.18.0", Some(29864)),
356 // Allows use of the :vis macro fragment specifier
357 (active
, macro_vis_matcher
, "1.18.0", Some(41022)),
361 (removed
, import_shadowing
, "1.0.0", None
),
362 (removed
, managed_boxes
, "1.0.0", None
),
363 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
364 (removed
, negate_unsigned
, "1.0.0", Some(29645)),
365 (removed
, reflect
, "1.0.0", Some(27749)),
366 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
367 (removed
, opt_out_copy
, "1.0.0", None
),
368 (removed
, quad_precision_float
, "1.0.0", None
),
369 (removed
, struct_inherit
, "1.0.0", None
),
370 (removed
, test_removed_feature
, "1.0.0", None
),
371 (removed
, visible_private_types
, "1.0.0", None
),
372 (removed
, unsafe_no_drop_flag
, "1.0.0", None
),
373 // Allows using items which are missing stability attributes
375 (removed
, unmarked_api
, "1.0.0", None
),
376 (removed
, pushpop_unsafe
, "1.2.0", None
),
380 (stable_removed
, no_stack_check
, "1.0.0", None
),
384 (accepted
, associated_types
, "1.0.0", None
),
385 // allow overloading augmented assignment operations like `a += b`
386 (accepted
, augmented_assignments
, "1.8.0", Some(28235)),
387 // allow empty structs and enum variants with braces
388 (accepted
, braced_empty_structs
, "1.8.0", Some(29720)),
389 (accepted
, default_type_params
, "1.0.0", None
),
390 (accepted
, globs
, "1.0.0", None
),
391 (accepted
, if_let
, "1.0.0", None
),
392 // A temporary feature gate used to enable parser extensions needed
393 // to bootstrap fix for #5723.
394 (accepted
, issue_5723_bootstrap
, "1.0.0", None
),
395 (accepted
, macro_rules
, "1.0.0", None
),
396 // Allows using #![no_std]
397 (accepted
, no_std
, "1.6.0", None
),
398 (accepted
, slicing_syntax
, "1.0.0", None
),
399 (accepted
, struct_variant
, "1.0.0", None
),
400 // These are used to test this portion of the compiler, they don't actually
402 (accepted
, test_accepted_feature
, "1.0.0", None
),
403 (accepted
, tuple_indexing
, "1.0.0", None
),
404 // Allows macros to appear in the type position.
405 (accepted
, type_macros
, "1.13.0", Some(27245)),
406 (accepted
, while_let
, "1.0.0", None
),
407 // Allows `#[deprecated]` attribute
408 (accepted
, deprecated
, "1.9.0", Some(29935)),
410 (accepted
, question_mark
, "1.13.0", Some(31436)),
411 // Allows `..` in tuple (struct) patterns
412 (accepted
, dotdot_in_tuple_patterns
, "1.14.0", Some(33627)),
413 (accepted
, item_like_imports
, "1.14.0", Some(35120)),
414 // Allows using `Self` and associated types in struct expressions and patterns.
415 (accepted
, more_struct_aliases
, "1.16.0", Some(37544)),
416 // elide `'static` lifetimes in `static`s and `const`s
417 (accepted
, static_in_const
, "1.17.0", Some(35897)),
418 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
419 (accepted
, field_init_shorthand
, "1.17.0", Some(37340)),
420 // Allows the definition recursive static items.
421 (accepted
, static_recursion
, "1.17.0", Some(29719)),
422 // pub(restricted) visibilities (RFC 1422)
423 (accepted
, pub_restricted
, "1.18.0", Some(32409)),
424 // The #![windows_subsystem] attribute
425 (accepted
, windows_subsystem
, "1.18.0", Some(37499)),
427 // If you change this, please modify src/doc/unstable-book as well. You must
428 // move that documentation into the relevant place in the other docs, and
429 // remove the chapter on the flag.
431 #[derive(PartialEq, Copy, Clone, Debug)]
432 pub enum AttributeType
{
433 /// Normal, builtin attribute that is consumed
434 /// by the compiler before the unused_attribute check
437 /// Builtin attribute that may not be consumed by the compiler
438 /// before the unused_attribute check. These attributes
439 /// will be ignored by the unused_attribute lint
442 /// Builtin attribute that is only allowed at the crate level
446 pub enum AttributeGate
{
447 /// Is gated by a given feature gate, reason
448 /// and function to check if enabled
449 Gated(Stability
, &'
static str, &'
static str, fn(&Features
) -> bool
),
451 /// Ungated attribute, can be used on all release channels
456 fn is_deprecated(&self) -> bool
{
458 Gated(Stability
::Deprecated(_
), ..) => true,
464 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
467 // Argument is tracking issue link.
468 Deprecated(&'
static str),
472 impl ::std
::fmt
::Debug
for AttributeGate
{
473 fn fmt(&self, fmt
: &mut ::std
::fmt
::Formatter
) -> ::std
::fmt
::Result
{
475 Gated(ref stab
, ref name
, ref expl
, _
) =>
476 write
!(fmt
, "Gated({:?}, {}, {})", stab
, name
, expl
),
477 Ungated
=> write
!(fmt
, "Ungated")
482 macro_rules
! cfg_fn
{
483 ($field
: ident
) => {{
484 fn f(features
: &Features
) -> bool
{
487 f
as fn(&Features
) -> bool
491 pub fn deprecated_attributes() -> Vec
<&'
static (&'
static str, AttributeType
, AttributeGate
)> {
492 BUILTIN_ATTRIBUTES
.iter().filter(|a
| a
.2.is_deprecated
()).collect()
495 pub fn is_builtin_attr(attr
: &ast
::Attribute
) -> bool
{
496 BUILTIN_ATTRIBUTES
.iter().any(|&(builtin_name
, _
, _
)| attr
.check_name(builtin_name
))
499 // Attributes that have a special meaning to rustc or rustdoc
500 pub const BUILTIN_ATTRIBUTES
: &'
static [(&'
static str, AttributeType
, AttributeGate
)] = &[
503 ("warn", Normal
, Ungated
),
504 ("allow", Normal
, Ungated
),
505 ("forbid", Normal
, Ungated
),
506 ("deny", Normal
, Ungated
),
508 ("macro_reexport", Normal
, Ungated
),
509 ("macro_use", Normal
, Ungated
),
510 ("macro_export", Normal
, Ungated
),
511 ("plugin_registrar", Normal
, Ungated
),
513 ("cfg", Normal
, Ungated
),
514 ("cfg_attr", Normal
, Ungated
),
515 ("main", Normal
, Ungated
),
516 ("start", Normal
, Ungated
),
517 ("test", Normal
, Ungated
),
518 ("bench", Normal
, Ungated
),
519 ("simd", Normal
, Ungated
),
520 ("repr", Normal
, Ungated
),
521 ("path", Normal
, Ungated
),
522 ("abi", Normal
, Ungated
),
523 ("automatically_derived", Normal
, Ungated
),
524 ("no_mangle", Normal
, Ungated
),
525 ("no_link", Normal
, Ungated
),
526 ("derive", Normal
, Ungated
),
527 ("should_panic", Normal
, Ungated
),
528 ("ignore", Normal
, Ungated
),
529 ("no_implicit_prelude", Normal
, Ungated
),
530 ("reexport_test_harness_main", Normal
, Ungated
),
531 ("link_args", Normal
, Ungated
),
532 ("macro_escape", Normal
, Ungated
),
535 ("structural_match", Whitelisted
, Gated(Stability
::Unstable
,
537 "the semantics of constant patterns is \
539 cfg_fn
!(structural_match
))),
541 ("plugin", CrateLevel
, Gated(Stability
::Unstable
,
543 "compiler plugins are experimental \
547 ("no_std", CrateLevel
, Ungated
),
548 ("no_core", CrateLevel
, Gated(Stability
::Unstable
,
550 "no_core is experimental",
552 ("lang", Normal
, Gated(Stability
::Unstable
,
554 "language items are subject to change",
555 cfg_fn
!(lang_items
))),
556 ("linkage", Whitelisted
, Gated(Stability
::Unstable
,
558 "the `linkage` attribute is experimental \
559 and not portable across platforms",
561 ("thread_local", Whitelisted
, Gated(Stability
::Unstable
,
563 "`#[thread_local]` is an experimental feature, and does \
564 not currently handle destructors. There is no \
565 corresponding `#[task_local]` mapping to the task \
567 cfg_fn
!(thread_local
))),
569 ("rustc_on_unimplemented", Normal
, Gated(Stability
::Unstable
,
571 "the `#[rustc_on_unimplemented]` attribute \
572 is an experimental feature",
573 cfg_fn
!(on_unimplemented
))),
574 ("allocator", Whitelisted
, Gated(Stability
::Unstable
,
576 "the `#[allocator]` attribute is an experimental feature",
577 cfg_fn
!(allocator
))),
578 ("needs_allocator", Normal
, Gated(Stability
::Unstable
,
580 "the `#[needs_allocator]` \
581 attribute is an experimental \
583 cfg_fn
!(needs_allocator
))),
584 ("panic_runtime", Whitelisted
, Gated(Stability
::Unstable
,
586 "the `#[panic_runtime]` attribute is \
587 an experimental feature",
588 cfg_fn
!(panic_runtime
))),
589 ("needs_panic_runtime", Whitelisted
, Gated(Stability
::Unstable
,
590 "needs_panic_runtime",
591 "the `#[needs_panic_runtime]` \
592 attribute is an experimental \
594 cfg_fn
!(needs_panic_runtime
))),
595 ("rustc_variance", Normal
, Gated(Stability
::Unstable
,
597 "the `#[rustc_variance]` attribute \
598 is just used for rustc unit tests \
599 and will never be stable",
600 cfg_fn
!(rustc_attrs
))),
601 ("rustc_error", Whitelisted
, Gated(Stability
::Unstable
,
603 "the `#[rustc_error]` attribute \
604 is just used for rustc unit tests \
605 and will never be stable",
606 cfg_fn
!(rustc_attrs
))),
607 ("rustc_if_this_changed", Whitelisted
, Gated(Stability
::Unstable
,
609 "the `#[rustc_if_this_changed]` attribute \
610 is just used for rustc unit tests \
611 and will never be stable",
612 cfg_fn
!(rustc_attrs
))),
613 ("rustc_then_this_would_need", Whitelisted
, Gated(Stability
::Unstable
,
615 "the `#[rustc_if_this_changed]` attribute \
616 is just used for rustc unit tests \
617 and will never be stable",
618 cfg_fn
!(rustc_attrs
))),
619 ("rustc_dirty", Whitelisted
, Gated(Stability
::Unstable
,
621 "the `#[rustc_dirty]` attribute \
622 is just used for rustc unit tests \
623 and will never be stable",
624 cfg_fn
!(rustc_attrs
))),
625 ("rustc_clean", Whitelisted
, Gated(Stability
::Unstable
,
627 "the `#[rustc_clean]` attribute \
628 is just used for rustc unit tests \
629 and will never be stable",
630 cfg_fn
!(rustc_attrs
))),
631 ("rustc_metadata_dirty", Whitelisted
, Gated(Stability
::Unstable
,
633 "the `#[rustc_metadata_dirty]` attribute \
634 is just used for rustc unit tests \
635 and will never be stable",
636 cfg_fn
!(rustc_attrs
))),
637 ("rustc_metadata_clean", Whitelisted
, Gated(Stability
::Unstable
,
639 "the `#[rustc_metadata_clean]` attribute \
640 is just used for rustc unit tests \
641 and will never be stable",
642 cfg_fn
!(rustc_attrs
))),
643 ("rustc_partition_reused", Whitelisted
, Gated(Stability
::Unstable
,
646 is just used for rustc unit tests \
647 and will never be stable",
648 cfg_fn
!(rustc_attrs
))),
649 ("rustc_partition_translated", Whitelisted
, Gated(Stability
::Unstable
,
652 is just used for rustc unit tests \
653 and will never be stable",
654 cfg_fn
!(rustc_attrs
))),
655 ("rustc_symbol_name", Whitelisted
, Gated(Stability
::Unstable
,
657 "internal rustc attributes will never be stable",
658 cfg_fn
!(rustc_attrs
))),
659 ("rustc_item_path", Whitelisted
, Gated(Stability
::Unstable
,
661 "internal rustc attributes will never be stable",
662 cfg_fn
!(rustc_attrs
))),
663 ("rustc_move_fragments", Normal
, Gated(Stability
::Unstable
,
665 "the `#[rustc_move_fragments]` attribute \
666 is just used for rustc unit tests \
667 and will never be stable",
668 cfg_fn
!(rustc_attrs
))),
669 ("rustc_mir", Whitelisted
, Gated(Stability
::Unstable
,
671 "the `#[rustc_mir]` attribute \
672 is just used for rustc unit tests \
673 and will never be stable",
674 cfg_fn
!(rustc_attrs
))),
675 ("rustc_inherit_overflow_checks", Whitelisted
, Gated(Stability
::Unstable
,
677 "the `#[rustc_inherit_overflow_checks]` \
678 attribute is just used to control \
679 overflow checking behavior of several \
680 libcore functions that are inlined \
681 across crates and will never be stable",
682 cfg_fn
!(rustc_attrs
))),
683 ("compiler_builtins", Whitelisted
, Gated(Stability
::Unstable
,
685 "the `#[compiler_builtins]` attribute is used to \
686 identify the `compiler_builtins` crate which \
687 contains compiler-rt intrinsics and will never be \
689 cfg_fn
!(compiler_builtins
))),
690 ("sanitizer_runtime", Whitelisted
, Gated(Stability
::Unstable
,
692 "the `#[sanitizer_runtime]` attribute is used to \
693 identify crates that contain the runtime of a \
694 sanitizer and will never be stable",
695 cfg_fn
!(sanitizer_runtime
))),
697 ("allow_internal_unstable", Normal
, Gated(Stability
::Unstable
,
698 "allow_internal_unstable",
699 EXPLAIN_ALLOW_INTERNAL_UNSTABLE
,
700 cfg_fn
!(allow_internal_unstable
))),
702 ("fundamental", Whitelisted
, Gated(Stability
::Unstable
,
704 "the `#[fundamental]` attribute \
705 is an experimental feature",
706 cfg_fn
!(fundamental
))),
708 ("proc_macro_derive", Normal
, Ungated
),
710 ("rustc_copy_clone_marker", Whitelisted
, Gated(Stability
::Unstable
,
712 "internal implementation detail",
713 cfg_fn
!(rustc_attrs
))),
715 // FIXME: #14408 whitelist docs since rustdoc looks at them
716 ("doc", Whitelisted
, Ungated
),
718 // FIXME: #14406 these are processed in trans, which happens after the
720 ("cold", Whitelisted
, Ungated
),
721 ("naked", Whitelisted
, Gated(Stability
::Unstable
,
723 "the `#[naked]` attribute \
724 is an experimental feature",
725 cfg_fn
!(naked_functions
))),
726 ("target_feature", Whitelisted
, Gated(
727 Stability
::Unstable
, "target_feature",
728 "the `#[target_feature]` attribute is an experimental feature",
729 cfg_fn
!(target_feature
))),
730 ("export_name", Whitelisted
, Ungated
),
731 ("inline", Whitelisted
, Ungated
),
732 ("link", Whitelisted
, Ungated
),
733 ("link_name", Whitelisted
, Ungated
),
734 ("link_section", Whitelisted
, Ungated
),
735 ("no_builtins", Whitelisted
, Ungated
),
736 ("no_mangle", Whitelisted
, Ungated
),
737 ("no_debug", Whitelisted
, Gated(
738 Stability
::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
740 "the `#[no_debug]` attribute is an experimental feature",
742 ("omit_gdb_pretty_printer_section", Whitelisted
, Gated(Stability
::Unstable
,
743 "omit_gdb_pretty_printer_section",
744 "the `#[omit_gdb_pretty_printer_section]` \
745 attribute is just used for the Rust test \
747 cfg_fn
!(omit_gdb_pretty_printer_section
))),
748 ("unsafe_destructor_blind_to_params",
750 Gated(Stability
::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
751 "dropck_parametricity",
752 "unsafe_destructor_blind_to_params has been replaced by \
753 may_dangle and will be removed in the future",
754 cfg_fn
!(dropck_parametricity
))),
757 Gated(Stability
::Unstable
,
759 "may_dangle has unstable semantics and may be removed in the future",
760 cfg_fn
!(dropck_eyepatch
))),
761 ("unwind", Whitelisted
, Gated(Stability
::Unstable
,
763 "#[unwind] is experimental",
764 cfg_fn
!(unwind_attributes
))),
765 ("used", Whitelisted
, Gated(
766 Stability
::Unstable
, "used",
767 "the `#[used]` attribute is an experimental feature",
771 ("prelude_import", Whitelisted
, Gated(Stability
::Unstable
,
773 "`#[prelude_import]` is for use by rustc only",
774 cfg_fn
!(prelude_import
))),
776 // FIXME: #14407 these are only looked at on-demand so we can't
777 // guarantee they'll have already been checked
778 ("rustc_deprecated", Whitelisted
, Ungated
),
779 ("must_use", Whitelisted
, Ungated
),
780 ("stable", Whitelisted
, Ungated
),
781 ("unstable", Whitelisted
, Ungated
),
782 ("deprecated", Normal
, Ungated
),
784 ("rustc_paren_sugar", Normal
, Gated(Stability
::Unstable
,
786 "unboxed_closures are still evolving",
787 cfg_fn
!(unboxed_closures
))),
789 ("windows_subsystem", Whitelisted
, Ungated
),
791 ("proc_macro_attribute", Normal
, Gated(Stability
::Unstable
,
793 "attribute proc macros are currently unstable",
794 cfg_fn
!(proc_macro
))),
796 ("proc_macro", Normal
, Gated(Stability
::Unstable
,
798 "function-like proc macros are currently unstable",
799 cfg_fn
!(proc_macro
))),
801 ("rustc_derive_registrar", Normal
, Gated(Stability
::Unstable
,
802 "rustc_derive_registrar",
803 "used internally by rustc",
804 cfg_fn
!(rustc_attrs
))),
806 // Crate level attributes
807 ("crate_name", CrateLevel
, Ungated
),
808 ("crate_type", CrateLevel
, Ungated
),
809 ("crate_id", CrateLevel
, Ungated
),
810 ("feature", CrateLevel
, Ungated
),
811 ("no_start", CrateLevel
, Ungated
),
812 ("no_main", CrateLevel
, Ungated
),
813 ("no_builtins", CrateLevel
, Ungated
),
814 ("recursion_limit", CrateLevel
, Ungated
),
815 ("type_length_limit", CrateLevel
, Ungated
),
818 // cfg(...)'s that are feature gated
819 const GATED_CFGS
: &'
static [(&'
static str, &'
static str, fn(&Features
) -> bool
)] = &[
820 // (name in cfg, feature, function to check if the feature is enabled)
821 ("target_feature", "cfg_target_feature", cfg_fn
!(cfg_target_feature
)),
822 ("target_vendor", "cfg_target_vendor", cfg_fn
!(cfg_target_vendor
)),
823 ("target_thread_local", "cfg_target_thread_local", cfg_fn
!(cfg_target_thread_local
)),
824 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn
!(cfg_target_has_atomic
)),
827 #[derive(Debug, Eq, PartialEq)]
828 pub struct GatedCfg
{
834 pub fn gate(cfg
: &ast
::MetaItem
) -> Option
<GatedCfg
> {
835 let name
= cfg
.name().as_str();
837 .position(|info
| info
.0 == name
)
846 pub fn check_and_emit(&self, sess
: &ParseSess
, features
: &Features
) {
847 let (cfg
, feature
, has_feature
) = GATED_CFGS
[self.index
];
848 if !has_feature(features
) && !self.span
.allows_unstable() {
849 let explain
= format
!("`cfg({})` is experimental and subject to change", cfg
);
850 emit_feature_err(sess
, feature
, self.span
, GateIssue
::Language
, &explain
);
856 features
: &'a Features
,
857 parse_sess
: &'a ParseSess
,
858 plugin_attributes
: &'a
[(String
, AttributeType
)],
861 macro_rules
! gate_feature_fn
{
862 ($cx
: expr
, $has_feature
: expr
, $span
: expr
, $name
: expr
, $explain
: expr
) => {{
863 let (cx
, has_feature
, span
, name
, explain
) = ($cx
, $has_feature
, $span
, $name
, $explain
);
864 let has_feature
: bool
= has_feature(&$cx
.features
);
865 debug
!("gate_feature(feature = {:?}, span = {:?}); has? {}", name
, span
, has_feature
);
866 if !has_feature
&& !span
.allows_unstable() {
867 emit_feature_err(cx
.parse_sess
, name
, span
, GateIssue
::Language
, explain
);
872 macro_rules
! gate_feature
{
873 ($cx
: expr
, $feature
: ident
, $span
: expr
, $explain
: expr
) => {
874 gate_feature_fn
!($cx
, |x
:&Features
| x
.$feature
, $span
, stringify
!($feature
), $explain
)
878 impl<'a
> Context
<'a
> {
879 fn check_attribute(&self, attr
: &ast
::Attribute
, is_macro
: bool
) {
880 debug
!("check_attribute(attr = {:?})", attr
);
881 let name
= unwrap_or
!(attr
.name(), return).as_str();
882 for &(n
, ty
, ref gateage
) in BUILTIN_ATTRIBUTES
{
884 if let &Gated(_
, ref name
, ref desc
, ref has_feature
) = gateage
{
885 gate_feature_fn
!(self, has_feature
, attr
.span
, name
, desc
);
887 debug
!("check_attribute: {:?} is builtin, {:?}, {:?}", attr
.path
, ty
, gateage
);
891 for &(ref n
, ref ty
) in self.plugin_attributes
{
892 if attr
.path
== &**n
{
893 // Plugins can't gate attributes, so we don't check for it
894 // unlike the code above; we only use this loop to
895 // short-circuit to avoid the checks below
896 debug
!("check_attribute: {:?} is registered by a plugin, {:?}", attr
.path
, ty
);
900 if name
.starts_with("rustc_") {
901 gate_feature
!(self, rustc_attrs
, attr
.span
,
902 "unless otherwise specified, attributes \
903 with the prefix `rustc_` \
904 are reserved for internal compiler diagnostics");
905 } else if name
.starts_with("derive_") {
906 gate_feature
!(self, custom_derive
, attr
.span
, EXPLAIN_DERIVE_UNDERSCORE
);
907 } else if !attr
::is_known(attr
) {
908 // Only run the custom attribute lint during regular
909 // feature gate checking. Macro gating runs
910 // before the plugin attributes are registered
911 // so we skip this then
913 gate_feature
!(self, custom_attribute
, attr
.span
,
914 &format
!("The attribute `{}` is currently \
915 unknown to the compiler and \
917 added to it in the future",
924 pub fn check_attribute(attr
: &ast
::Attribute
, parse_sess
: &ParseSess
, features
: &Features
) {
925 let cx
= Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] }
;
926 cx
.check_attribute(attr
, true);
929 pub fn find_lang_feature_accepted_version(feature
: &str) -> Option
<&'
static str> {
930 ACCEPTED_FEATURES
.iter().find(|t
| t
.0 == feature
).map(|t
| t
.1)
933 fn find_lang_feature_issue(feature
: &str) -> Option
<u32> {
934 if let Some(info
) = ACTIVE_FEATURES
.iter().find(|t
| t
.0 == feature
) {
936 // FIXME (#28244): enforce that active features have issue numbers
937 // assert!(issue.is_some())
940 // search in Accepted, Removed, or Stable Removed features
941 let found
= ACCEPTED_FEATURES
.iter().chain(REMOVED_FEATURES
).chain(STABLE_REMOVED_FEATURES
)
942 .find(|t
| t
.0 == feature
);
944 Some(&(_
, _
, issue
)) => issue
,
945 None
=> panic
!("Feature `{}` is not declared anywhere", feature
),
955 pub fn emit_feature_err(sess
: &ParseSess
, feature
: &str, span
: Span
, issue
: GateIssue
,
957 feature_err(sess
, feature
, span
, issue
, explain
).emit();
960 pub fn feature_err
<'a
>(sess
: &'a ParseSess
, feature
: &str, span
: Span
, issue
: GateIssue
,
961 explain
: &str) -> DiagnosticBuilder
<'a
> {
962 let diag
= &sess
.span_diagnostic
;
964 let issue
= match issue
{
965 GateIssue
::Language
=> find_lang_feature_issue(feature
),
966 GateIssue
::Library(lib
) => lib
,
969 let mut err
= if let Some(n
) = issue
{
970 diag
.struct_span_err(span
, &format
!("{} (see issue #{})", explain
, n
))
972 diag
.struct_span_err(span
, explain
)
975 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
976 if sess
.unstable_features
.is_nightly_build() {
977 err
.help(&format
!("add #![feature({})] to the \
978 crate attributes to enable",
985 const EXPLAIN_BOX_SYNTAX
: &'
static str =
986 "box expression syntax is experimental; you can call `Box::new` instead.";
988 pub const EXPLAIN_STMT_ATTR_SYNTAX
: &'
static str =
989 "attributes on non-item statements and expressions are experimental.";
991 pub const EXPLAIN_ASM
: &'
static str =
992 "inline assembly is not stable enough for use and is subject to change";
994 pub const EXPLAIN_GLOBAL_ASM
: &'
static str =
995 "`global_asm!` is not stable enough for use and is subject to change";
997 pub const EXPLAIN_LOG_SYNTAX
: &'
static str =
998 "`log_syntax!` is not stable enough for use and is subject to change";
1000 pub const EXPLAIN_CONCAT_IDENTS
: &'
static str =
1001 "`concat_idents` is not stable enough for use and is subject to change";
1003 pub const EXPLAIN_TRACE_MACROS
: &'
static str =
1004 "`trace_macros` is not stable enough for use and is subject to change";
1005 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE
: &'
static str =
1006 "allow_internal_unstable side-steps feature gating and stability checks";
1008 pub const EXPLAIN_CUSTOM_DERIVE
: &'
static str =
1009 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1011 pub const EXPLAIN_DEPR_CUSTOM_DERIVE
: &'
static str =
1012 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1013 Prefer using procedural macro custom derive.";
1015 pub const EXPLAIN_DERIVE_UNDERSCORE
: &'
static str =
1016 "attributes of the form `#[derive_*]` are reserved for the compiler";
1018 pub const EXPLAIN_VIS_MATCHER
: &'
static str =
1019 ":vis fragment specifier is experimental and subject to change";
1021 pub const EXPLAIN_PLACEMENT_IN
: &'
static str =
1022 "placement-in expression syntax is experimental and subject to change.";
1024 pub const CLOSURE_TO_FN_COERCION
: &'
static str =
1025 "non-capturing closure to fn coercion is experimental";
1027 struct PostExpansionVisitor
<'a
> {
1028 context
: &'a Context
<'a
>,
1031 macro_rules
! gate_feature_post
{
1032 ($cx
: expr
, $feature
: ident
, $span
: expr
, $explain
: expr
) => {{
1033 let (cx
, span
) = ($cx
, $span
);
1034 if !span
.allows_unstable() {
1035 gate_feature
!(cx
.context
, $feature
, span
, $explain
)
1040 impl<'a
> PostExpansionVisitor
<'a
> {
1041 fn check_abi(&self, abi
: Abi
, span
: Span
) {
1043 Abi
::RustIntrinsic
=> {
1044 gate_feature_post
!(&self, intrinsics
, span
,
1045 "intrinsics are subject to change");
1047 Abi
::PlatformIntrinsic
=> {
1048 gate_feature_post
!(&self, platform_intrinsics
, span
,
1049 "platform intrinsics are experimental and possibly buggy");
1051 Abi
::Vectorcall
=> {
1052 gate_feature_post
!(&self, abi_vectorcall
, span
,
1053 "vectorcall is experimental and subject to change");
1056 gate_feature_post
!(&self, unboxed_closures
, span
,
1057 "rust-call ABI is subject to change");
1060 gate_feature_post
!(&self, abi_sysv64
, span
,
1061 "sysv64 ABI is experimental and subject to change");
1064 gate_feature_post
!(&self, abi_ptx
, span
,
1065 "PTX ABIs are experimental and subject to change");
1067 Abi
::Unadjusted
=> {
1068 gate_feature_post
!(&self, abi_unadjusted
, span
,
1069 "unadjusted ABI is an implementation detail and perma-unstable");
1071 Abi
::Msp430Interrupt
=> {
1072 gate_feature_post
!(&self, abi_msp430_interrupt
, span
,
1073 "msp430-interrupt ABI is experimental and subject to change");
1075 Abi
::X86Interrupt
=> {
1076 gate_feature_post
!(&self, abi_x86_interrupt
, span
,
1077 "x86-interrupt ABI is experimental and subject to change");
1092 fn contains_novel_literal(item
: &ast
::MetaItem
) -> bool
{
1093 use ast
::MetaItemKind
::*;
1094 use ast
::NestedMetaItemKind
::*;
1098 NameValue(ref lit
) => !lit
.node
.is_str(),
1099 List(ref list
) => list
.iter().any(|li
| {
1101 MetaItem(ref mi
) => contains_novel_literal(&mi
),
1108 fn starts_with_digit(s
: &str) -> bool
{
1109 s
.as_bytes().first().cloned().map_or(false, |b
| b
>= b'
0'
&& b
<= b'
9'
)
1112 impl<'a
> Visitor
<'a
> for PostExpansionVisitor
<'a
> {
1113 fn visit_attribute(&mut self, attr
: &ast
::Attribute
) {
1114 if !attr
.span
.allows_unstable() {
1115 // check for gated attributes
1116 self.context
.check_attribute(attr
, false);
1119 if self.context
.features
.proc_macro
&& attr
::is_known(attr
) {
1123 let meta
= panictry
!(attr
.parse_meta(&self.context
.parse_sess
));
1124 if contains_novel_literal(&meta
) {
1125 gate_feature_post
!(&self, attr_literals
, attr
.span
,
1126 "non-string literals in attributes, or string \
1127 literals in top-level positions, are experimental");
1131 fn visit_name(&mut self, sp
: Span
, name
: ast
::Name
) {
1132 if !name
.as_str().is_ascii() {
1133 gate_feature_post
!(&self, non_ascii_idents
, sp
,
1134 "non-ascii idents are not fully supported.");
1138 fn visit_item(&mut self, i
: &'a ast
::Item
) {
1140 ast
::ItemKind
::ExternCrate(_
) => {
1141 if attr
::contains_name(&i
.attrs
[..], "macro_reexport") {
1142 gate_feature_post
!(&self, macro_reexport
, i
.span
,
1143 "macros reexports are experimental \
1144 and possibly buggy");
1148 ast
::ItemKind
::ForeignMod(ref foreign_module
) => {
1149 if attr
::contains_name(&i
.attrs
[..], "link_args") {
1150 gate_feature_post
!(&self, link_args
, i
.span
,
1151 "the `link_args` attribute is not portable \
1152 across platforms, it is recommended to \
1153 use `#[link(name = \"foo\")]` instead")
1155 self.check_abi(foreign_module
.abi
, i
.span
);
1158 ast
::ItemKind
::Fn(..) => {
1159 if attr
::contains_name(&i
.attrs
[..], "plugin_registrar") {
1160 gate_feature_post
!(&self, plugin_registrar
, i
.span
,
1161 "compiler plugins are experimental and possibly buggy");
1163 if attr
::contains_name(&i
.attrs
[..], "start") {
1164 gate_feature_post
!(&self, start
, i
.span
,
1165 "a #[start] function is an experimental \
1166 feature whose signature may change \
1169 if attr
::contains_name(&i
.attrs
[..], "main") {
1170 gate_feature_post
!(&self, main
, i
.span
,
1171 "declaration of a nonstandard #[main] \
1172 function may change over time, for now \
1173 a top-level `fn main()` is required");
1177 ast
::ItemKind
::Struct(..) => {
1178 if attr
::contains_name(&i
.attrs
[..], "simd") {
1179 gate_feature_post
!(&self, simd
, i
.span
,
1180 "SIMD types are experimental and possibly buggy");
1181 self.context
.parse_sess
.span_diagnostic
.span_warn(i
.span
,
1182 "the `#[simd]` attribute \
1183 is deprecated, use \
1184 `#[repr(simd)]` instead");
1186 for attr
in &i
.attrs
{
1187 if attr
.path
== "repr" {
1188 for item
in attr
.meta_item_list().unwrap_or_else(Vec
::new
) {
1189 if item
.check_name("simd") {
1190 gate_feature_post
!(&self, repr_simd
, i
.span
,
1191 "SIMD types are experimental \
1192 and possibly buggy");
1195 if item
.check_name("align") {
1196 gate_feature_post
!(&self, repr_align
, i
.span
,
1197 "the struct `#[repr(align(u16))]` attribute \
1205 ast
::ItemKind
::Union(..) => {
1206 gate_feature_post
!(&self, untagged_unions
,
1208 "unions are unstable and possibly buggy");
1211 ast
::ItemKind
::DefaultImpl(..) => {
1212 gate_feature_post
!(&self, optin_builtin_traits
,
1214 "default trait implementations are experimental \
1215 and possibly buggy");
1218 ast
::ItemKind
::Impl(_
, polarity
, _
, _
, _
, _
) => {
1220 ast
::ImplPolarity
::Negative
=> {
1221 gate_feature_post
!(&self, optin_builtin_traits
,
1223 "negative trait bounds are not yet fully implemented; \
1224 use marker types for now");
1233 visit
::walk_item(self, i
);
1236 fn visit_foreign_item(&mut self, i
: &'a ast
::ForeignItem
) {
1237 let links_to_llvm
= match attr
::first_attr_value_str_by_name(&i
.attrs
, "link_name") {
1238 Some(val
) => val
.as_str().starts_with("llvm."),
1242 gate_feature_post
!(&self, link_llvm_intrinsics
, i
.span
,
1243 "linking to LLVM intrinsics is experimental");
1246 visit
::walk_foreign_item(self, i
)
1249 fn visit_ty(&mut self, ty
: &'a ast
::Ty
) {
1251 ast
::TyKind
::BareFn(ref bare_fn_ty
) => {
1252 self.check_abi(bare_fn_ty
.abi
, ty
.span
);
1254 ast
::TyKind
::ImplTrait(..) => {
1255 gate_feature_post
!(&self, conservative_impl_trait
, ty
.span
,
1256 "`impl Trait` is experimental");
1258 ast
::TyKind
::Never
=> {
1259 gate_feature_post
!(&self, never_type
, ty
.span
,
1260 "The `!` type is experimental");
1264 visit
::walk_ty(self, ty
)
1267 fn visit_fn_ret_ty(&mut self, ret_ty
: &'a ast
::FunctionRetTy
) {
1268 if let ast
::FunctionRetTy
::Ty(ref output_ty
) = *ret_ty
{
1269 match output_ty
.node
{
1270 ast
::TyKind
::Never
=> return,
1273 self.visit_ty(output_ty
)
1277 fn visit_expr(&mut self, e
: &'a ast
::Expr
) {
1279 ast
::ExprKind
::Box(_
) => {
1280 gate_feature_post
!(&self, box_syntax
, e
.span
, EXPLAIN_BOX_SYNTAX
);
1282 ast
::ExprKind
::Type(..) => {
1283 gate_feature_post
!(&self, type_ascription
, e
.span
,
1284 "type ascription is experimental");
1286 ast
::ExprKind
::Range(_
, _
, ast
::RangeLimits
::Closed
) => {
1287 gate_feature_post
!(&self, inclusive_range_syntax
,
1289 "inclusive range syntax is experimental");
1291 ast
::ExprKind
::InPlace(..) => {
1292 gate_feature_post
!(&self, placement_in_syntax
, e
.span
, EXPLAIN_PLACEMENT_IN
);
1294 ast
::ExprKind
::Struct(_
, ref fields
, _
) => {
1295 for field
in fields
{
1296 if starts_with_digit(&field
.ident
.node
.name
.as_str()) {
1297 gate_feature_post
!(&self, relaxed_adts
,
1299 "numeric fields in struct expressions are unstable");
1303 ast
::ExprKind
::Break(_
, Some(_
)) => {
1304 gate_feature_post
!(&self, loop_break_value
, e
.span
,
1305 "`break` with a value is experimental");
1307 ast
::ExprKind
::Lit(ref lit
) => {
1308 if let ast
::LitKind
::Int(_
, ref ty
) = lit
.node
{
1310 ast
::LitIntType
::Signed(ast
::IntTy
::I128
) |
1311 ast
::LitIntType
::Unsigned(ast
::UintTy
::U128
) => {
1312 gate_feature_post
!(&self, i128_type
, e
.span
,
1313 "128-bit integers are not stable");
1319 ast
::ExprKind
::Catch(_
) => {
1320 gate_feature_post
!(&self, catch_expr
, e
.span
, "`catch` expression is experimental");
1324 visit
::walk_expr(self, e
);
1327 fn visit_pat(&mut self, pattern
: &'a ast
::Pat
) {
1328 match pattern
.node
{
1329 PatKind
::Slice(_
, Some(_
), ref last
) if !last
.is_empty() => {
1330 gate_feature_post
!(&self, advanced_slice_patterns
,
1332 "multiple-element slice matches anywhere \
1333 but at the end of a slice (e.g. \
1334 `[0, ..xs, 0]`) are experimental")
1336 PatKind
::Slice(..) => {
1337 gate_feature_post
!(&self, slice_patterns
,
1339 "slice pattern syntax is experimental");
1341 PatKind
::Box(..) => {
1342 gate_feature_post
!(&self, box_patterns
,
1344 "box pattern syntax is experimental");
1346 PatKind
::Struct(_
, ref fields
, _
) => {
1347 for field
in fields
{
1348 if starts_with_digit(&field
.node
.ident
.name
.as_str()) {
1349 gate_feature_post
!(&self, relaxed_adts
,
1351 "numeric fields in struct patterns are unstable");
1355 PatKind
::Range(_
, _
, RangeEnd
::Excluded
) => {
1356 gate_feature_post
!(&self, exclusive_range_pattern
, pattern
.span
,
1357 "exclusive range pattern syntax is experimental");
1361 visit
::walk_pat(self, pattern
)
1364 fn visit_fn(&mut self,
1365 fn_kind
: FnKind
<'a
>,
1366 fn_decl
: &'a ast
::FnDecl
,
1369 // check for const fn declarations
1371 FnKind
::ItemFn(_
, _
, _
, Spanned { node: ast::Constness::Const, .. }
, _
, _
, _
) => {
1372 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
1383 FnKind
::ItemFn(_
, _
, _
, _
, abi
, _
, _
) |
1384 FnKind
::Method(_
, &ast
::MethodSig { abi, .. }
, _
, _
) => {
1385 self.check_abi(abi
, span
);
1389 visit
::walk_fn(self, fn_kind
, fn_decl
, span
);
1392 fn visit_trait_item(&mut self, ti
: &'a ast
::TraitItem
) {
1394 ast
::TraitItemKind
::Const(..) => {
1395 gate_feature_post
!(&self, associated_consts
,
1397 "associated constants are experimental")
1399 ast
::TraitItemKind
::Method(ref sig
, ref block
) => {
1400 if block
.is_none() {
1401 self.check_abi(sig
.abi
, ti
.span
);
1403 if sig
.constness
.node
== ast
::Constness
::Const
{
1404 gate_feature_post
!(&self, const_fn
, ti
.span
, "const fn is unstable");
1407 ast
::TraitItemKind
::Type(_
, Some(_
)) => {
1408 gate_feature_post
!(&self, associated_type_defaults
, ti
.span
,
1409 "associated type defaults are unstable");
1413 visit
::walk_trait_item(self, ti
);
1416 fn visit_impl_item(&mut self, ii
: &'a ast
::ImplItem
) {
1417 if ii
.defaultness
== ast
::Defaultness
::Default
{
1418 gate_feature_post
!(&self, specialization
,
1420 "specialization is unstable");
1424 ast
::ImplItemKind
::Const(..) => {
1425 gate_feature_post
!(&self, associated_consts
,
1427 "associated constants are experimental")
1429 ast
::ImplItemKind
::Method(ref sig
, _
) => {
1430 if sig
.constness
.node
== ast
::Constness
::Const
{
1431 gate_feature_post
!(&self, const_fn
, ii
.span
, "const fn is unstable");
1436 visit
::walk_impl_item(self, ii
);
1439 fn visit_generics(&mut self, g
: &'a ast
::Generics
) {
1440 for t
in &g
.ty_params
{
1441 if !t
.attrs
.is_empty() {
1442 gate_feature_post
!(&self, generic_param_attrs
, t
.attrs
[0].span
,
1443 "attributes on type parameter bindings are experimental");
1446 visit
::walk_generics(self, g
)
1449 fn visit_lifetime_def(&mut self, lifetime_def
: &'a ast
::LifetimeDef
) {
1450 if !lifetime_def
.attrs
.is_empty() {
1451 gate_feature_post
!(&self, generic_param_attrs
, lifetime_def
.attrs
[0].span
,
1452 "attributes on lifetime bindings are experimental");
1454 visit
::walk_lifetime_def(self, lifetime_def
)
1458 pub fn get_features(span_handler
: &Handler
, krate_attrs
: &[ast
::Attribute
]) -> Features
{
1459 let mut features
= Features
::new();
1461 let mut feature_checker
= MutexFeatureChecker
::default();
1463 for attr
in krate_attrs
{
1464 if !attr
.check_name("feature") {
1468 match attr
.meta_item_list() {
1470 span_err
!(span_handler
, attr
.span
, E0555
,
1471 "malformed feature attribute, expected #![feature(...)]");
1475 let name
= if let Some(word
) = mi
.word() {
1478 span_err
!(span_handler
, mi
.span
, E0556
,
1479 "malformed feature, expected just one word");
1483 if let Some(&(_
, _
, _
, setter
)) = ACTIVE_FEATURES
.iter()
1484 .find(|& &(n
, _
, _
, _
)| name
== n
) {
1485 *(setter(&mut features
)) = true;
1486 feature_checker
.collect(&features
, mi
.span
);
1488 else if let Some(&(_
, _
, _
)) = REMOVED_FEATURES
.iter()
1489 .find(|& &(n
, _
, _
)| name
== n
)
1490 .or_else(|| STABLE_REMOVED_FEATURES
.iter()
1491 .find(|& &(n
, _
, _
)| name
== n
)) {
1492 span_err
!(span_handler
, mi
.span
, E0557
, "feature has been removed");
1494 else if let Some(&(_
, _
, _
)) = ACCEPTED_FEATURES
.iter()
1495 .find(|& &(n
, _
, _
)| name
== n
) {
1496 features
.declared_stable_lang_features
.push((name
, mi
.span
));
1498 features
.declared_lib_features
.push((name
, mi
.span
));
1505 feature_checker
.check(span_handler
);
1510 // A collector for mutually-exclusive features and their flag spans
1512 struct MutexFeatureChecker
{
1513 proc_macro
: Option
<Span
>,
1514 custom_attribute
: Option
<Span
>,
1517 impl MutexFeatureChecker
{
1518 // If this method turns out to be a hotspot due to branching,
1519 // the branching can be eliminated by modifying `setter!()` to set these spans
1520 // only for the features that need to be checked for mutual exclusion.
1521 fn collect(&mut self, features
: &Features
, span
: Span
) {
1522 if features
.proc_macro
{
1523 // If self.proc_macro is None, set to Some(span)
1524 self.proc_macro
= self.proc_macro
.or(Some(span
));
1527 if features
.custom_attribute
{
1528 self.custom_attribute
= self.custom_attribute
.or(Some(span
));
1532 fn check(self, handler
: &Handler
) {
1533 if let (Some(pm_span
), Some(ca_span
)) = (self.proc_macro
, self.custom_attribute
) {
1534 handler
.struct_span_err(pm_span
, "Cannot use `#![feature(proc_macro)]` and \
1535 `#![feature(custom_attribute)] at the same time")
1536 .span_note(ca_span
, "`#![feature(custom_attribute)]` declared here")
1544 pub fn check_crate(krate
: &ast
::Crate
,
1546 features
: &Features
,
1547 plugin_attributes
: &[(String
, AttributeType
)],
1548 unstable
: UnstableFeatures
) {
1549 maybe_stage_features(&sess
.span_diagnostic
, krate
, unstable
);
1553 plugin_attributes
: plugin_attributes
,
1555 visit
::walk_crate(&mut PostExpansionVisitor { context: &ctx }
, krate
);
1558 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1559 pub enum UnstableFeatures
{
1560 /// Hard errors for unstable features are active, as on
1561 /// beta/stable channels.
1563 /// Allow features to be activated, as on nightly.
1565 /// Errors are bypassed for bootstrapping. This is required any time
1566 /// during the build that feature-related lints are set to warn or above
1567 /// because the build turns on warnings-as-errors and uses lots of unstable
1568 /// features. As a result, this is always required for building Rust itself.
1572 impl UnstableFeatures
{
1573 pub fn from_environment() -> UnstableFeatures
{
1574 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1575 let disable_unstable_features
= option_env
!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1576 // Whether we should enable unstable features for bootstrapping
1577 let bootstrap
= env
::var("RUSTC_BOOTSTRAP").is_ok();
1578 match (disable_unstable_features
, bootstrap
) {
1579 (_
, true) => UnstableFeatures
::Cheat
,
1580 (true, _
) => UnstableFeatures
::Disallow
,
1581 (false, _
) => UnstableFeatures
::Allow
1585 pub fn is_nightly_build(&self) -> bool
{
1587 UnstableFeatures
::Allow
| UnstableFeatures
::Cheat
=> true,
1593 fn maybe_stage_features(span_handler
: &Handler
, krate
: &ast
::Crate
,
1594 unstable
: UnstableFeatures
) {
1595 let allow_features
= match unstable
{
1596 UnstableFeatures
::Allow
=> true,
1597 UnstableFeatures
::Disallow
=> false,
1598 UnstableFeatures
::Cheat
=> true
1600 if !allow_features
{
1601 for attr
in &krate
.attrs
{
1602 if attr
.check_name("feature") {
1603 let release_channel
= option_env
!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1604 span_err
!(span_handler
, attr
.span
, E0554
,
1605 "#[feature] may not be used on the {} release channel",