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}
;
31 use codemap
::{CodeMap, Spanned}
;
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 // pub(restricted) visibilities (RFC 1422)
264 (active
, pub_restricted
, "1.9.0", Some(32409)),
266 // Allow Drop types in statics/const functions (RFC 1440)
267 (active
, drop_types_in_const
, "1.9.0", Some(33156)),
269 // Allows cfg(target_has_atomic = "...").
270 (active
, cfg_target_has_atomic
, "1.9.0", Some(32976)),
272 // Allows `impl Trait` in function return types.
273 (active
, conservative_impl_trait
, "1.12.0", Some(34511)),
275 // Permits numeric fields in struct expressions and patterns.
276 (active
, relaxed_adts
, "1.12.0", Some(35626)),
279 (active
, never_type
, "1.13.0", Some(35121)),
281 // Allows all literals in attribute lists and values of key-value pairs.
282 (active
, attr_literals
, "1.13.0", Some(34981)),
284 // Allows the sysV64 ABI to be specified on all platforms
285 // instead of just the platforms on which it is the C ABI
286 (active
, abi_sysv64
, "1.13.0", Some(36167)),
288 // Allows untagged unions `union U { ... }`
289 (active
, untagged_unions
, "1.13.0", Some(32836)),
291 // Used to identify the `compiler_builtins` crate
293 (active
, compiler_builtins
, "1.13.0", None
),
295 // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
296 (active
, generic_param_attrs
, "1.11.0", Some(34761)),
298 // The #![windows_subsystem] attribute
299 (active
, windows_subsystem
, "1.14.0", Some(37499)),
301 // Allows #[link(..., cfg(..))]
302 (active
, link_cfg
, "1.14.0", Some(37406)),
304 (active
, use_extern_macros
, "1.15.0", Some(35896)),
306 // Allows `break {expr}` with a value inside `loop`s.
307 (active
, loop_break_value
, "1.14.0", Some(37339)),
309 // Allows #[target_feature(...)]
310 (active
, target_feature
, "1.15.0", None
),
312 // `extern "ptx-*" fn()`
313 (active
, abi_ptx
, "1.15.0", None
),
316 (active
, i128_type
, "1.16.0", Some(35118)),
318 // The `unadjusted` ABI. Perma unstable.
319 (active
, abi_unadjusted
, "1.16.0", None
),
322 (active
, proc_macro
, "1.16.0", Some(38356)),
324 // Allows attributes on struct literal fields.
325 (active
, struct_field_attributes
, "1.16.0", Some(38814)),
327 // Allows #[link(kind="static-nobundle"...]
328 (active
, static_nobundle
, "1.16.0", Some(37403)),
330 // `extern "msp430-interrupt" fn()`
331 (active
, abi_msp430_interrupt
, "1.16.0", Some(38487)),
333 // Coerces non capturing closures to function pointers
334 (active
, closure_to_fn_coercion
, "1.17.0", Some(39817)),
336 // Used to identify crates that contain sanitizer runtimes
338 (active
, sanitizer_runtime
, "1.17.0", None
),
340 // `extern "x86-interrupt" fn()`
341 (active
, abi_x86_interrupt
, "1.17.0", Some(40180)),
345 (removed
, import_shadowing
, "1.0.0", None
),
346 (removed
, managed_boxes
, "1.0.0", None
),
347 // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
348 (removed
, negate_unsigned
, "1.0.0", Some(29645)),
349 (removed
, reflect
, "1.0.0", Some(27749)),
350 // A way to temporarily opt out of opt in copy. This will *never* be accepted.
351 (removed
, opt_out_copy
, "1.0.0", None
),
352 (removed
, quad_precision_float
, "1.0.0", None
),
353 (removed
, struct_inherit
, "1.0.0", None
),
354 (removed
, test_removed_feature
, "1.0.0", None
),
355 (removed
, visible_private_types
, "1.0.0", None
),
356 (removed
, unsafe_no_drop_flag
, "1.0.0", None
),
357 // Allows using items which are missing stability attributes
359 (removed
, unmarked_api
, "1.0.0", None
),
360 (removed
, pushpop_unsafe
, "1.2.0", None
),
364 (stable_removed
, no_stack_check
, "1.0.0", None
),
368 (accepted
, associated_types
, "1.0.0", None
),
369 // allow overloading augmented assignment operations like `a += b`
370 (accepted
, augmented_assignments
, "1.8.0", Some(28235)),
371 // allow empty structs and enum variants with braces
372 (accepted
, braced_empty_structs
, "1.8.0", Some(29720)),
373 (accepted
, default_type_params
, "1.0.0", None
),
374 (accepted
, globs
, "1.0.0", None
),
375 (accepted
, if_let
, "1.0.0", None
),
376 // A temporary feature gate used to enable parser extensions needed
377 // to bootstrap fix for #5723.
378 (accepted
, issue_5723_bootstrap
, "1.0.0", None
),
379 (accepted
, macro_rules
, "1.0.0", None
),
380 // Allows using #![no_std]
381 (accepted
, no_std
, "1.6.0", None
),
382 (accepted
, slicing_syntax
, "1.0.0", None
),
383 (accepted
, struct_variant
, "1.0.0", None
),
384 // These are used to test this portion of the compiler, they don't actually
386 (accepted
, test_accepted_feature
, "1.0.0", None
),
387 (accepted
, tuple_indexing
, "1.0.0", None
),
388 // Allows macros to appear in the type position.
389 (accepted
, type_macros
, "1.13.0", Some(27245)),
390 (accepted
, while_let
, "1.0.0", None
),
391 // Allows `#[deprecated]` attribute
392 (accepted
, deprecated
, "1.9.0", Some(29935)),
394 (accepted
, question_mark
, "1.13.0", Some(31436)),
395 // Allows `..` in tuple (struct) patterns
396 (accepted
, dotdot_in_tuple_patterns
, "1.14.0", Some(33627)),
397 (accepted
, item_like_imports
, "1.14.0", Some(35120)),
398 // Allows using `Self` and associated types in struct expressions and patterns.
399 (accepted
, more_struct_aliases
, "1.16.0", Some(37544)),
400 // elide `'static` lifetimes in `static`s and `const`s
401 (accepted
, static_in_const
, "1.17.0", Some(35897)),
402 // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
403 (accepted
, field_init_shorthand
, "1.17.0", Some(37340)),
404 // Allows the definition recursive static items.
405 (accepted
, static_recursion
, "1.17.0", Some(29719)),
407 // If you change this, please modify src/doc/unstable-book as well. You must
408 // move that documentation into the relevant place in the other docs, and
409 // remove the chapter on the flag.
411 #[derive(PartialEq, Copy, Clone, Debug)]
412 pub enum AttributeType
{
413 /// Normal, builtin attribute that is consumed
414 /// by the compiler before the unused_attribute check
417 /// Builtin attribute that may not be consumed by the compiler
418 /// before the unused_attribute check. These attributes
419 /// will be ignored by the unused_attribute lint
422 /// Builtin attribute that is only allowed at the crate level
426 pub enum AttributeGate
{
427 /// Is gated by a given feature gate, reason
428 /// and function to check if enabled
429 Gated(Stability
, &'
static str, &'
static str, fn(&Features
) -> bool
),
431 /// Ungated attribute, can be used on all release channels
436 fn is_deprecated(&self) -> bool
{
438 Gated(Stability
::Deprecated(_
), ..) => true,
444 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
447 // Argument is tracking issue link.
448 Deprecated(&'
static str),
452 impl ::std
::fmt
::Debug
for AttributeGate
{
453 fn fmt(&self, fmt
: &mut ::std
::fmt
::Formatter
) -> ::std
::fmt
::Result
{
455 Gated(ref stab
, ref name
, ref expl
, _
) =>
456 write
!(fmt
, "Gated({:?}, {}, {})", stab
, name
, expl
),
457 Ungated
=> write
!(fmt
, "Ungated")
462 macro_rules
! cfg_fn
{
463 ($field
: ident
) => {{
464 fn f(features
: &Features
) -> bool
{
467 f
as fn(&Features
) -> bool
471 pub fn deprecated_attributes() -> Vec
<&'
static (&'
static str, AttributeType
, AttributeGate
)> {
472 BUILTIN_ATTRIBUTES
.iter().filter(|a
| a
.2.is_deprecated
()).collect()
475 pub fn is_builtin_attr(attr
: &ast
::Attribute
) -> bool
{
476 BUILTIN_ATTRIBUTES
.iter().any(|&(builtin_name
, _
, _
)| attr
.check_name(builtin_name
))
479 // Attributes that have a special meaning to rustc or rustdoc
480 pub const BUILTIN_ATTRIBUTES
: &'
static [(&'
static str, AttributeType
, AttributeGate
)] = &[
483 ("warn", Normal
, Ungated
),
484 ("allow", Normal
, Ungated
),
485 ("forbid", Normal
, Ungated
),
486 ("deny", Normal
, Ungated
),
488 ("macro_reexport", Normal
, Ungated
),
489 ("macro_use", Normal
, Ungated
),
490 ("macro_export", Normal
, Ungated
),
491 ("plugin_registrar", Normal
, Ungated
),
493 ("cfg", Normal
, Ungated
),
494 ("cfg_attr", Normal
, Ungated
),
495 ("main", Normal
, Ungated
),
496 ("start", Normal
, Ungated
),
497 ("test", Normal
, Ungated
),
498 ("bench", Normal
, Ungated
),
499 ("simd", Normal
, Ungated
),
500 ("repr", Normal
, Ungated
),
501 ("path", Normal
, Ungated
),
502 ("abi", Normal
, Ungated
),
503 ("automatically_derived", Normal
, Ungated
),
504 ("no_mangle", Normal
, Ungated
),
505 ("no_link", Normal
, Ungated
),
506 ("derive", Normal
, Ungated
),
507 ("should_panic", Normal
, Ungated
),
508 ("ignore", Normal
, Ungated
),
509 ("no_implicit_prelude", Normal
, Ungated
),
510 ("reexport_test_harness_main", Normal
, Ungated
),
511 ("link_args", Normal
, Ungated
),
512 ("macro_escape", Normal
, Ungated
),
515 ("structural_match", Whitelisted
, Gated(Stability
::Unstable
,
517 "the semantics of constant patterns is \
519 cfg_fn
!(structural_match
))),
521 ("plugin", CrateLevel
, Gated(Stability
::Unstable
,
523 "compiler plugins are experimental \
527 ("no_std", CrateLevel
, Ungated
),
528 ("no_core", CrateLevel
, Gated(Stability
::Unstable
,
530 "no_core is experimental",
532 ("lang", Normal
, Gated(Stability
::Unstable
,
534 "language items are subject to change",
535 cfg_fn
!(lang_items
))),
536 ("linkage", Whitelisted
, Gated(Stability
::Unstable
,
538 "the `linkage` attribute is experimental \
539 and not portable across platforms",
541 ("thread_local", Whitelisted
, Gated(Stability
::Unstable
,
543 "`#[thread_local]` is an experimental feature, and does \
544 not currently handle destructors. There is no \
545 corresponding `#[task_local]` mapping to the task \
547 cfg_fn
!(thread_local
))),
549 ("rustc_on_unimplemented", Normal
, Gated(Stability
::Unstable
,
551 "the `#[rustc_on_unimplemented]` attribute \
552 is an experimental feature",
553 cfg_fn
!(on_unimplemented
))),
554 ("allocator", Whitelisted
, Gated(Stability
::Unstable
,
556 "the `#[allocator]` attribute is an experimental feature",
557 cfg_fn
!(allocator
))),
558 ("needs_allocator", Normal
, Gated(Stability
::Unstable
,
560 "the `#[needs_allocator]` \
561 attribute is an experimental \
563 cfg_fn
!(needs_allocator
))),
564 ("panic_runtime", Whitelisted
, Gated(Stability
::Unstable
,
566 "the `#[panic_runtime]` attribute is \
567 an experimental feature",
568 cfg_fn
!(panic_runtime
))),
569 ("needs_panic_runtime", Whitelisted
, Gated(Stability
::Unstable
,
570 "needs_panic_runtime",
571 "the `#[needs_panic_runtime]` \
572 attribute is an experimental \
574 cfg_fn
!(needs_panic_runtime
))),
575 ("rustc_variance", Normal
, Gated(Stability
::Unstable
,
577 "the `#[rustc_variance]` attribute \
578 is just used for rustc unit tests \
579 and will never be stable",
580 cfg_fn
!(rustc_attrs
))),
581 ("rustc_error", Whitelisted
, Gated(Stability
::Unstable
,
583 "the `#[rustc_error]` attribute \
584 is just used for rustc unit tests \
585 and will never be stable",
586 cfg_fn
!(rustc_attrs
))),
587 ("rustc_if_this_changed", Whitelisted
, Gated(Stability
::Unstable
,
589 "the `#[rustc_if_this_changed]` attribute \
590 is just used for rustc unit tests \
591 and will never be stable",
592 cfg_fn
!(rustc_attrs
))),
593 ("rustc_then_this_would_need", Whitelisted
, Gated(Stability
::Unstable
,
595 "the `#[rustc_if_this_changed]` attribute \
596 is just used for rustc unit tests \
597 and will never be stable",
598 cfg_fn
!(rustc_attrs
))),
599 ("rustc_dirty", Whitelisted
, Gated(Stability
::Unstable
,
601 "the `#[rustc_dirty]` attribute \
602 is just used for rustc unit tests \
603 and will never be stable",
604 cfg_fn
!(rustc_attrs
))),
605 ("rustc_clean", Whitelisted
, Gated(Stability
::Unstable
,
607 "the `#[rustc_clean]` attribute \
608 is just used for rustc unit tests \
609 and will never be stable",
610 cfg_fn
!(rustc_attrs
))),
611 ("rustc_metadata_dirty", Whitelisted
, Gated(Stability
::Unstable
,
613 "the `#[rustc_metadata_dirty]` attribute \
614 is just used for rustc unit tests \
615 and will never be stable",
616 cfg_fn
!(rustc_attrs
))),
617 ("rustc_metadata_clean", Whitelisted
, Gated(Stability
::Unstable
,
619 "the `#[rustc_metadata_clean]` attribute \
620 is just used for rustc unit tests \
621 and will never be stable",
622 cfg_fn
!(rustc_attrs
))),
623 ("rustc_partition_reused", Whitelisted
, Gated(Stability
::Unstable
,
626 is just used for rustc unit tests \
627 and will never be stable",
628 cfg_fn
!(rustc_attrs
))),
629 ("rustc_partition_translated", Whitelisted
, Gated(Stability
::Unstable
,
632 is just used for rustc unit tests \
633 and will never be stable",
634 cfg_fn
!(rustc_attrs
))),
635 ("rustc_symbol_name", Whitelisted
, Gated(Stability
::Unstable
,
637 "internal rustc attributes will never be stable",
638 cfg_fn
!(rustc_attrs
))),
639 ("rustc_item_path", Whitelisted
, Gated(Stability
::Unstable
,
641 "internal rustc attributes will never be stable",
642 cfg_fn
!(rustc_attrs
))),
643 ("rustc_move_fragments", Normal
, Gated(Stability
::Unstable
,
645 "the `#[rustc_move_fragments]` attribute \
646 is just used for rustc unit tests \
647 and will never be stable",
648 cfg_fn
!(rustc_attrs
))),
649 ("rustc_mir", Whitelisted
, Gated(Stability
::Unstable
,
651 "the `#[rustc_mir]` attribute \
652 is just used for rustc unit tests \
653 and will never be stable",
654 cfg_fn
!(rustc_attrs
))),
655 ("rustc_inherit_overflow_checks", Whitelisted
, Gated(Stability
::Unstable
,
657 "the `#[rustc_inherit_overflow_checks]` \
658 attribute is just used to control \
659 overflow checking behavior of several \
660 libcore functions that are inlined \
661 across crates and will never be stable",
662 cfg_fn
!(rustc_attrs
))),
663 ("compiler_builtins", Whitelisted
, Gated(Stability
::Unstable
,
665 "the `#[compiler_builtins]` attribute is used to \
666 identify the `compiler_builtins` crate which \
667 contains compiler-rt intrinsics and will never be \
669 cfg_fn
!(compiler_builtins
))),
670 ("sanitizer_runtime", Whitelisted
, Gated(Stability
::Unstable
,
672 "the `#[sanitizer_runtime]` attribute is used to \
673 identify crates that contain the runtime of a \
674 sanitizer and will never be stable",
675 cfg_fn
!(sanitizer_runtime
))),
677 ("allow_internal_unstable", Normal
, Gated(Stability
::Unstable
,
678 "allow_internal_unstable",
679 EXPLAIN_ALLOW_INTERNAL_UNSTABLE
,
680 cfg_fn
!(allow_internal_unstable
))),
682 ("fundamental", Whitelisted
, Gated(Stability
::Unstable
,
684 "the `#[fundamental]` attribute \
685 is an experimental feature",
686 cfg_fn
!(fundamental
))),
688 ("proc_macro_derive", Normal
, Ungated
),
690 ("rustc_copy_clone_marker", Whitelisted
, Gated(Stability
::Unstable
,
692 "internal implementation detail",
693 cfg_fn
!(rustc_attrs
))),
695 // FIXME: #14408 whitelist docs since rustdoc looks at them
696 ("doc", Whitelisted
, Ungated
),
698 // FIXME: #14406 these are processed in trans, which happens after the
700 ("cold", Whitelisted
, Ungated
),
701 ("naked", Whitelisted
, Gated(Stability
::Unstable
,
703 "the `#[naked]` attribute \
704 is an experimental feature",
705 cfg_fn
!(naked_functions
))),
706 ("target_feature", Whitelisted
, Gated(
707 Stability
::Unstable
, "target_feature",
708 "the `#[target_feature]` attribute is an experimental feature",
709 cfg_fn
!(target_feature
))),
710 ("export_name", Whitelisted
, Ungated
),
711 ("inline", Whitelisted
, Ungated
),
712 ("link", Whitelisted
, Ungated
),
713 ("link_name", Whitelisted
, Ungated
),
714 ("link_section", Whitelisted
, Ungated
),
715 ("no_builtins", Whitelisted
, Ungated
),
716 ("no_mangle", Whitelisted
, Ungated
),
717 ("no_debug", Whitelisted
, Gated(
718 Stability
::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
720 "the `#[no_debug]` attribute is an experimental feature",
722 ("omit_gdb_pretty_printer_section", Whitelisted
, Gated(Stability
::Unstable
,
723 "omit_gdb_pretty_printer_section",
724 "the `#[omit_gdb_pretty_printer_section]` \
725 attribute is just used for the Rust test \
727 cfg_fn
!(omit_gdb_pretty_printer_section
))),
728 ("unsafe_destructor_blind_to_params",
730 Gated(Stability
::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
731 "dropck_parametricity",
732 "unsafe_destructor_blind_to_params has been replaced by \
733 may_dangle and will be removed in the future",
734 cfg_fn
!(dropck_parametricity
))),
737 Gated(Stability
::Unstable
,
739 "may_dangle has unstable semantics and may be removed in the future",
740 cfg_fn
!(dropck_eyepatch
))),
741 ("unwind", Whitelisted
, Gated(Stability
::Unstable
,
743 "#[unwind] is experimental",
744 cfg_fn
!(unwind_attributes
))),
747 ("prelude_import", Whitelisted
, Gated(Stability
::Unstable
,
749 "`#[prelude_import]` is for use by rustc only",
750 cfg_fn
!(prelude_import
))),
752 // FIXME: #14407 these are only looked at on-demand so we can't
753 // guarantee they'll have already been checked
754 ("rustc_deprecated", Whitelisted
, Ungated
),
755 ("must_use", Whitelisted
, Ungated
),
756 ("stable", Whitelisted
, Ungated
),
757 ("unstable", Whitelisted
, Ungated
),
758 ("deprecated", Normal
, Ungated
),
760 ("rustc_paren_sugar", Normal
, Gated(Stability
::Unstable
,
762 "unboxed_closures are still evolving",
763 cfg_fn
!(unboxed_closures
))),
765 ("windows_subsystem", Whitelisted
, Gated(Stability
::Unstable
,
767 "the windows subsystem attribute \
768 is currently unstable",
769 cfg_fn
!(windows_subsystem
))),
771 ("proc_macro_attribute", Normal
, Gated(Stability
::Unstable
,
773 "attribute proc macros are currently unstable",
774 cfg_fn
!(proc_macro
))),
776 ("proc_macro", Normal
, Gated(Stability
::Unstable
,
778 "function-like proc macros are currently unstable",
779 cfg_fn
!(proc_macro
))),
781 ("rustc_derive_registrar", Normal
, Gated(Stability
::Unstable
,
782 "rustc_derive_registrar",
783 "used internally by rustc",
784 cfg_fn
!(rustc_attrs
))),
786 // Crate level attributes
787 ("crate_name", CrateLevel
, Ungated
),
788 ("crate_type", CrateLevel
, Ungated
),
789 ("crate_id", CrateLevel
, Ungated
),
790 ("feature", CrateLevel
, Ungated
),
791 ("no_start", CrateLevel
, Ungated
),
792 ("no_main", CrateLevel
, Ungated
),
793 ("no_builtins", CrateLevel
, Ungated
),
794 ("recursion_limit", CrateLevel
, Ungated
),
795 ("type_length_limit", CrateLevel
, Ungated
),
798 // cfg(...)'s that are feature gated
799 const GATED_CFGS
: &'
static [(&'
static str, &'
static str, fn(&Features
) -> bool
)] = &[
800 // (name in cfg, feature, function to check if the feature is enabled)
801 ("target_feature", "cfg_target_feature", cfg_fn
!(cfg_target_feature
)),
802 ("target_vendor", "cfg_target_vendor", cfg_fn
!(cfg_target_vendor
)),
803 ("target_thread_local", "cfg_target_thread_local", cfg_fn
!(cfg_target_thread_local
)),
804 ("target_has_atomic", "cfg_target_has_atomic", cfg_fn
!(cfg_target_has_atomic
)),
807 #[derive(Debug, Eq, PartialEq)]
808 pub struct GatedCfg
{
814 pub fn gate(cfg
: &ast
::MetaItem
) -> Option
<GatedCfg
> {
815 let name
= &*cfg
.name().as_str();
817 .position(|info
| info
.0 == name
)
826 pub fn check_and_emit(&self, sess
: &ParseSess
, features
: &Features
) {
827 let (cfg
, feature
, has_feature
) = GATED_CFGS
[self.index
];
828 if !has_feature(features
) && !sess
.codemap().span_allows_unstable(self.span
) {
829 let explain
= format
!("`cfg({})` is experimental and subject to change", cfg
);
830 emit_feature_err(sess
, feature
, self.span
, GateIssue
::Language
, &explain
);
836 features
: &'a Features
,
837 parse_sess
: &'a ParseSess
,
839 plugin_attributes
: &'a
[(String
, AttributeType
)],
842 macro_rules
! gate_feature_fn
{
843 ($cx
: expr
, $has_feature
: expr
, $span
: expr
, $name
: expr
, $explain
: expr
) => {{
844 let (cx
, has_feature
, span
, name
, explain
) = ($cx
, $has_feature
, $span
, $name
, $explain
);
845 let has_feature
: bool
= has_feature(&$cx
.features
);
846 debug
!("gate_feature(feature = {:?}, span = {:?}); has? {}", name
, span
, has_feature
);
847 if !has_feature
&& !cx
.cm
.span_allows_unstable(span
) {
848 emit_feature_err(cx
.parse_sess
, name
, span
, GateIssue
::Language
, explain
);
853 macro_rules
! gate_feature
{
854 ($cx
: expr
, $feature
: ident
, $span
: expr
, $explain
: expr
) => {
855 gate_feature_fn
!($cx
, |x
:&Features
| x
.$feature
, $span
, stringify
!($feature
), $explain
)
859 impl<'a
> Context
<'a
> {
860 fn check_attribute(&self, attr
: &ast
::Attribute
, is_macro
: bool
) {
861 debug
!("check_attribute(attr = {:?})", attr
);
862 let name
= &*attr
.name().as_str();
863 for &(n
, ty
, ref gateage
) in BUILTIN_ATTRIBUTES
{
865 if let &Gated(_
, ref name
, ref desc
, ref has_feature
) = gateage
{
866 gate_feature_fn
!(self, has_feature
, attr
.span
, name
, desc
);
868 debug
!("check_attribute: {:?} is builtin, {:?}, {:?}", name
, ty
, gateage
);
872 for &(ref n
, ref ty
) in self.plugin_attributes
{
874 // Plugins can't gate attributes, so we don't check for it
875 // unlike the code above; we only use this loop to
876 // short-circuit to avoid the checks below
877 debug
!("check_attribute: {:?} is registered by a plugin, {:?}", name
, ty
);
881 if name
.starts_with("rustc_") {
882 gate_feature
!(self, rustc_attrs
, attr
.span
,
883 "unless otherwise specified, attributes \
884 with the prefix `rustc_` \
885 are reserved for internal compiler diagnostics");
886 } else if name
.starts_with("derive_") {
887 gate_feature
!(self, custom_derive
, attr
.span
, EXPLAIN_DERIVE_UNDERSCORE
);
888 } else if attr
::is_known(attr
) {
889 debug
!("check_attribute: {:?} is known", name
);
891 // Only run the custom attribute lint during regular
892 // feature gate checking. Macro gating runs
893 // before the plugin attributes are registered
894 // so we skip this then
896 gate_feature
!(self, custom_attribute
, attr
.span
,
897 &format
!("The attribute `{}` is currently \
898 unknown to the compiler and \
900 added to it in the future",
907 pub fn check_attribute(attr
: &ast
::Attribute
, parse_sess
: &ParseSess
,
908 cm
: &CodeMap
, features
: &Features
) {
910 features
: features
, parse_sess
: parse_sess
,
911 cm
: cm
, plugin_attributes
: &[]
913 cx
.check_attribute(attr
, true);
916 pub fn find_lang_feature_accepted_version(feature
: &str) -> Option
<&'
static str> {
917 ACCEPTED_FEATURES
.iter().find(|t
| t
.0 == feature
).map(|t
| t
.1)
920 fn find_lang_feature_issue(feature
: &str) -> Option
<u32> {
921 if let Some(info
) = ACTIVE_FEATURES
.iter().find(|t
| t
.0 == feature
) {
923 // FIXME (#28244): enforce that active features have issue numbers
924 // assert!(issue.is_some())
927 // search in Accepted, Removed, or Stable Removed features
928 let found
= ACCEPTED_FEATURES
.iter().chain(REMOVED_FEATURES
).chain(STABLE_REMOVED_FEATURES
)
929 .find(|t
| t
.0 == feature
);
931 Some(&(_
, _
, issue
)) => issue
,
932 None
=> panic
!("Feature `{}` is not declared anywhere", feature
),
942 pub fn emit_feature_err(sess
: &ParseSess
, feature
: &str, span
: Span
, issue
: GateIssue
,
944 feature_err(sess
, feature
, span
, issue
, explain
).emit();
947 pub fn feature_err
<'a
>(sess
: &'a ParseSess
, feature
: &str, span
: Span
, issue
: GateIssue
,
948 explain
: &str) -> DiagnosticBuilder
<'a
> {
949 let diag
= &sess
.span_diagnostic
;
951 let issue
= match issue
{
952 GateIssue
::Language
=> find_lang_feature_issue(feature
),
953 GateIssue
::Library(lib
) => lib
,
956 let mut err
= if let Some(n
) = issue
{
957 diag
.struct_span_err(span
, &format
!("{} (see issue #{})", explain
, n
))
959 diag
.struct_span_err(span
, explain
)
962 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
963 if sess
.unstable_features
.is_nightly_build() {
964 err
.help(&format
!("add #![feature({})] to the \
965 crate attributes to enable",
972 const EXPLAIN_BOX_SYNTAX
: &'
static str =
973 "box expression syntax is experimental; you can call `Box::new` instead.";
975 pub const EXPLAIN_STMT_ATTR_SYNTAX
: &'
static str =
976 "attributes on non-item statements and expressions are experimental.";
978 pub const EXPLAIN_ASM
: &'
static str =
979 "inline assembly is not stable enough for use and is subject to change";
981 pub const EXPLAIN_LOG_SYNTAX
: &'
static str =
982 "`log_syntax!` is not stable enough for use and is subject to change";
984 pub const EXPLAIN_CONCAT_IDENTS
: &'
static str =
985 "`concat_idents` is not stable enough for use and is subject to change";
987 pub const EXPLAIN_TRACE_MACROS
: &'
static str =
988 "`trace_macros` is not stable enough for use and is subject to change";
989 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE
: &'
static str =
990 "allow_internal_unstable side-steps feature gating and stability checks";
992 pub const EXPLAIN_CUSTOM_DERIVE
: &'
static str =
993 "`#[derive]` for custom traits is deprecated and will be removed in the future.";
995 pub const EXPLAIN_DEPR_CUSTOM_DERIVE
: &'
static str =
996 "`#[derive]` for custom traits is deprecated and will be removed in the future. \
997 Prefer using procedural macro custom derive.";
999 pub const EXPLAIN_DERIVE_UNDERSCORE
: &'
static str =
1000 "attributes of the form `#[derive_*]` are reserved for the compiler";
1002 pub const EXPLAIN_PLACEMENT_IN
: &'
static str =
1003 "placement-in expression syntax is experimental and subject to change.";
1005 pub const CLOSURE_TO_FN_COERCION
: &'
static str =
1006 "non-capturing closure to fn coercion is experimental";
1008 struct PostExpansionVisitor
<'a
> {
1009 context
: &'a Context
<'a
>,
1012 macro_rules
! gate_feature_post
{
1013 ($cx
: expr
, $feature
: ident
, $span
: expr
, $explain
: expr
) => {{
1014 let (cx
, span
) = ($cx
, $span
);
1015 if !cx
.context
.cm
.span_allows_unstable(span
) {
1016 gate_feature
!(cx
.context
, $feature
, span
, $explain
)
1021 impl<'a
> PostExpansionVisitor
<'a
> {
1022 fn check_abi(&self, abi
: Abi
, span
: Span
) {
1024 Abi
::RustIntrinsic
=> {
1025 gate_feature_post
!(&self, intrinsics
, span
,
1026 "intrinsics are subject to change");
1028 Abi
::PlatformIntrinsic
=> {
1029 gate_feature_post
!(&self, platform_intrinsics
, span
,
1030 "platform intrinsics are experimental and possibly buggy");
1032 Abi
::Vectorcall
=> {
1033 gate_feature_post
!(&self, abi_vectorcall
, span
,
1034 "vectorcall is experimental and subject to change");
1037 gate_feature_post
!(&self, unboxed_closures
, span
,
1038 "rust-call ABI is subject to change");
1041 gate_feature_post
!(&self, abi_sysv64
, span
,
1042 "sysv64 ABI is experimental and subject to change");
1045 gate_feature_post
!(&self, abi_ptx
, span
,
1046 "PTX ABIs are experimental and subject to change");
1048 Abi
::Unadjusted
=> {
1049 gate_feature_post
!(&self, abi_unadjusted
, span
,
1050 "unadjusted ABI is an implementation detail and perma-unstable");
1052 Abi
::Msp430Interrupt
=> {
1053 gate_feature_post
!(&self, abi_msp430_interrupt
, span
,
1054 "msp430-interrupt ABI is experimental and subject to change");
1056 Abi
::X86Interrupt
=> {
1057 gate_feature_post
!(&self, abi_x86_interrupt
, span
,
1058 "x86-interrupt ABI is experimental and subject to change");
1073 fn contains_novel_literal(item
: &ast
::MetaItem
) -> bool
{
1074 use ast
::MetaItemKind
::*;
1075 use ast
::NestedMetaItemKind
::*;
1079 NameValue(ref lit
) => !lit
.node
.is_str(),
1080 List(ref list
) => list
.iter().any(|li
| {
1082 MetaItem(ref mi
) => contains_novel_literal(&mi
),
1089 fn starts_with_digit(s
: &str) -> bool
{
1090 s
.as_bytes().first().cloned().map_or(false, |b
| b
>= b'
0'
&& b
<= b'
9'
)
1093 impl<'a
> Visitor
<'a
> for PostExpansionVisitor
<'a
> {
1094 fn visit_attribute(&mut self, attr
: &ast
::Attribute
) {
1095 if !self.context
.cm
.span_allows_unstable(attr
.span
) {
1096 // check for gated attributes
1097 self.context
.check_attribute(attr
, false);
1100 if contains_novel_literal(&attr
.value
) {
1101 gate_feature_post
!(&self, attr_literals
, attr
.span
,
1102 "non-string literals in attributes, or string \
1103 literals in top-level positions, are experimental");
1107 fn visit_name(&mut self, sp
: Span
, name
: ast
::Name
) {
1108 if !name
.as_str().is_ascii() {
1109 gate_feature_post
!(&self, non_ascii_idents
, sp
,
1110 "non-ascii idents are not fully supported.");
1114 fn visit_item(&mut self, i
: &'a ast
::Item
) {
1116 ast
::ItemKind
::ExternCrate(_
) => {
1117 if attr
::contains_name(&i
.attrs
[..], "macro_reexport") {
1118 gate_feature_post
!(&self, macro_reexport
, i
.span
,
1119 "macros reexports are experimental \
1120 and possibly buggy");
1124 ast
::ItemKind
::ForeignMod(ref foreign_module
) => {
1125 if attr
::contains_name(&i
.attrs
[..], "link_args") {
1126 gate_feature_post
!(&self, link_args
, i
.span
,
1127 "the `link_args` attribute is not portable \
1128 across platforms, it is recommended to \
1129 use `#[link(name = \"foo\")]` instead")
1131 self.check_abi(foreign_module
.abi
, i
.span
);
1134 ast
::ItemKind
::Fn(..) => {
1135 if attr
::contains_name(&i
.attrs
[..], "plugin_registrar") {
1136 gate_feature_post
!(&self, plugin_registrar
, i
.span
,
1137 "compiler plugins are experimental and possibly buggy");
1139 if attr
::contains_name(&i
.attrs
[..], "start") {
1140 gate_feature_post
!(&self, start
, i
.span
,
1141 "a #[start] function is an experimental \
1142 feature whose signature may change \
1145 if attr
::contains_name(&i
.attrs
[..], "main") {
1146 gate_feature_post
!(&self, main
, i
.span
,
1147 "declaration of a nonstandard #[main] \
1148 function may change over time, for now \
1149 a top-level `fn main()` is required");
1153 ast
::ItemKind
::Struct(..) => {
1154 if attr
::contains_name(&i
.attrs
[..], "simd") {
1155 gate_feature_post
!(&self, simd
, i
.span
,
1156 "SIMD types are experimental and possibly buggy");
1157 self.context
.parse_sess
.span_diagnostic
.span_warn(i
.span
,
1158 "the `#[simd]` attribute \
1159 is deprecated, use \
1160 `#[repr(simd)]` instead");
1162 for attr
in &i
.attrs
{
1163 if attr
.name() == "repr" {
1164 for item
in attr
.meta_item_list().unwrap_or(&[]) {
1165 if item
.check_name("simd") {
1166 gate_feature_post
!(&self, repr_simd
, i
.span
,
1167 "SIMD types are experimental \
1168 and possibly buggy");
1176 ast
::ItemKind
::Union(..) => {
1177 gate_feature_post
!(&self, untagged_unions
,
1179 "unions are unstable and possibly buggy");
1182 ast
::ItemKind
::DefaultImpl(..) => {
1183 gate_feature_post
!(&self, optin_builtin_traits
,
1185 "default trait implementations are experimental \
1186 and possibly buggy");
1189 ast
::ItemKind
::Impl(_
, polarity
, _
, _
, _
, _
) => {
1191 ast
::ImplPolarity
::Negative
=> {
1192 gate_feature_post
!(&self, optin_builtin_traits
,
1194 "negative trait bounds are not yet fully implemented; \
1195 use marker types for now");
1204 visit
::walk_item(self, i
);
1207 fn visit_foreign_item(&mut self, i
: &'a ast
::ForeignItem
) {
1208 let links_to_llvm
= match attr
::first_attr_value_str_by_name(&i
.attrs
, "link_name") {
1209 Some(val
) => val
.as_str().starts_with("llvm."),
1213 gate_feature_post
!(&self, link_llvm_intrinsics
, i
.span
,
1214 "linking to LLVM intrinsics is experimental");
1217 visit
::walk_foreign_item(self, i
)
1220 fn visit_ty(&mut self, ty
: &'a ast
::Ty
) {
1222 ast
::TyKind
::BareFn(ref bare_fn_ty
) => {
1223 self.check_abi(bare_fn_ty
.abi
, ty
.span
);
1225 ast
::TyKind
::ImplTrait(..) => {
1226 gate_feature_post
!(&self, conservative_impl_trait
, ty
.span
,
1227 "`impl Trait` is experimental");
1229 ast
::TyKind
::Never
=> {
1230 gate_feature_post
!(&self, never_type
, ty
.span
,
1231 "The `!` type is experimental");
1235 visit
::walk_ty(self, ty
)
1238 fn visit_fn_ret_ty(&mut self, ret_ty
: &'a ast
::FunctionRetTy
) {
1239 if let ast
::FunctionRetTy
::Ty(ref output_ty
) = *ret_ty
{
1240 match output_ty
.node
{
1241 ast
::TyKind
::Never
=> return,
1244 self.visit_ty(output_ty
)
1248 fn visit_expr(&mut self, e
: &'a ast
::Expr
) {
1250 ast
::ExprKind
::Box(_
) => {
1251 gate_feature_post
!(&self, box_syntax
, e
.span
, EXPLAIN_BOX_SYNTAX
);
1253 ast
::ExprKind
::Type(..) => {
1254 gate_feature_post
!(&self, type_ascription
, e
.span
,
1255 "type ascription is experimental");
1257 ast
::ExprKind
::Range(_
, _
, ast
::RangeLimits
::Closed
) => {
1258 gate_feature_post
!(&self, inclusive_range_syntax
,
1260 "inclusive range syntax is experimental");
1262 ast
::ExprKind
::InPlace(..) => {
1263 gate_feature_post
!(&self, placement_in_syntax
, e
.span
, EXPLAIN_PLACEMENT_IN
);
1265 ast
::ExprKind
::Struct(_
, ref fields
, _
) => {
1266 for field
in fields
{
1267 if starts_with_digit(&field
.ident
.node
.name
.as_str()) {
1268 gate_feature_post
!(&self, relaxed_adts
,
1270 "numeric fields in struct expressions are unstable");
1274 ast
::ExprKind
::Break(_
, Some(_
)) => {
1275 gate_feature_post
!(&self, loop_break_value
, e
.span
,
1276 "`break` with a value is experimental");
1278 ast
::ExprKind
::Lit(ref lit
) => {
1279 if let ast
::LitKind
::Int(_
, ref ty
) = lit
.node
{
1281 ast
::LitIntType
::Signed(ast
::IntTy
::I128
) |
1282 ast
::LitIntType
::Unsigned(ast
::UintTy
::U128
) => {
1283 gate_feature_post
!(&self, i128_type
, e
.span
,
1284 "128-bit integers are not stable");
1292 visit
::walk_expr(self, e
);
1295 fn visit_pat(&mut self, pattern
: &'a ast
::Pat
) {
1296 match pattern
.node
{
1297 PatKind
::Slice(_
, Some(_
), ref last
) if !last
.is_empty() => {
1298 gate_feature_post
!(&self, advanced_slice_patterns
,
1300 "multiple-element slice matches anywhere \
1301 but at the end of a slice (e.g. \
1302 `[0, ..xs, 0]`) are experimental")
1304 PatKind
::Slice(..) => {
1305 gate_feature_post
!(&self, slice_patterns
,
1307 "slice pattern syntax is experimental");
1309 PatKind
::Box(..) => {
1310 gate_feature_post
!(&self, box_patterns
,
1312 "box pattern syntax is experimental");
1314 PatKind
::Struct(_
, ref fields
, _
) => {
1315 for field
in fields
{
1316 if starts_with_digit(&field
.node
.ident
.name
.as_str()) {
1317 gate_feature_post
!(&self, relaxed_adts
,
1319 "numeric fields in struct patterns are unstable");
1323 PatKind
::Range(_
, _
, RangeEnd
::Excluded
) => {
1324 gate_feature_post
!(&self, exclusive_range_pattern
, pattern
.span
,
1325 "exclusive range pattern syntax is experimental");
1329 visit
::walk_pat(self, pattern
)
1332 fn visit_fn(&mut self,
1333 fn_kind
: FnKind
<'a
>,
1334 fn_decl
: &'a ast
::FnDecl
,
1337 // check for const fn declarations
1339 FnKind
::ItemFn(_
, _
, _
, Spanned { node: ast::Constness::Const, .. }
, _
, _
, _
) => {
1340 gate_feature_post
!(&self, const_fn
, span
, "const fn is unstable");
1343 // stability of const fn methods are covered in
1344 // visit_trait_item and visit_impl_item below; this is
1345 // because default methods don't pass through this
1351 FnKind
::ItemFn(_
, _
, _
, _
, abi
, _
, _
) |
1352 FnKind
::Method(_
, &ast
::MethodSig { abi, .. }
, _
, _
) => {
1353 self.check_abi(abi
, span
);
1357 visit
::walk_fn(self, fn_kind
, fn_decl
, span
);
1360 fn visit_trait_item(&mut self, ti
: &'a ast
::TraitItem
) {
1362 ast
::TraitItemKind
::Const(..) => {
1363 gate_feature_post
!(&self, associated_consts
,
1365 "associated constants are experimental")
1367 ast
::TraitItemKind
::Method(ref sig
, ref block
) => {
1368 if block
.is_none() {
1369 self.check_abi(sig
.abi
, ti
.span
);
1371 if sig
.constness
.node
== ast
::Constness
::Const
{
1372 gate_feature_post
!(&self, const_fn
, ti
.span
, "const fn is unstable");
1375 ast
::TraitItemKind
::Type(_
, Some(_
)) => {
1376 gate_feature_post
!(&self, associated_type_defaults
, ti
.span
,
1377 "associated type defaults are unstable");
1381 visit
::walk_trait_item(self, ti
);
1384 fn visit_impl_item(&mut self, ii
: &'a ast
::ImplItem
) {
1385 if ii
.defaultness
== ast
::Defaultness
::Default
{
1386 gate_feature_post
!(&self, specialization
,
1388 "specialization is unstable");
1392 ast
::ImplItemKind
::Const(..) => {
1393 gate_feature_post
!(&self, associated_consts
,
1395 "associated constants are experimental")
1397 ast
::ImplItemKind
::Method(ref sig
, _
) => {
1398 if sig
.constness
.node
== ast
::Constness
::Const
{
1399 gate_feature_post
!(&self, const_fn
, ii
.span
, "const fn is unstable");
1404 visit
::walk_impl_item(self, ii
);
1407 fn visit_vis(&mut self, vis
: &'a ast
::Visibility
) {
1408 let span
= match *vis
{
1409 ast
::Visibility
::Crate(span
) => span
,
1410 ast
::Visibility
::Restricted { ref path, .. }
=> path
.span
,
1413 gate_feature_post
!(&self, pub_restricted
, span
, "`pub(restricted)` syntax is experimental");
1415 visit
::walk_vis(self, vis
)
1418 fn visit_generics(&mut self, g
: &'a ast
::Generics
) {
1419 for t
in &g
.ty_params
{
1420 if !t
.attrs
.is_empty() {
1421 gate_feature_post
!(&self, generic_param_attrs
, t
.attrs
[0].span
,
1422 "attributes on type parameter bindings are experimental");
1425 visit
::walk_generics(self, g
)
1428 fn visit_lifetime_def(&mut self, lifetime_def
: &'a ast
::LifetimeDef
) {
1429 if !lifetime_def
.attrs
.is_empty() {
1430 gate_feature_post
!(&self, generic_param_attrs
, lifetime_def
.attrs
[0].span
,
1431 "attributes on lifetime bindings are experimental");
1433 visit
::walk_lifetime_def(self, lifetime_def
)
1437 pub fn get_features(span_handler
: &Handler
, krate_attrs
: &[ast
::Attribute
]) -> Features
{
1438 let mut features
= Features
::new();
1440 let mut feature_checker
= MutexFeatureChecker
::default();
1442 for attr
in krate_attrs
{
1443 if !attr
.check_name("feature") {
1447 match attr
.meta_item_list() {
1449 span_err
!(span_handler
, attr
.span
, E0555
,
1450 "malformed feature attribute, expected #![feature(...)]");
1454 let name
= if let Some(word
) = mi
.word() {
1457 span_err
!(span_handler
, mi
.span
, E0556
,
1458 "malformed feature, expected just one word");
1462 if let Some(&(_
, _
, _
, setter
)) = ACTIVE_FEATURES
.iter()
1463 .find(|& &(n
, _
, _
, _
)| name
== n
) {
1464 *(setter(&mut features
)) = true;
1465 feature_checker
.collect(&features
, mi
.span
);
1467 else if let Some(&(_
, _
, _
)) = REMOVED_FEATURES
.iter()
1468 .find(|& &(n
, _
, _
)| name
== n
)
1469 .or_else(|| STABLE_REMOVED_FEATURES
.iter()
1470 .find(|& &(n
, _
, _
)| name
== n
)) {
1471 span_err
!(span_handler
, mi
.span
, E0557
, "feature has been removed");
1473 else if let Some(&(_
, _
, _
)) = ACCEPTED_FEATURES
.iter()
1474 .find(|& &(n
, _
, _
)| name
== n
) {
1475 features
.declared_stable_lang_features
.push((name
, mi
.span
));
1477 features
.declared_lib_features
.push((name
, mi
.span
));
1484 feature_checker
.check(span_handler
);
1489 // A collector for mutually-exclusive features and their flag spans
1491 struct MutexFeatureChecker
{
1492 proc_macro
: Option
<Span
>,
1493 custom_attribute
: Option
<Span
>,
1496 impl MutexFeatureChecker
{
1497 // If this method turns out to be a hotspot due to branching,
1498 // the branching can be eliminated by modifying `setter!()` to set these spans
1499 // only for the features that need to be checked for mutual exclusion.
1500 fn collect(&mut self, features
: &Features
, span
: Span
) {
1501 if features
.proc_macro
{
1502 // If self.proc_macro is None, set to Some(span)
1503 self.proc_macro
= self.proc_macro
.or(Some(span
));
1506 if features
.custom_attribute
{
1507 self.custom_attribute
= self.custom_attribute
.or(Some(span
));
1511 fn check(self, handler
: &Handler
) {
1512 if let (Some(pm_span
), Some(ca_span
)) = (self.proc_macro
, self.custom_attribute
) {
1513 handler
.struct_span_err(pm_span
, "Cannot use `#![feature(proc_macro)]` and \
1514 `#![feature(custom_attribute)] at the same time")
1515 .span_note(ca_span
, "`#![feature(custom_attribute)]` declared here")
1523 pub fn check_crate(krate
: &ast
::Crate
,
1525 features
: &Features
,
1526 plugin_attributes
: &[(String
, AttributeType
)],
1527 unstable
: UnstableFeatures
) {
1528 maybe_stage_features(&sess
.span_diagnostic
, krate
, unstable
);
1533 plugin_attributes
: plugin_attributes
,
1535 visit
::walk_crate(&mut PostExpansionVisitor { context: &ctx }
, krate
);
1538 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1539 pub enum UnstableFeatures
{
1540 /// Hard errors for unstable features are active, as on
1541 /// beta/stable channels.
1543 /// Allow features to be activated, as on nightly.
1545 /// Errors are bypassed for bootstrapping. This is required any time
1546 /// during the build that feature-related lints are set to warn or above
1547 /// because the build turns on warnings-as-errors and uses lots of unstable
1548 /// features. As a result, this is always required for building Rust itself.
1552 impl UnstableFeatures
{
1553 pub fn from_environment() -> UnstableFeatures
{
1554 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1555 let disable_unstable_features
= option_env
!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1556 // Whether we should enable unstable features for bootstrapping
1557 let bootstrap
= env
::var("RUSTC_BOOTSTRAP").is_ok();
1558 match (disable_unstable_features
, bootstrap
) {
1559 (_
, true) => UnstableFeatures
::Cheat
,
1560 (true, _
) => UnstableFeatures
::Disallow
,
1561 (false, _
) => UnstableFeatures
::Allow
1565 pub fn is_nightly_build(&self) -> bool
{
1567 UnstableFeatures
::Allow
| UnstableFeatures
::Cheat
=> true,
1573 fn maybe_stage_features(span_handler
: &Handler
, krate
: &ast
::Crate
,
1574 unstable
: UnstableFeatures
) {
1575 let allow_features
= match unstable
{
1576 UnstableFeatures
::Allow
=> true,
1577 UnstableFeatures
::Disallow
=> false,
1578 UnstableFeatures
::Cheat
=> true
1580 if !allow_features
{
1581 for attr
in &krate
.attrs
{
1582 if attr
.check_name("feature") {
1583 let release_channel
= option_env
!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1584 span_err
!(span_handler
, attr
.span
, E0554
,
1585 "#[feature] may not be used on the {} release channel",