feature_gate.rs 89.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Feature gating
//!
L
Luke Gallagher 已提交
13
//! This module implements the gating necessary for preventing certain compiler
14 15 16 17 18
//! features from being used by default. This module will crawl a pre-expanded
//! AST to ensure that there are no features which are used that are not
//! enabled.
//!
//! Features are enabled in programs via the crate-level attributes of
19
//! `#![feature(...)]` with a comma-separated list of features.
B
Brian Anderson 已提交
20 21 22 23
//!
//! For the purpose of future feature-tracking, once code for detection of feature
//! gate usage is added, *do not remove it again* even once the feature
//! becomes stable.
G
GuillaumeGomez 已提交
24

25
use self::AttributeType::*;
26
use self::AttributeGate::*;
27

28
use rustc_data_structures::fx::FxHashMap;
29
use rustc_target::spec::abi::Abi;
30
use ast::{self, NodeId, PatKind, RangeEnd};
31
use attr;
D
Donato Sciarra 已提交
32
use source_map::Spanned;
33
use edition::{ALL_EDITIONS, Edition};
34
use syntax_pos::{Span, DUMMY_SP};
35
use errors::{DiagnosticBuilder, Handler};
36
use visit::{self, FnKind, Visitor};
J
Jeffrey Seyfried 已提交
37
use parse::ParseSess;
V
Vadim Petrochenkov 已提交
38
use symbol::{keywords, Symbol};
39

40
use std::{env, path};
41

42
macro_rules! set {
43
    ($field: ident) => {{
44 45
        fn f(features: &mut Features, _: Span) {
            features.$field = true;
46
        }
47
        f as fn(&mut Features, Span)
48 49
    }}
}
50

51
macro_rules! declare_features {
K
Kurtis Nusbaum 已提交
52
    ($((active, $feature: ident, $ver: expr, $issue: expr, $edition: expr),)+) => {
53 54
        /// Represents active features that are currently being implemented or
        /// currently being considered for addition/removal.
55
        const ACTIVE_FEATURES:
56
                &'static [(&'static str, &'static str, Option<u32>,
K
Kurtis Nusbaum 已提交
57 58
                           Option<Edition>, fn(&mut Features, Span))] =
            &[$((stringify!($feature), $ver, $issue, $edition, set!($feature))),+];
59 60

        /// A set of features to be used by later passes.
61
        #[derive(Clone)]
62
        pub struct Features {
V
varkor 已提交
63 64
            /// `#![feature]` attrs for language features, for error reporting
            pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
65
            /// `#![feature]` attrs for non-language (library) features
66
            pub declared_lib_features: Vec<(Symbol, Span)>,
67 68
            $(pub $feature: bool),+
        }
69

70 71 72
        impl Features {
            pub fn new() -> Features {
                Features {
V
varkor 已提交
73
                    declared_lang_features: Vec::new(),
74 75 76 77
                    declared_lib_features: Vec::new(),
                    $($feature: false),+
                }
            }
78 79 80 81 82 83

            pub fn walk_feature_fields<F>(&self, mut f: F)
                where F: FnMut(&str, bool)
            {
                $(f(stringify!($feature), self.$feature);)+
            }
84 85 86
        }
    };

87
    ($((removed, $feature: ident, $ver: expr, $issue: expr, None, $reason: expr),)+) => {
88
        /// Represents unstable features which have since been removed (it was once Active)
89 90
        const REMOVED_FEATURES: &[(&str, &str, Option<u32>, Option<&str>)] = &[
            $((stringify!($feature), $ver, $issue, $reason)),+
91 92 93
        ];
    };

94
    ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => {
95
        /// Represents stable features which have since been removed (it was once Accepted)
96 97
        const STABLE_REMOVED_FEATURES: &[(&str, &str, Option<u32>, Option<&str>)] = &[
            $((stringify!($feature), $ver, $issue, None)),+
98 99 100
        ];
    };

101
    ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => {
102
        /// Those language feature has since been Accepted (it was once Active)
103 104
        const ACCEPTED_FEATURES: &[(&str, &str, Option<u32>, Option<&str>)] = &[
            $((stringify!($feature), $ver, $issue, None)),+
105 106
        ];
    }
107 108
}

S
Steve Klabnik 已提交
109 110
// If you change this, please modify src/doc/unstable-book as well.
//
B
Brian Anderson 已提交
111
// Don't ever remove anything from this list; set them to 'Removed'.
S
Steve Klabnik 已提交
112
//
B
Brian Anderson 已提交
113 114 115
// The version numbers here correspond to the version in which the current status
// was set. This is most important for knowing when a particular feature became
// stable (active).
S
Steve Klabnik 已提交
116
//
117 118
// NB: tools/tidy/src/features.rs parses this information directly out of the
// source, so take care when modifying it.
119 120

declare_features! (
121 122 123 124 125 126 127 128
    (active, asm, "1.0.0", Some(29722), None),
    (active, concat_idents, "1.0.0", Some(29599), None),
    (active, link_args, "1.0.0", Some(29596), None),
    (active, log_syntax, "1.0.0", Some(29598), None),
    (active, non_ascii_idents, "1.0.0", Some(28979), None),
    (active, plugin_registrar, "1.0.0", Some(29597), None),
    (active, thread_local, "1.0.0", Some(29594), None),
    (active, trace_macros, "1.0.0", Some(29598), None),
A
Aaron Turon 已提交
129

A
Alexander Regueiro 已提交
130
    // rustc internal, for now
131 132
    (active, intrinsics, "1.0.0", None, None),
    (active, lang_items, "1.0.0", None, None),
133
    (active, format_args_nl, "1.29.0", None, None),
134

135 136 137
    (active, link_llvm_intrinsics, "1.0.0", Some(29602), None),
    (active, linkage, "1.0.0", Some(29603), None),
    (active, quote, "1.0.0", Some(29601), None),
138

A
Aaron Turon 已提交
139
    // rustc internal
140 141
    (active, rustc_diagnostic_macros, "1.0.0", None, None),
    (active, rustc_const_unstable, "1.0.0", None, None),
142
    (active, box_syntax, "1.0.0", Some(49733), None),
143 144 145 146 147 148 149 150 151 152 153 154
    (active, unboxed_closures, "1.0.0", Some(29625), None),

    (active, fundamental, "1.0.0", Some(29635), None),
    (active, main, "1.0.0", Some(29634), None),
    (active, needs_allocator, "1.4.0", Some(27389), None),
    (active, on_unimplemented, "1.0.0", Some(29628), None),
    (active, plugin, "1.0.0", Some(29597), None),
    (active, simd_ffi, "1.0.0", Some(27731), None),
    (active, start, "1.0.0", Some(29633), None),
    (active, structural_match, "1.8.0", Some(31434), None),
    (active, panic_runtime, "1.10.0", Some(32837), None),
    (active, needs_panic_runtime, "1.10.0", Some(32837), None),
155

156
    // OIBIT specific features
157
    (active, optin_builtin_traits, "1.0.0", Some(13231), None),
158

159
    // Allows use of #[staged_api]
A
Alexander Regueiro 已提交
160
    //
A
Aaron Turon 已提交
161
    // rustc internal
162
    (active, staged_api, "1.0.0", None, None),
163

A
Alex Crichton 已提交
164
    // Allows using #![no_core]
165
    (active, no_core, "1.3.0", Some(29639), None),
A
Alex Crichton 已提交
166

167
    // Allows using `box` in patterns; RFC 469
168
    (active, box_patterns, "1.0.0", Some(29641), None),
169

170 171
    // Allows using the unsafe_destructor_blind_to_params attribute;
    // RFC 1238
172
    (active, dropck_parametricity, "1.3.0", Some(28498), None),
173

174
    // Allows using the may_dangle attribute; RFC 1327
175
    (active, dropck_eyepatch, "1.10.0", Some(34761), None),
176

177
    // Allows the use of custom attributes; RFC 572
178
    (active, custom_attribute, "1.0.0", Some(29642), None),
M
Manish Goregaokar 已提交
179

180 181
    // Allows the use of #[derive(Anything)] as sugar for
    // #[derive_Anything].
182
    (active, custom_derive, "1.0.0", Some(29644), None),
183

M
Manish Goregaokar 已提交
184
    // Allows the use of rustc_* attributes; RFC 572
185
    (active, rustc_attrs, "1.0.0", Some(29642), None),
H
Huon Wilson 已提交
186

187
    // Allows the use of non lexical lifetimes; RFC 2094
188
    (active, nll, "1.0.0", Some(43234), None),
189

190 191 192 193
    // Allows the use of #[allow_internal_unstable]. This is an
    // attribute on macro_rules! and can't use the attribute handling
    // below (it has to be checked before expansion possibly makes
    // macros disappear).
A
Aaron Turon 已提交
194 195
    //
    // rustc internal
196
    (active, allow_internal_unstable, "1.0.0", None, None),
197

198 199 200 201 202 203
    // Allows the use of #[allow_internal_unsafe]. This is an
    // attribute on macro_rules! and can't use the attribute handling
    // below (it has to be checked before expansion possibly makes
    // macros disappear).
    //
    // rustc internal
204
    (active, allow_internal_unsafe, "1.0.0", None, None),
205

206
    // #23121. Array patterns have some hazards yet.
207
    (active, slice_patterns, "1.0.0", Some(23121), None),
208

N
Niko Matsakis 已提交
209
    // Allows the definition of `const fn` functions.
210
    (active, const_fn, "1.2.0", Some(24111), None),
211

212 213 214
    // Allows let bindings and destructuring in `const fn` functions and constants.
    (active, const_let, "1.22.1", Some(48821), None),

215 216 217 218 219 220 221 222 223
    // Allows accessing fields of unions inside const fn
    (active, const_fn_union, "1.27.0", Some(51909), None),

    // Allows casting raw pointers to `usize` during const eval
    (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),

    // Allows dereferencing raw pointers during const eval
    (active, const_raw_ptr_deref, "1.27.0", Some(51911), None),

224 225 226
    // Allows comparing raw pointers during const eval
    (active, const_compare_raw_pointers, "1.27.0", Some(53020), None),

227
    // Allows panicking during const eval (produces compile-time errors)
228
    (active, const_panic, "1.30.0", Some(51999), None),
229

230
    // Allows using #[prelude_import] on glob `use` items.
A
Aaron Turon 已提交
231 232
    //
    // rustc internal
233
    (active, prelude_import, "1.2.0", None, None),
234

B
Brian Anderson 已提交
235
    // Allows default type parameters to influence type inference.
236
    (active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
237 238

    // Allows associated type defaults
239
    (active, associated_type_defaults, "1.2.0", Some(29661), None),
J
Jared Roesch 已提交
240

A
Alexander Regueiro 已提交
241
    // Allows `repr(simd)`, and importing the various simd intrinsics
242
    (active, repr_simd, "1.4.0", Some(27731), None),
243

A
Alexander Regueiro 已提交
244
    // Allows `extern "platform-intrinsic" { ... }`
245
    (active, platform_intrinsics, "1.4.0", Some(27731), None),
246

A
Alexander Regueiro 已提交
247
    // Allows `#[unwind(..)]`
248
    // rustc internal for rust runtime
249
    (active, unwind_attributes, "1.4.0", None, None),
V
Vadim Petrochenkov 已提交
250

A
Alexander Regueiro 已提交
251
    // Allows the use of `#[naked]` on functions.
252
    (active, naked_functions, "1.9.0", Some(32408), None),
253

A
Alexander Regueiro 已提交
254
    // Allows `#[no_debug]`
255
    (active, no_debug, "1.5.0", Some(29721), None),
256

A
Alexander Regueiro 已提交
257 258 259
    // Allows `#[omit_gdb_pretty_printer_section]`
    //
    // rustc internal
260
    (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
261 262

    // Allows cfg(target_vendor = "...").
263
    (active, cfg_target_vendor, "1.5.0", Some(29718), None),
264 265

    // Allow attributes on expressions and non-item statements
266
    (active, stmt_expr_attributes, "1.6.0", Some(15701), None),
267 268

    // allow using type ascription in expressions
269
    (active, type_ascription, "1.6.0", Some(23416), None),
270 271

    // Allows cfg(target_thread_local)
272
    (active, cfg_target_thread_local, "1.7.0", Some(29594), None),
273 274

    // rustc internal
275
    (active, abi_vectorcall, "1.7.0", None, None),
A
Alex Burka 已提交
276

277
    // X..Y patterns
278
    (active, exclusive_range_pattern, "1.11.0", Some(37854), None),
279

A
Aaron Turon 已提交
280
    // impl specialization (RFC 1210)
281
    (active, specialization, "1.7.0", Some(31844), None),
282

283
    // Allows cfg(target_has_atomic = "...").
284
    (active, cfg_target_has_atomic, "1.9.0", Some(32976), None),
285

286 287 288
    // The `!` type. Does not imply exhaustive_patterns (below) any more.
    (active, never_type, "1.13.0", Some(35121), None),

A
Alexander Regueiro 已提交
289
    // Allows exhaustive pattern matching on types that contain uninhabited types
290
    (active, exhaustive_patterns, "1.13.0", Some(51085), None),
291

292
    // Allows untagged unions `union U { ... }`
293
    (active, untagged_unions, "1.13.0", Some(32836), None),
A
Andre Bogus 已提交
294

295 296
    // Used to identify the `compiler_builtins` crate
    // rustc internal
297
    (active, compiler_builtins, "1.13.0", None, None),
298

299
    // Allows #[link(..., cfg(..))]
300
    (active, link_cfg, "1.14.0", Some(37406), None),
301

J
Jorge Aparicio 已提交
302
    // `extern "ptx-*" fn()`
303
    (active, abi_ptx, "1.15.0", Some(38788), None),
304

305
    // The `repr(i128)` annotation for enums
306
    (active, repr128, "1.16.0", Some(35118), None),
307

308
    // The `unadjusted` ABI. Perma unstable.
309
    // rustc internal
310
    (active, abi_unadjusted, "1.16.0", None, None),
311

312
    // Declarative macros 2.0 (`macro`).
313
    (active, decl_macro, "1.17.0", Some(39412), None),
314

T
Taylor Cramer 已提交
315
    // Allows #[link(kind="static-nobundle"...)]
316
    (active, static_nobundle, "1.16.0", Some(37403), None),
V
Vadim Chugunov 已提交
317

318
    // `extern "msp430-interrupt" fn()`
319
    (active, abi_msp430_interrupt, "1.16.0", Some(38487), None),
J
Jorge Aparicio 已提交
320 321 322

    // Used to identify crates that contain sanitizer runtimes
    // rustc internal
323
    (active, sanitizer_runtime, "1.17.0", None, None),
324

325
    // Used to identify crates that contain the profiler runtime
A
Alexander Regueiro 已提交
326
    //
327
    // rustc internal
328
    (active, profiler_runtime, "1.18.0", None, None),
329

330
    // `extern "x86-interrupt" fn()`
331
    (active, abi_x86_interrupt, "1.17.0", Some(40180), None),
J
Jorge Aparicio 已提交
332

333
    // Allows the `try {...}` expression
334
    (active, try_blocks, "1.29.0", Some(31436), None),
335

336
    // Used to preserve symbols (see llvm.used)
337
    (active, used, "1.18.0", Some(40289), None),
338

339
    // Allows module-level inline assembly by way of global_asm!()
340
    (active, global_asm, "1.18.0", Some(35119), None),
341 342

    // Allows overlapping impls of marker traits
343
    (active, overlapping_marker_traits, "1.18.0", Some(29864), None),
344

345
    // rustc internal
346
    (active, abi_thiscall, "1.19.0", None, None),
347 348

    // Allows a test to fail without failing the whole suite
349
    (active, allow_fail, "1.19.0", Some(42219), None),
350 351

    // Allows unsized tuple coercion.
352
    (active, unsized_tuple_coercion, "1.20.0", Some(42877), None),
353

J
John Kåre Alsaker 已提交
354
    // Generators
355
    (active, generators, "1.21.0", Some(43122), None),
J
John Kåre Alsaker 已提交
356

A
Alex Burka 已提交
357
    // Trait aliases
358
    (active, trait_alias, "1.24.0", Some(41517), None),
J
John Kåre Alsaker 已提交
359

360
    // rustc internal
361
    (active, allocator_internals, "1.20.0", None, None),
K
kennytm 已提交
362 363

    // #[doc(cfg(...))]
364
    (active, doc_cfg, "1.21.0", Some(43781), None),
365
    // #[doc(masked)]
366
    (active, doc_masked, "1.21.0", Some(44027), None),
367
    // #[doc(spotlight)]
368
    (active, doc_spotlight, "1.22.0", Some(45040), None),
369
    // #[doc(include="some-file")]
370
    (active, external_doc, "1.22.0", Some(44732), None),
371

D
David Wood 已提交
372
    // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
373
    (active, non_exhaustive, "1.22.0", Some(44109), None),
D
David Wood 已提交
374

375
    // `crate` as visibility modifier, synonymous to `pub(crate)`
376
    (active, crate_visibility_modifier, "1.23.0", Some(45388), Some(Edition::Edition2018)),
P
Paul Lietar 已提交
377 378

    // extern types
379
    (active, extern_types, "1.23.0", Some(43467), None),
380

A
Alexander Regueiro 已提交
381
    // Allows trait methods with arbitrary self types
382
    (active, arbitrary_self_types, "1.23.0", Some(44874), None),
383

V
Vadim Petrochenkov 已提交
384
    // `crate` in paths
385
    (active, crate_in_paths, "1.23.0", Some(45477), Some(Edition::Edition2018)),
386 387

    // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`)
388
    (active, in_band_lifetimes, "1.23.0", Some(44524), None),
389

A
Alexander Regueiro 已提交
390
    // Generic associated types (RFC 1598)
391
    (active, generic_associated_types, "1.23.0", Some(44265), None),
392 393

    // Resolve absolute paths as paths from other crates
394
    (active, extern_absolute_paths, "1.24.0", Some(44660), Some(Edition::Edition2018)),
395 396

    // `foo.rs` as an alternative to `foo/mod.rs`
397
    (active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)),
398

V
Vadim Petrochenkov 已提交
399
    // `extern` in paths
400
    (active, extern_in_paths, "1.23.0", Some(44660), None),
R
Robin Kruppe 已提交
401

M
Mark Mansi 已提交
402
    // Use `?` as the Kleene "at most one" operator
403
    (active, macro_at_most_once_rep, "1.25.0", Some(48075), None),
404

405 406 407
    // Infer outlives requirements; RFC 2093
    (active, infer_outlives_requirements, "1.26.0", Some(44493), None),

T
toidiu 已提交
408
    // Infer static outlives requirements; RFC 2093
409 410
    (active, infer_static_outlives_requirements, "1.26.0", Some(44493), None),

411
    // Multiple patterns with `|` in `if let` and `while let`
412
    (active, if_while_or_patterns, "1.26.0", Some(48215), None),
413 414

    // Parentheses in patterns
415
    (active, pattern_parentheses, "1.26.0", Some(51087), None),
416

417 418 419
    // Allows `#[repr(packed)]` attribute on structs
    (active, repr_packed, "1.26.0", Some(33158), None),

420 421
    // `use path as _;` and `extern crate c as _;`
    (active, underscore_imports, "1.26.0", Some(48216), None),
422

423 424
    // Allows macro invocations in `extern {}` blocks
    (active, macros_in_extern, "1.27.0", Some(49476), None),
425

O
Oliver Schneider 已提交
426 427 428
    // `existential type`
    (active, existential_type, "1.28.0", Some(34511), None),

429
    // unstable #[target_feature] directives
430 431 432 433 434 435 436 437 438
    (active, arm_target_feature, "1.27.0", Some(44839), None),
    (active, aarch64_target_feature, "1.27.0", Some(44839), None),
    (active, hexagon_target_feature, "1.27.0", Some(44839), None),
    (active, powerpc_target_feature, "1.27.0", Some(44839), None),
    (active, mips_target_feature, "1.27.0", Some(44839), None),
    (active, avx512_target_feature, "1.27.0", Some(44839), None),
    (active, mmx_target_feature, "1.27.0", Some(44839), None),
    (active, sse4a_target_feature, "1.27.0", Some(44839), None),
    (active, tbm_target_feature, "1.27.0", Some(44839), None),
G
gnzlbg 已提交
439
    (active, wasm_target_feature, "1.30.0", Some(44839), None),
440 441 442

    // Allows macro invocations on modules expressions and statements and
    // procedural macros to expand to non-items.
443 444 445 446
    (active, proc_macro_mod, "1.27.0", Some(38356), None),
    (active, proc_macro_expr, "1.27.0", Some(38356), None),
    (active, proc_macro_non_items, "1.27.0", Some(38356), None),
    (active, proc_macro_gen, "1.27.0", Some(38356), None),
G
Guillaume Gomez 已提交
447 448

    // #[doc(alias = "...")]
449
    (active, doc_alias, "1.27.0", Some(50146), None),
450 451 452

    // Access to crate names passed via `--extern` through prelude
    (active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)),
F
flip1995 已提交
453

F
flip1995 已提交
454 455
    // Scoped lints
    (active, tool_lints, "1.28.0", Some(44690), None),
456

A
Alexander Regueiro 已提交
457
    // Allows irrefutable patterns in if-let and while-let statements (RFC 2086)
458
    (active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
459

460 461
    // Allows use of the :literal macro fragment specifier (RFC 1576)
    (active, macro_literal_matcher, "1.27.0", Some(35625), None),
M
Matthew Jasper 已提交
462 463 464

    // inconsistent bounds in where clauses
    (active, trivial_bounds, "1.28.0", Some(48214), None),
E
est31 已提交
465 466 467

    // 'a: { break 'a; }
    (active, label_break_value, "1.28.0", Some(48594), None),
468

V
varkor 已提交
469
    // Integer match exhaustiveness checking
V
varkor 已提交
470
    (active, exhaustive_integer_patterns, "1.30.0", Some(50907), None),
V
varkor 已提交
471

472 473
    // #[panic_implementation]
    (active, panic_implementation, "1.28.0", Some(44489), None),
474 475 476

    // #[doc(keyword = "...")]
    (active, doc_keyword, "1.28.0", Some(51315), None),
W
Without Boats 已提交
477 478

    // Allows async and await syntax
T
Taylor Cramer 已提交
479
    (active, async_await, "1.28.0", Some(50547), None),
S
Simon Sapin 已提交
480 481 482

    // #[alloc_error_handler]
    (active, alloc_error_handler, "1.29.0", Some(51540), None),
R
Richard Diamond 已提交
483 484

    (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None),
485 486 487 488

    // impl<I:Iterator> Iterator for &mut Iterator
    // impl Debug for Foo<'_>
    (active, impl_header_lifetime_elision, "1.30.0", Some(15872), Some(Edition::Edition2018)),
489

A
Alexander Regueiro 已提交
490
    // Support for arbitrary delimited token streams in non-macro attributes
491
    (active, unrestricted_attribute_tokens, "1.30.0", Some(44690), None),
492

A
Alexander Regueiro 已提交
493
    // Allows `use x::y;` to resolve through `self::x`, not just `::x`
494
    (active, uniform_paths, "1.30.0", Some(53130), None),
A
Alexander Regueiro 已提交
495 496 497

    // Allows `Self` in type definitions
    (active, self_in_typedefs, "1.30.0", Some(49303), None),
M
Masaki Hara 已提交
498 499 500

    // unsized rvalues at arguments and parameters
    (active, unsized_locals, "1.30.0", Some(48055), None),
501 502 503
);

declare_features! (
504 505
    (removed, import_shadowing, "1.0.0", None, None, None),
    (removed, managed_boxes, "1.0.0", None, None, None),
506
    // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
507 508
    (removed, negate_unsigned, "1.0.0", Some(29645), None, None),
    (removed, reflect, "1.0.0", Some(27749), None, None),
509
    // A way to temporarily opt out of opt in copy. This will *never* be accepted.
510 511 512 513 514 515
    (removed, opt_out_copy, "1.0.0", None, None, None),
    (removed, quad_precision_float, "1.0.0", None, None, None),
    (removed, struct_inherit, "1.0.0", None, None, None),
    (removed, test_removed_feature, "1.0.0", None, None, None),
    (removed, visible_private_types, "1.0.0", None, None, None),
    (removed, unsafe_no_drop_flag, "1.0.0", None, None, None),
516 517
    // Allows using items which are missing stability attributes
    // rustc internal
518 519 520 521 522 523 524 525
    (removed, unmarked_api, "1.0.0", None, None, None),
    (removed, pushpop_unsafe, "1.2.0", None, None, None),
    (removed, allocator, "1.0.0", None, None, None),
    (removed, simd, "1.0.0", Some(27731), None,
     Some("removed in favor of `#[repr(simd)]`")),
    (removed, advanced_slice_patterns, "1.0.0", Some(23121), None,
     Some("merged into `#![feature(slice_patterns)]`")),
    (removed, macro_reexport, "1.0.0", Some(29638), None,
526
     Some("subsumed by `pub use`")),
527 528
);

529
declare_features! (
530
    (stable_removed, no_stack_check, "1.0.0", None, None),
531 532 533
);

declare_features! (
534
    (accepted, associated_types, "1.0.0", None, None),
535
    // allow overloading augmented assignment operations like `a += b`
536
    (accepted, augmented_assignments, "1.8.0", Some(28235), None),
537
    // allow empty structs and enum variants with braces
538
    (accepted, braced_empty_structs, "1.8.0", Some(29720), None),
539
    // Allows indexing into constant arrays.
540
    (accepted, const_indexing, "1.26.0", Some(29947), None),
541 542 543
    (accepted, default_type_params, "1.0.0", None, None),
    (accepted, globs, "1.0.0", None, None),
    (accepted, if_let, "1.0.0", None, None),
544 545
    // A temporary feature gate used to enable parser extensions needed
    // to bootstrap fix for #5723.
546 547
    (accepted, issue_5723_bootstrap, "1.0.0", None, None),
    (accepted, macro_rules, "1.0.0", None, None),
548
    // Allows using #![no_std]
549 550 551
    (accepted, no_std, "1.6.0", None, None),
    (accepted, slicing_syntax, "1.0.0", None, None),
    (accepted, struct_variant, "1.0.0", None, None),
552 553
    // These are used to test this portion of the compiler, they don't actually
    // mean anything
554 555
    (accepted, test_accepted_feature, "1.0.0", None, None),
    (accepted, tuple_indexing, "1.0.0", None, None),
D
Daniele Baracchi 已提交
556
    // Allows macros to appear in the type position.
557 558
    (accepted, type_macros, "1.13.0", Some(27245), None),
    (accepted, while_let, "1.0.0", None, None),
559
    // Allows `#[deprecated]` attribute
560
    (accepted, deprecated, "1.9.0", Some(29935), None),
N
Nick Cameron 已提交
561
    // `expr?`
562
    (accepted, question_mark, "1.13.0", Some(31436), None),
563
    // Allows `..` in tuple (struct) patterns
564 565
    (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None),
    (accepted, item_like_imports, "1.15.0", Some(35120), None),
566
    // Allows using `Self` and associated types in struct expressions and patterns.
567
    (accepted, more_struct_aliases, "1.16.0", Some(37544), None),
E
est31 已提交
568
    // elide `'static` lifetimes in `static`s and `const`s
569
    (accepted, static_in_const, "1.17.0", Some(35897), None),
E
est31 已提交
570
    // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
571
    (accepted, field_init_shorthand, "1.17.0", Some(37340), None),
T
Taylor Cramer 已提交
572
    // Allows the definition recursive static items.
573
    (accepted, static_recursion, "1.17.0", Some(29719), None),
T
Taylor Cramer 已提交
574
    // pub(restricted) visibilities (RFC 1422)
575
    (accepted, pub_restricted, "1.18.0", Some(32409), None),
576
    // The #![windows_subsystem] attribute
577
    (accepted, windows_subsystem, "1.18.0", Some(37499), None),
578
    // Allows `break {expr}` with a value inside `loop`s.
579
    (accepted, loop_break_value, "1.19.0", Some(37339), None),
580
    // Permits numeric fields in struct expressions and patterns.
581
    (accepted, relaxed_adts, "1.19.0", Some(35626), None),
M
Cleanup  
Matt Peterson 已提交
582
    // Coerces non capturing closures to function pointers
583
    (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
584
    // Allows attributes on struct literal fields.
585
    (accepted, struct_field_attributes, "1.20.0", Some(38814), None),
586 587
    // Allows the definition of associated constants in `trait` or `impl`
    // blocks.
588
    (accepted, associated_consts, "1.20.0", Some(29646), None),
589
    // Usage of the `compile_error!` macro
590
    (accepted, compile_error, "1.20.0", Some(40872), None),
591
    // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
592
    (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None),
593
    // Allow Drop types in constants (RFC 1440)
594
    (accepted, drop_types_in_const, "1.22.0", Some(33156), None),
C
CensoredUsername 已提交
595 596
    // Allows the sysV64 ABI to be specified on all platforms
    // instead of just the platforms on which it is the C ABI
597
    (accepted, abi_sysv64, "1.24.0", Some(36167), None),
598
    // Allows `repr(align(16))` struct attribute (RFC 1358)
599
    (accepted, repr_align, "1.25.0", Some(33626), None),
600
    // allow '|' at beginning of match arms (RFC 1925)
601
    (accepted, match_beginning_vert, "1.25.0", Some(44101), None),
P
Pietro Albini 已提交
602
    // Nested groups in `use` (RFC 2128)
603
    (accepted, use_nested_groups, "1.25.0", Some(44494), None),
604 605
    // a..=b and ..=b
    (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None),
606 607
    // allow `..=` in patterns (RFC 1192)
    (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None),
608 609
    // Termination trait in main (RFC 1937)
    (accepted, termination_trait, "1.26.0", Some(43301), None),
610 611 612
    // Copy/Clone closures (RFC 2132)
    (accepted, clone_closures, "1.26.0", Some(44490), None),
    (accepted, copy_closures, "1.26.0", Some(44490), None),
T
Taylor Cramer 已提交
613 614
    // Allows `impl Trait` in function arguments.
    (accepted, universal_impl_trait, "1.26.0", Some(34511), None),
615 616
    // Allows `impl Trait` in function return types.
    (accepted, conservative_impl_trait, "1.26.0", Some(34511), None),
M
Mark Mansi 已提交
617 618
    // The `i128` type
    (accepted, i128_type, "1.26.0", Some(35118), None),
T
Taylor Cramer 已提交
619 620
    // Default match binding modes (RFC 2005)
    (accepted, match_default_bindings, "1.26.0", Some(42640), None),
T
Taylor Cramer 已提交
621 622
    // allow `'_` placeholder lifetimes
    (accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
623
    // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
624
    (accepted, generic_param_attrs, "1.27.0", Some(48848), None),
A
Alex Crichton 已提交
625 626 627 628
    // Allows cfg(target_feature = "...").
    (accepted, cfg_target_feature, "1.27.0", Some(29717), None),
    // Allows #[target_feature(...)]
    (accepted, target_feature, "1.27.0", None, None),
629
    // Trait object syntax with `dyn` prefix
630
    (accepted, dyn_trait, "1.27.0", Some(44662), None),
631 632
    // allow `#[must_use]` on functions; and, must-use operators (RFC 1940)
    (accepted, fn_must_use, "1.27.0", Some(43302), None),
A
Alex Burka 已提交
633 634
    // Allows use of the :lifetime macro fragment specifier
    (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None),
D
dylan_DPC 已提交
635
    // Termination trait in tests (RFC 1937)
D
dylan_DPC 已提交
636
    (accepted, termination_trait_test, "1.27.0", Some(48854), None),
637 638
    // The #[global_allocator] attribute
    (accepted, global_allocator, "1.28.0", Some(27389), None),
S
Simon Sapin 已提交
639 640
    // Allows `#[repr(transparent)]` attribute on newtype structs
    (accepted, repr_transparent, "1.28.0", Some(43036), None),
641 642
    // Defining procedural macros in `proc-macro` crates
    (accepted, proc_macro, "1.29.0", Some(38356), None),
J
Jakub Kozlowski 已提交
643 644
    // Allows use of the :vis macro fragment specifier
    (accepted, macro_vis_matcher, "1.29.0", Some(41022), None),
645 646 647
    // Allows importing and reexporting macros with `use`,
    // enables macro modularization in general.
    (accepted, use_extern_macros, "1.30.0", Some(35896), None),
648 649
    // Allows keywords to be escaped for use as identifiers
    (accepted, raw_identifiers, "1.30.0", Some(48589), None),
650 651 652 653
    // Attributes scoped to tools
    (accepted, tool_attributes, "1.30.0", Some(44690), None),
    // Allows multi-segment paths in attributes and derives
    (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None),
654 655
    // Allows all literals in attribute lists and values of key-value pairs.
    (accepted, attr_literals, "1.30.0", Some(34981), None),
656
);
657

S
Steve Klabnik 已提交
658 659 660
// If you change this, please modify src/doc/unstable-book as well. You must
// move that documentation into the relevant place in the other docs, and
// remove the chapter on the flag.
661

662
#[derive(Copy, Clone, PartialEq, Debug)]
663 664 665 666
pub enum AttributeType {
    /// Normal, builtin attribute that is consumed
    /// by the compiler before the unused_attribute check
    Normal,
667

668 669 670 671
    /// Builtin attribute that may not be consumed by the compiler
    /// before the unused_attribute check. These attributes
    /// will be ignored by the unused_attribute lint
    Whitelisted,
672

673 674 675 676 677 678 679
    /// Builtin attribute that is only allowed at the crate level
    CrateLevel,
}

pub enum AttributeGate {
    /// Is gated by a given feature gate, reason
    /// and function to check if enabled
680
    Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
681 682 683 684 685

    /// Ungated attribute, can be used on all release channels
    Ungated,
}

N
Nick Cameron 已提交
686 687 688 689 690 691 692 693 694
impl AttributeGate {
    fn is_deprecated(&self) -> bool {
        match *self {
            Gated(Stability::Deprecated(_), ..) => true,
            _ => false,
        }
    }
}

695
#[derive(Copy, Clone, Debug)]
696 697
pub enum Stability {
    Unstable,
N
Nick Cameron 已提交
698 699
    // Argument is tracking issue link.
    Deprecated(&'static str),
700 701
}

702 703 704 705
// fn() is not Debug
impl ::std::fmt::Debug for AttributeGate {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
706
            Gated(ref stab, name, expl, _) =>
N
Nick Cameron 已提交
707
                write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
708 709 710 711 712 713 714 715 716 717 718 719
            Ungated => write!(fmt, "Ungated")
        }
    }
}

macro_rules! cfg_fn {
    ($field: ident) => {{
        fn f(features: &Features) -> bool {
            features.$field
        }
        f as fn(&Features) -> bool
    }}
720 721
}

N
Nick Cameron 已提交
722
pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
723
    BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
N
Nick Cameron 已提交
724 725
}

726 727 728 729
pub fn is_builtin_attr_name(name: ast::Name) -> bool {
    BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| name == builtin_name)
}

730
pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
731
    BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name)
732 733
}

734
// Attributes that have a special meaning to rustc or rustdoc
735
pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
736 737
    // Normal attributes

738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
    ("warn", Normal, Ungated),
    ("allow", Normal, Ungated),
    ("forbid", Normal, Ungated),
    ("deny", Normal, Ungated),

    ("macro_use", Normal, Ungated),
    ("macro_export", Normal, Ungated),
    ("plugin_registrar", Normal, Ungated),

    ("cfg", Normal, Ungated),
    ("cfg_attr", Normal, Ungated),
    ("main", Normal, Ungated),
    ("start", Normal, Ungated),
    ("test", Normal, Ungated),
    ("bench", Normal, Ungated),
    ("repr", Normal, Ungated),
    ("path", Normal, Ungated),
    ("abi", Normal, Ungated),
    ("automatically_derived", Normal, Ungated),
    ("no_mangle", Normal, Ungated),
    ("no_link", Normal, Ungated),
    ("derive", Normal, Ungated),
    ("should_panic", Normal, Ungated),
    ("ignore", Normal, Ungated),
    ("no_implicit_prelude", Normal, Ungated),
    ("reexport_test_harness_main", Normal, Ungated),
764 765 766 767 768 769
    ("link_args", Normal, Gated(Stability::Unstable,
                                "link_args",
                                "the `link_args` attribute is experimental and not \
                                 portable across platforms, it is recommended to \
                                 use `#[link(name = \"foo\")] instead",
                                cfg_fn!(link_args))),
770
    ("macro_escape", Normal, Ungated),
771

772
    // RFC #1445.
773 774
    ("structural_match", Whitelisted, Gated(Stability::Unstable,
                                            "structural_match",
775
                                            "the semantics of constant patterns is \
776 777
                                             not yet settled",
                                            cfg_fn!(structural_match))),
778

D
David Wood 已提交
779 780 781 782 783 784
    // RFC #2008
    ("non_exhaustive", Whitelisted, Gated(Stability::Unstable,
                                          "non_exhaustive",
                                          "non exhaustive is an experimental feature",
                                          cfg_fn!(non_exhaustive))),

785 786
    ("plugin", CrateLevel, Gated(Stability::Unstable,
                                 "plugin",
787
                                 "compiler plugins are experimental \
788 789 790
                                  and possibly buggy",
                                 cfg_fn!(plugin))),

791
    ("no_std", CrateLevel, Ungated),
792 793
    ("no_core", CrateLevel, Gated(Stability::Unstable,
                                  "no_core",
794 795
                                  "no_core is experimental",
                                  cfg_fn!(no_core))),
796 797
    ("lang", Normal, Gated(Stability::Unstable,
                           "lang_items",
798 799
                           "language items are subject to change",
                           cfg_fn!(lang_items))),
800 801
    ("linkage", Whitelisted, Gated(Stability::Unstable,
                                   "linkage",
802
                                   "the `linkage` attribute is experimental \
803 804
                                    and not portable across platforms",
                                   cfg_fn!(linkage))),
805 806
    ("thread_local", Whitelisted, Gated(Stability::Unstable,
                                        "thread_local",
807
                                        "`#[thread_local]` is an experimental feature, and does \
808
                                         not currently handle destructors.",
809
                                        cfg_fn!(thread_local))),
810

811 812
    ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
                                             "on_unimplemented",
813
                                             "the `#[rustc_on_unimplemented]` attribute \
814 815
                                              is an experimental feature",
                                             cfg_fn!(on_unimplemented))),
816 817 818 819 820
    ("rustc_const_unstable", Normal, Gated(Stability::Unstable,
                                             "rustc_const_unstable",
                                             "the `#[rustc_const_unstable]` attribute \
                                              is an internal feature",
                                             cfg_fn!(rustc_const_unstable))),
821
    ("global_allocator", Normal, Ungated),
822 823 824 825 826
    ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
                                            "allocator_internals",
                                            "the `#[default_lib_allocator]` \
                                             attribute is an experimental feature",
                                            cfg_fn!(allocator_internals))),
827
    ("needs_allocator", Normal, Gated(Stability::Unstable,
828
                                      "allocator_internals",
829 830
                                      "the `#[needs_allocator]` \
                                       attribute is an experimental \
831
                                       feature",
832
                                      cfg_fn!(allocator_internals))),
833 834
    ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
                                         "panic_runtime",
835 836 837
                                         "the `#[panic_runtime]` attribute is \
                                          an experimental feature",
                                         cfg_fn!(panic_runtime))),
838 839
    ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
                                               "needs_panic_runtime",
840 841 842 843
                                               "the `#[needs_panic_runtime]` \
                                                attribute is an experimental \
                                                feature",
                                               cfg_fn!(needs_panic_runtime))),
844 845 846 847 848 849
    ("rustc_outlives", Normal, Gated(Stability::Unstable,
                                     "rustc_attrs",
                                     "the `#[rustc_outlives]` attribute \
                                      is just used for rustc unit tests \
                                      and will never be stable",
                                     cfg_fn!(rustc_attrs))),
850 851
    ("rustc_variance", Normal, Gated(Stability::Unstable,
                                     "rustc_attrs",
852
                                     "the `#[rustc_variance]` attribute \
N
Niko Matsakis 已提交
853
                                      is just used for rustc unit tests \
854 855
                                      and will never be stable",
                                     cfg_fn!(rustc_attrs))),
856 857 858 859 860 861
    ("rustc_regions", Normal, Gated(Stability::Unstable,
                                    "rustc_attrs",
                                    "the `#[rustc_regions]` attribute \
                                     is just used for rustc unit tests \
                                     and will never be stable",
                                    cfg_fn!(rustc_attrs))),
862 863
    ("rustc_error", Whitelisted, Gated(Stability::Unstable,
                                       "rustc_attrs",
864
                                       "the `#[rustc_error]` attribute \
N
Niko Matsakis 已提交
865
                                        is just used for rustc unit tests \
866 867
                                        and will never be stable",
                                       cfg_fn!(rustc_attrs))),
868 869
    ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
                                                 "rustc_attrs",
870 871 872 873
                                                 "the `#[rustc_if_this_changed]` attribute \
                                                  is just used for rustc unit tests \
                                                  and will never be stable",
                                                 cfg_fn!(rustc_attrs))),
874 875
    ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
                                                      "rustc_attrs",
876 877 878 879
                                                      "the `#[rustc_if_this_changed]` attribute \
                                                       is just used for rustc unit tests \
                                                       and will never be stable",
                                                      cfg_fn!(rustc_attrs))),
880 881
    ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
                                       "rustc_attrs",
882 883
                                       "the `#[rustc_dirty]` attribute \
                                        is just used for rustc unit tests \
884 885
                                        and will never be stable",
                                       cfg_fn!(rustc_attrs))),
886 887
    ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
                                       "rustc_attrs",
888 889
                                       "the `#[rustc_clean]` attribute \
                                        is just used for rustc unit tests \
890 891
                                        and will never be stable",
                                       cfg_fn!(rustc_attrs))),
892 893
    ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
                                                  "rustc_attrs",
894 895 896 897
                                                  "this attribute \
                                                   is just used for rustc unit tests \
                                                   and will never be stable",
                                                  cfg_fn!(rustc_attrs))),
I
Irina Popa 已提交
898
    ("rustc_partition_codegened", Whitelisted, Gated(Stability::Unstable,
899
                                                      "rustc_attrs",
900 901 902 903
                                                      "this attribute \
                                                       is just used for rustc unit tests \
                                                       and will never be stable",
                                                      cfg_fn!(rustc_attrs))),
904 905 906 907 908 909
    ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable,
                                                      "rustc_attrs",
                                                      "this attribute \
                                                       is just used for rustc unit tests \
                                                       and will never be stable",
                                                      cfg_fn!(rustc_attrs))),
910 911
    ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
                                             "rustc_attrs",
912 913
                                             "internal rustc attributes will never be stable",
                                             cfg_fn!(rustc_attrs))),
914 915
    ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
                                           "rustc_attrs",
916 917
                                           "internal rustc attributes will never be stable",
                                           cfg_fn!(rustc_attrs))),
918 919
    ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
                                     "rustc_attrs",
920 921
                                     "the `#[rustc_mir]` attribute \
                                      is just used for rustc unit tests \
922 923
                                      and will never be stable",
                                     cfg_fn!(rustc_attrs))),
924 925
    ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
                                                         "rustc_attrs",
926 927 928 929 930 931
                                                         "the `#[rustc_inherit_overflow_checks]` \
                                                          attribute is just used to control \
                                                          overflow checking behavior of several \
                                                          libcore functions that are inlined \
                                                          across crates and will never be stable",
                                                          cfg_fn!(rustc_attrs))),
932

S
scalexm 已提交
933 934 935 936 937 938 939
    ("rustc_dump_program_clauses", Whitelisted, Gated(Stability::Unstable,
                                                     "rustc_attrs",
                                                     "the `#[rustc_dump_program_clauses]` \
                                                      attribute is just used for rustc unit \
                                                      tests and will never be stable",
                                                     cfg_fn!(rustc_attrs))),

940 941 942 943 944
    // RFC #2094
    ("nll", Whitelisted, Gated(Stability::Unstable,
                               "nll",
                               "Non lexical lifetimes",
                               cfg_fn!(nll))),
945 946
    ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
                                             "compiler_builtins",
947 948 949 950 951
                                             "the `#[compiler_builtins]` attribute is used to \
                                              identify the `compiler_builtins` crate which \
                                              contains compiler-rt intrinsics and will never be \
                                              stable",
                                          cfg_fn!(compiler_builtins))),
J
Jorge Aparicio 已提交
952 953 954 955 956 957
    ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
                                             "sanitizer_runtime",
                                             "the `#[sanitizer_runtime]` attribute is used to \
                                              identify crates that contain the runtime of a \
                                              sanitizer and will never be stable",
                                             cfg_fn!(sanitizer_runtime))),
958 959 960 961 962 963 964
    ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
                                             "profiler_runtime",
                                             "the `#[profiler_runtime]` attribute is used to \
                                              identify the `profiler_builtins` crate which \
                                              contains the profiler runtime and will never be \
                                              stable",
                                             cfg_fn!(profiler_runtime))),
965

966 967
    ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
                                              "allow_internal_unstable",
968 969
                                              EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
                                              cfg_fn!(allow_internal_unstable))),
970

971 972 973 974 975
    ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
                                            "allow_internal_unsafe",
                                            EXPLAIN_ALLOW_INTERNAL_UNSAFE,
                                            cfg_fn!(allow_internal_unsafe))),

976 977
    ("fundamental", Whitelisted, Gated(Stability::Unstable,
                                       "fundamental",
978
                                       "the `#[fundamental]` attribute \
979 980
                                        is an experimental feature",
                                       cfg_fn!(fundamental))),
981

982
    ("proc_macro_derive", Normal, Ungated),
983

984 985
    ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
                                                   "rustc_attrs",
986 987 988
                                                   "internal implementation detail",
                                                   cfg_fn!(rustc_attrs))),

989
    // FIXME: #14408 whitelist docs since rustdoc looks at them
990
    ("doc", Whitelisted, Ungated),
991

I
Irina Popa 已提交
992
    // FIXME: #14406 these are processed in codegen, which happens after the
993
    // lint pass
994
    ("cold", Whitelisted, Ungated),
995 996
    ("naked", Whitelisted, Gated(Stability::Unstable,
                                 "naked_functions",
T
Ticki 已提交
997
                                 "the `#[naked]` attribute \
998
                                  is an experimental feature",
999
                                 cfg_fn!(naked_functions))),
1000
    ("target_feature", Whitelisted, Ungated),
1001 1002 1003 1004 1005 1006 1007
    ("export_name", Whitelisted, Ungated),
    ("inline", Whitelisted, Ungated),
    ("link", Whitelisted, Ungated),
    ("link_name", Whitelisted, Ungated),
    ("link_section", Whitelisted, Ungated),
    ("no_builtins", Whitelisted, Ungated),
    ("no_mangle", Whitelisted, Ungated),
N
Nick Cameron 已提交
1008 1009 1010
    ("no_debug", Whitelisted, Gated(
        Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
        "no_debug",
1011 1012
        "the `#[no_debug]` attribute was an experimental feature that has been \
         deprecated due to lack of demand",
N
Nick Cameron 已提交
1013
        cfg_fn!(no_debug))),
1014 1015
    ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
                                                       "omit_gdb_pretty_printer_section",
1016 1017
                                                       "the `#[omit_gdb_pretty_printer_section]` \
                                                        attribute is just used for the Rust test \
1018 1019
                                                        suite",
                                                       cfg_fn!(omit_gdb_pretty_printer_section))),
1020 1021
    ("unsafe_destructor_blind_to_params",
     Normal,
1022
     Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
1023
           "dropck_parametricity",
1024 1025
           "unsafe_destructor_blind_to_params has been replaced by \
            may_dangle and will be removed in the future",
1026
           cfg_fn!(dropck_parametricity))),
1027 1028
    ("may_dangle",
     Normal,
1029 1030
     Gated(Stability::Unstable,
           "dropck_eyepatch",
1031 1032
           "may_dangle has unstable semantics and may be removed in the future",
           cfg_fn!(dropck_eyepatch))),
1033 1034 1035
    ("unwind", Whitelisted, Gated(Stability::Unstable,
                                  "unwind_attributes",
                                  "#[unwind] is experimental",
1036
                                  cfg_fn!(unwind_attributes))),
J
Jorge Aparicio 已提交
1037 1038 1039 1040
    ("used", Whitelisted, Gated(
        Stability::Unstable, "used",
        "the `#[used]` attribute is an experimental feature",
        cfg_fn!(used))),
1041 1042

    // used in resolve
1043 1044
    ("prelude_import", Whitelisted, Gated(Stability::Unstable,
                                          "prelude_import",
1045 1046
                                          "`#[prelude_import]` is for use by rustc only",
                                          cfg_fn!(prelude_import))),
1047 1048 1049

    // FIXME: #14407 these are only looked at on-demand so we can't
    // guarantee they'll have already been checked
1050
    ("rustc_deprecated", Whitelisted, Ungated),
1051 1052 1053
    ("must_use", Whitelisted, Ungated),
    ("stable", Whitelisted, Ungated),
    ("unstable", Whitelisted, Ungated),
1054
    ("deprecated", Normal, Ungated),
1055

1056 1057
    ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
                                        "unboxed_closures",
1058 1059
                                        "unboxed_closures are still evolving",
                                        cfg_fn!(unboxed_closures))),
1060

1061
    ("windows_subsystem", Whitelisted, Ungated),
1062

1063 1064
    ("proc_macro_attribute", Normal, Ungated),
    ("proc_macro", Normal, Ungated),
1065

1066 1067 1068 1069 1070
    ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
                                             "rustc_derive_registrar",
                                             "used internally by rustc",
                                             cfg_fn!(rustc_attrs))),

1071 1072 1073 1074 1075
    ("allow_fail", Normal, Gated(Stability::Unstable,
                                 "allow_fail",
                                 "allow_fail attribute is currently unstable",
                                 cfg_fn!(allow_fail))),

1076 1077 1078 1079 1080 1081
    ("rustc_std_internal_symbol", Whitelisted, Gated(Stability::Unstable,
                                     "rustc_attrs",
                                     "this is an internal attribute that will \
                                      never be stable",
                                     cfg_fn!(rustc_attrs))),

1082 1083 1084 1085 1086 1087 1088
    // whitelists "identity-like" conversion methods to suggest on type mismatch
    ("rustc_conversion_suggestion", Whitelisted, Gated(Stability::Unstable,
                                                       "rustc_attrs",
                                                       "this is an internal attribute that will \
                                                        never be stable",
                                                       cfg_fn!(rustc_attrs))),

1089 1090 1091 1092
    ("rustc_args_required_const", Whitelisted, Gated(Stability::Unstable,
                                 "rustc_attrs",
                                 "never will be stable",
                                 cfg_fn!(rustc_attrs))),
1093 1094 1095 1096 1097 1098

    // RFC #2093
    ("infer_outlives_requirements", Normal, Gated(Stability::Unstable,
                                   "infer_outlives_requirements",
                                   "infer outlives requirements is an experimental feature",
                                   cfg_fn!(infer_outlives_requirements))),
1099

1100 1101 1102 1103 1104 1105
    // RFC #2093
    ("infer_static_outlives_requirements", Normal, Gated(Stability::Unstable,
                                   "infer_static_outlives_requirements",
                                   "infer 'static lifetime requirements",
                                   cfg_fn!(infer_static_outlives_requirements))),

1106 1107 1108 1109 1110 1111
    // RFC 2070
    ("panic_implementation", Normal, Gated(Stability::Unstable,
                           "panic_implementation",
                           "#[panic_implementation] is an unstable feature",
                           cfg_fn!(panic_implementation))),

S
Simon Sapin 已提交
1112 1113 1114 1115 1116
    ("alloc_error_handler", Normal, Gated(Stability::Unstable,
                           "alloc_error_handler",
                           "#[alloc_error_handler] is an unstable feature",
                           cfg_fn!(alloc_error_handler))),

1117
    // Crate level attributes
1118 1119 1120 1121 1122 1123 1124 1125
    ("crate_name", CrateLevel, Ungated),
    ("crate_type", CrateLevel, Ungated),
    ("crate_id", CrateLevel, Ungated),
    ("feature", CrateLevel, Ungated),
    ("no_start", CrateLevel, Ungated),
    ("no_main", CrateLevel, Ungated),
    ("no_builtins", CrateLevel, Ungated),
    ("recursion_limit", CrateLevel, Ungated),
1126
    ("type_length_limit", CrateLevel, Ungated),
1127 1128
];

1129
// cfg(...)'s that are feature gated
1130
const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
1131
    // (name in cfg, feature, function to check if the feature is enabled)
1132 1133
    ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
    ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
1134
    ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
1135 1136
];

1137
#[derive(Debug)]
1138 1139 1140 1141
pub struct GatedCfg {
    span: Span,
    index: usize,
}
1142

1143 1144
impl GatedCfg {
    pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
S
Seiichi Uchida 已提交
1145
        let name = cfg.name().as_str();
1146 1147 1148 1149 1150 1151 1152 1153 1154
        GATED_CFGS.iter()
                  .position(|info| info.0 == name)
                  .map(|idx| {
                      GatedCfg {
                          span: cfg.span,
                          index: idx
                      }
                  })
    }
J
Jeffrey Seyfried 已提交
1155 1156

    pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
1157
        let (cfg, feature, has_feature) = GATED_CFGS[self.index];
1158
        if !has_feature(features) && !self.span.allows_unstable() {
1159
            let explain = format!("`cfg({})` is experimental and subject to change", cfg);
1160
            emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
1161 1162 1163 1164
        }
    }
}

E
Eduard Burtescu 已提交
1165
struct Context<'a> {
L
Leo Testard 已提交
1166
    features: &'a Features,
1167
    parse_sess: &'a ParseSess,
1168
    plugin_attributes: &'a [(String, AttributeType)],
1169 1170
}

1171
macro_rules! gate_feature_fn {
1172 1173 1174
    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
        let (cx, has_feature, span,
             name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
1175 1176
        let has_feature: bool = has_feature(&$cx.features);
        debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
1177
        if !has_feature && !span.allows_unstable() {
1178 1179
            leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
                .emit();
1180
        }
1181 1182 1183 1184 1185
    }}
}

macro_rules! gate_feature {
    ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
1186 1187 1188 1189 1190 1191 1192
        gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
                         stringify!($feature), $explain, GateStrength::Hard)
    };
    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
        gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
                         stringify!($feature), $explain, $level)
    };
1193
}
1194

1195
impl<'a> Context<'a> {
1196
    fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
1197
        debug!("check_attribute(attr = {:?})", attr);
1198
        let name = attr.name().as_str();
1199
        for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
1200
            if name == n {
1201
                if let Gated(_, name, desc, ref has_feature) = *gateage {
1202
                    gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
1203 1204 1205 1206 1207 1208 1209 1210
                } else if name == "doc" {
                    if let Some(content) = attr.meta_item_list() {
                        if content.iter().any(|c| c.check_name("include")) {
                            gate_feature!(self, external_doc, attr.span,
                                "#[doc(include = \"...\")] is experimental"
                            );
                        }
                    }
1211
                }
1212
                debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
1213 1214 1215
                return;
            }
        }
1216
        for &(ref n, ref ty) in self.plugin_attributes {
1217
            if attr.path == &**n {
1218
                // Plugins can't gate attributes, so we don't check for it
M
Manish Goregaokar 已提交
1219 1220
                // unlike the code above; we only use this loop to
                // short-circuit to avoid the checks below
1221
                debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
1222 1223 1224
                return;
            }
        }
1225
        if name.starts_with("rustc_") {
1226 1227 1228 1229
            gate_feature!(self, rustc_attrs, attr.span,
                          "unless otherwise specified, attributes \
                           with the prefix `rustc_` \
                           are reserved for internal compiler diagnostics");
1230
        } else if name.starts_with("derive_") {
L
Leo Testard 已提交
1231
            gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
1232
        } else if !attr::is_known(attr) {
M
Manish Goregaokar 已提交
1233 1234 1235 1236
            // Only run the custom attribute lint during regular
            // feature gate checking. Macro gating runs
            // before the plugin attributes are registered
            // so we skip this then
1237
            if !is_macro {
1238 1239 1240
                let msg = format!("The attribute `{}` is currently unknown to the compiler and \
                                   may have meaning added to it in the future", attr.path);
                gate_feature!(self, custom_attribute, attr.span, &msg);
1241
            }
1242 1243
        }
    }
1244 1245
}

1246 1247
pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
    let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
L
Leo Testard 已提交
1248 1249 1250
    cx.check_attribute(attr, true);
}

1251
fn find_lang_feature_issue(feature: &str) -> Option<u32> {
1252 1253
    if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
        let issue = info.2;
1254 1255
        // FIXME (#28244): enforce that active features have issue numbers
        // assert!(issue.is_some())
1256 1257
        issue
    } else {
1258 1259 1260 1261
        // search in Accepted, Removed, or Stable Removed features
        let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
            .find(|t| t.0 == feature);
        match found {
1262
            Some(&(_, _, issue, _)) => issue,
1263 1264
            None => panic!("Feature `{}` is not declared anywhere", feature),
        }
1265 1266 1267 1268 1269 1270 1271 1272
    }
}

pub enum GateIssue {
    Language,
    Library(Option<u32>)
}

1273
#[derive(Debug, Copy, Clone, PartialEq)]
1274 1275 1276 1277 1278 1279 1280
pub enum GateStrength {
    /// A hard error. (Most feature gates should use this.)
    Hard,
    /// Only a warning. (Use this only as backwards-compatibility demands.)
    Soft,
}

1281
pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1282
                        explain: &str) {
1283 1284 1285 1286
    feature_err(sess, feature, span, issue, explain).emit();
}

pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1287
                       explain: &str) -> DiagnosticBuilder<'a> {
1288 1289 1290 1291 1292
    leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
}

fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
                           explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
1293 1294
    let diag = &sess.span_diagnostic;

1295 1296 1297 1298 1299
    let issue = match issue {
        GateIssue::Language => find_lang_feature_issue(feature),
        GateIssue::Library(lib) => lib,
    };

Z
Zack M. Davis 已提交
1300 1301 1302
    let explanation = match issue {
        None | Some(0) => explain.to_owned(),
        Some(n) => format!("{} (see issue #{})", explain, n)
1303 1304 1305
    };

    let mut err = match level {
1306 1307 1308
        GateStrength::Hard => {
            diag.struct_span_err_with_code(span, &explanation, stringify_error_code!(E0658))
        }
1309
        GateStrength::Soft => diag.struct_span_warn(span, &explanation),
N
Nick Cameron 已提交
1310
    };
1311 1312

    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
T
Tim Neumann 已提交
1313 1314 1315 1316
    if sess.unstable_features.is_nightly_build() {
        err.help(&format!("add #![feature({})] to the \
                           crate attributes to enable",
                          feature));
N
Nick Cameron 已提交
1317
    }
T
Tim Neumann 已提交
1318

1319 1320 1321 1322 1323 1324 1325
    // If we're on stable and only emitting a "soft" warning, add a note to
    // clarify that the feature isn't "on" (rather than being on but
    // warning-worthy).
    if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
        err.help("a nightly build of the compiler is required to enable this feature");
    }

1326
    err
1327

1328 1329
}

L
Leo Testard 已提交
1330 1331 1332
const EXPLAIN_BOX_SYNTAX: &'static str =
    "box expression syntax is experimental; you can call `Box::new` instead.";

J
Jeffrey Seyfried 已提交
1333
pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1334
    "attributes on expressions are experimental.";
L
Leo Testard 已提交
1335

1336 1337 1338
pub const EXPLAIN_ASM: &'static str =
    "inline assembly is not stable enough for use and is subject to change";

1339
pub const EXPLAIN_GLOBAL_ASM: &'static str =
A
A.J. Gardner 已提交
1340
    "`global_asm!` is not stable enough for use and is subject to change";
1341

1342 1343 1344 1345 1346
pub const EXPLAIN_LOG_SYNTAX: &'static str =
    "`log_syntax!` is not stable enough for use and is subject to change";

pub const EXPLAIN_CONCAT_IDENTS: &'static str =
    "`concat_idents` is not stable enough for use and is subject to change";
W
Wesley Wiser 已提交
1347

1348 1349 1350
pub const EXPLAIN_FORMAT_ARGS_NL: &'static str =
    "`format_args_nl` is only for internal language use and is subject to change";

1351 1352
pub const EXPLAIN_TRACE_MACROS: &'static str =
    "`trace_macros` is not stable enough for use and is subject to change";
1353 1354
pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
    "allow_internal_unstable side-steps feature gating and stability checks";
1355 1356
pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
    "allow_internal_unsafe side-steps the unsafe_code lint";
1357

1358
pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1359
    "`#[derive]` for custom traits is deprecated and will be removed in the future.";
N
Nick Cameron 已提交
1360 1361

pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1362 1363
    "`#[derive]` for custom traits is deprecated and will be removed in the future. \
    Prefer using procedural macro custom derive.";
1364

L
Leo Testard 已提交
1365 1366
pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
    "attributes of the form `#[derive_*]` are reserved for the compiler";
1367

1368 1369 1370
pub const EXPLAIN_LITERAL_MATCHER: &'static str =
    ":literal fragment specifier is experimental and subject to change";

1371
pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
M
mark 已提交
1372
    "unsized tuple coercion is not stable enough for use and is subject to change";
1373

M
Mark Mansi 已提交
1374
pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str =
M
mark 已提交
1375
    "using the `?` macro Kleene operator for \"at most one\" repetition is unstable";
M
Mark Mansi 已提交
1376

C
Corey Richardson 已提交
1377
struct PostExpansionVisitor<'a> {
N
Nick Cameron 已提交
1378
    context: &'a Context<'a>,
C
Corey Richardson 已提交
1379 1380
}

1381 1382 1383
macro_rules! gate_feature_post {
    ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
        let (cx, span) = ($cx, $span);
1384
        if !span.allows_unstable() {
1385
            gate_feature!(cx.context, $feature, span, $explain)
C
Corey Richardson 已提交
1386
        }
1387 1388 1389 1390 1391 1392
    }};
    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
        let (cx, span) = ($cx, $span);
        if !span.allows_unstable() {
            gate_feature!(cx.context, $feature, span, $explain, $level)
        }
1393
    }}
C
Corey Richardson 已提交
1394 1395
}

1396 1397 1398
impl<'a> PostExpansionVisitor<'a> {
    fn check_abi(&self, abi: Abi, span: Span) {
        match abi {
1399
            Abi::RustIntrinsic => {
1400
                gate_feature_post!(&self, intrinsics, span,
1401 1402
                                   "intrinsics are subject to change");
            },
1403 1404
            Abi::PlatformIntrinsic => {
                gate_feature_post!(&self, platform_intrinsics, span,
1405
                                   "platform intrinsics are experimental and possibly buggy");
1406 1407 1408
            },
            Abi::Vectorcall => {
                gate_feature_post!(&self, abi_vectorcall, span,
1409 1410
                                   "vectorcall is experimental and subject to change");
            },
1411 1412 1413 1414
            Abi::Thiscall => {
                gate_feature_post!(&self, abi_thiscall, span,
                                   "thiscall is experimental and subject to change");
            },
1415 1416 1417
            Abi::RustCall => {
                gate_feature_post!(&self, unboxed_closures, span,
                                   "rust-call ABI is subject to change");
1418
            },
J
Jorge Aparicio 已提交
1419 1420 1421
            Abi::PtxKernel => {
                gate_feature_post!(&self, abi_ptx, span,
                                   "PTX ABIs are experimental and subject to change");
1422 1423 1424 1425 1426
            },
            Abi::Unadjusted => {
                gate_feature_post!(&self, abi_unadjusted, span,
                                   "unadjusted ABI is an implementation detail and perma-unstable");
            },
1427 1428 1429 1430
            Abi::Msp430Interrupt => {
                gate_feature_post!(&self, abi_msp430_interrupt, span,
                                   "msp430-interrupt ABI is experimental and subject to change");
            },
1431 1432 1433 1434
            Abi::X86Interrupt => {
                gate_feature_post!(&self, abi_x86_interrupt, span,
                                   "x86-interrupt ABI is experimental and subject to change");
            },
R
Richard Diamond 已提交
1435 1436 1437 1438
            Abi::AmdGpuKernel => {
                gate_feature_post!(&self, abi_amdgpu_kernel, span,
                                   "amdgpu-kernel ABI is experimental and subject to change");
            },
J
Jorge Aparicio 已提交
1439 1440 1441 1442 1443 1444
            // Stable
            Abi::Cdecl |
            Abi::Stdcall |
            Abi::Fastcall |
            Abi::Aapcs |
            Abi::Win64 |
C
CensoredUsername 已提交
1445
            Abi::SysV64 |
J
Jorge Aparicio 已提交
1446 1447 1448
            Abi::Rust |
            Abi::C |
            Abi::System => {}
1449 1450 1451 1452
        }
    }
}

1453
impl<'a> PostExpansionVisitor<'a> {
1454
    fn whole_crate_feature_gates(&mut self, _krate: &ast::Crate) {
1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
        for &(ident, span) in &*self.context.parse_sess.non_modrs_mods.borrow() {
            if !span.allows_unstable() {
                let cx = &self.context;
                let level = GateStrength::Hard;
                let has_feature = cx.features.non_modrs_mods;
                let name = "non_modrs_mods";
                debug!("gate_feature(feature = {:?}, span = {:?}); has? {}",
                        name, span, has_feature);

                if !has_feature && !span.allows_unstable() {
                    leveled_feature_err(
                        cx.parse_sess, name, span, GateIssue::Language,
                        "mod statements in non-mod.rs files are unstable", level
                    )
                    .help(&format!("on stable builds, rename this file to {}{}mod.rs",
                                   ident, path::MAIN_SEPARATOR))
                    .emit();
                }
            }
        }
    }
}

1478
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1479
    fn visit_attribute(&mut self, attr: &ast::Attribute) {
1480
        if !attr.span.allows_unstable() {
1481
            // check for gated attributes
1482
            self.context.check_attribute(attr, false);
1483
        }
1484

K
kennytm 已提交
1485 1486 1487 1488 1489 1490
        if attr.check_name("doc") {
            if let Some(content) = attr.meta_item_list() {
                if content.len() == 1 && content[0].check_name("cfg") {
                    gate_feature_post!(&self, doc_cfg, attr.span,
                        "#[doc(cfg(...))] is experimental"
                    );
1491 1492 1493 1494
                } else if content.iter().any(|c| c.check_name("masked")) {
                    gate_feature_post!(&self, doc_masked, attr.span,
                        "#[doc(masked)] is experimental"
                    );
1495 1496 1497 1498
                } else if content.iter().any(|c| c.check_name("spotlight")) {
                    gate_feature_post!(&self, doc_spotlight, attr.span,
                        "#[doc(spotlight)] is experimental"
                    );
G
Guillaume Gomez 已提交
1499 1500 1501 1502
                } else if content.iter().any(|c| c.check_name("alias")) {
                    gate_feature_post!(&self, doc_alias, attr.span,
                        "#[doc(alias = \"...\")] is experimental"
                    );
1503 1504 1505 1506
                } else if content.iter().any(|c| c.check_name("keyword")) {
                    gate_feature_post!(&self, doc_keyword, attr.span,
                        "#[doc(keyword = \"...\")] is experimental"
                    );
K
kennytm 已提交
1507 1508 1509 1510
                }
            }
        }

1511
        if !self.context.features.unrestricted_attribute_tokens {
1512 1513 1514 1515 1516
            // Unfortunately, `parse_meta` cannot be called speculatively
            // because it can report errors by itself, so we have to call it
            // only if the feature is disabled.
            if let Err(mut err) = attr.parse_meta(self.context.parse_sess) {
                err.help("try enabling `#![feature(unrestricted_attribute_tokens)]`").emit()
1517
            }
1518
        }
1519 1520
    }

1521
    fn visit_name(&mut self, sp: Span, name: ast::Name) {
1522
        if !name.as_str().is_ascii() {
1523 1524
            gate_feature_post!(&self,
                               non_ascii_idents,
D
Donato Sciarra 已提交
1525
                               self.context.parse_sess.source_map().def_span(sp),
1526
                               "non-ascii idents are not fully supported.");
1527 1528 1529
        }
    }

1530
    fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) {
1531
        if let ast::UseTreeKind::Simple(Some(ident), ..) = use_tree.kind {
1532 1533 1534 1535 1536 1537 1538 1539 1540
            if ident.name == "_" {
                gate_feature_post!(&self, underscore_imports, use_tree.span,
                                   "renaming imports with `_` is unstable");
            }
        }

        visit::walk_use_tree(self, use_tree, id);
    }

1541
    fn visit_item(&mut self, i: &'a ast::Item) {
1542
        match i.node {
1543
            ast::ItemKind::ExternCrate(_) => {
1544 1545 1546 1547
                if i.ident.name == "_" {
                    gate_feature_post!(&self, underscore_imports, i.span,
                                       "renaming extern crates with `_` is unstable");
                }
1548 1549
            }

1550
            ast::ItemKind::ForeignMod(ref foreign_module) => {
1551
                self.check_abi(foreign_module.abi, i.span);
1552 1553
            }

1554
            ast::ItemKind::Fn(..) => {
1555
                if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1556 1557
                    gate_feature_post!(&self, plugin_registrar, i.span,
                                       "compiler plugins are experimental and possibly buggy");
1558
                }
1559
                if attr::contains_name(&i.attrs[..], "start") {
1560
                    gate_feature_post!(&self, start, i.span,
1561 1562 1563 1564
                                      "a #[start] function is an experimental \
                                       feature whose signature may change \
                                       over time");
                }
1565
                if attr::contains_name(&i.attrs[..], "main") {
1566 1567 1568 1569
                    gate_feature_post!(&self, main, i.span,
                                       "declaration of a nonstandard #[main] \
                                        function may change over time, for now \
                                        a top-level `fn main()` is required");
1570
                }
1571 1572
            }

1573
            ast::ItemKind::Struct(..) => {
1574 1575 1576 1577 1578 1579
                if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
                    for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
                        if item.check_name("simd") {
                            gate_feature_post!(&self, repr_simd, attr.span,
                                               "SIMD types are experimental and possibly buggy");
                        }
1580 1581 1582 1583 1584 1585 1586
                        if let Some((name, _)) = item.name_value_literal() {
                            if name == "packed" {
                                gate_feature_post!(&self, repr_packed, attr.span,
                                                   "the `#[repr(packed(n))]` attribute \
                                                   is experimental");
                            }
                        }
1587
                    }
1588
                }
D
David Manescu 已提交
1589 1590
            }

A
Alex Burka 已提交
1591 1592 1593 1594 1595 1596
            ast::ItemKind::TraitAlias(..) => {
                gate_feature_post!(&self, trait_alias,
                                   i.span,
                                   "trait aliases are not yet fully implemented");
            }

1597
            ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1598
                if polarity == ast::ImplPolarity::Negative {
1599 1600 1601 1602
                    gate_feature_post!(&self, optin_builtin_traits,
                                       i.span,
                                       "negative trait bounds are not yet fully implemented; \
                                        use marker types for now");
1603
                }
1604

1605 1606 1607 1608
                if let ast::Defaultness::Default = defaultness {
                    gate_feature_post!(&self, specialization,
                                       i.span,
                                       "specialization is unstable");
1609
                }
1610 1611
            }

1612 1613 1614 1615 1616
            ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
                gate_feature_post!(&self, optin_builtin_traits,
                                   i.span,
                                   "auto traits are experimental and possibly buggy");
            }
1617

1618 1619 1620 1621 1622
            ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
                let msg = "`macro` is experimental";
                gate_feature_post!(&self, decl_macro, i.span, msg);
            }

O
Oliver Schneider 已提交
1623 1624 1625 1626 1627 1628 1629 1630 1631
            ast::ItemKind::Existential(..) => {
                gate_feature_post!(
                    &self,
                    existential_type,
                    i.span,
                    "existential types are unstable"
                );
            }

1632 1633 1634
            _ => {}
        }

1635
        visit::walk_item(self, i);
1636
    }
1637

1638
    fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
P
Paul Lietar 已提交
1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655
        match i.node {
            ast::ForeignItemKind::Fn(..) |
            ast::ForeignItemKind::Static(..) => {
                let link_name = attr::first_attr_value_str_by_name(&i.attrs, "link_name");
                let links_to_llvm = match link_name {
                    Some(val) => val.as_str().starts_with("llvm."),
                    _ => false
                };
                if links_to_llvm {
                    gate_feature_post!(&self, link_llvm_intrinsics, i.span,
                                       "linking to LLVM intrinsics is experimental");
                }
            }
            ast::ForeignItemKind::Ty => {
                    gate_feature_post!(&self, extern_types, i.span,
                                       "extern types are experimental");
            }
1656
            ast::ForeignItemKind::Macro(..) => {}
1657 1658
        }

1659
        visit::walk_foreign_item(self, i)
1660 1661
    }

1662
    fn visit_ty(&mut self, ty: &'a ast::Ty) {
1663 1664 1665 1666
        match ty.node {
            ast::TyKind::BareFn(ref bare_fn_ty) => {
                self.check_abi(bare_fn_ty.abi, ty.span);
            }
1667 1668 1669 1670
            ast::TyKind::Never => {
                gate_feature_post!(&self, never_type, ty.span,
                                   "The `!` type is experimental");
            }
1671 1672 1673 1674 1675
            _ => {}
        }
        visit::walk_ty(self, ty)
    }

1676
    fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1677
        if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1678 1679 1680
            if let ast::TyKind::Never = output_ty.node {
                // Do nothing
            } else {
1681
                self.visit_ty(output_ty)
1682
            }
1683 1684 1685
        }
    }

1686
    fn visit_expr(&mut self, e: &'a ast::Expr) {
1687
        match e.node {
1688
            ast::ExprKind::Box(_) => {
1689
                gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1690
            }
1691
            ast::ExprKind::Type(..) => {
1692
                gate_feature_post!(&self, type_ascription, e.span,
1693 1694
                                  "type ascription is experimental");
            }
1695 1696 1697
            ast::ExprKind::ObsoleteInPlace(..) => {
                // these get a hard error in ast-validation
            }
J
John Kåre Alsaker 已提交
1698 1699 1700 1701 1702
            ast::ExprKind::Yield(..) => {
                gate_feature_post!(&self, generators,
                                  e.span,
                                  "yield syntax is experimental");
            }
1703
            ast::ExprKind::TryBlock(_) => {
1704
                gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
1705
            }
1706 1707 1708 1709 1710 1711
            ast::ExprKind::IfLet(ref pats, ..) | ast::ExprKind::WhileLet(ref pats, ..) => {
                if pats.len() > 1 {
                    gate_feature_post!(&self, if_while_or_patterns, e.span,
                                    "multiple patterns in `if let` and `while let` are unstable");
                }
            }
E
est31 已提交
1712 1713 1714 1715 1716 1717
            ast::ExprKind::Block(_, opt_label) => {
                if let Some(label) = opt_label {
                    gate_feature_post!(&self, label_break_value, label.ident.span,
                                    "labels on blocks are unstable");
                }
            }
1718
            ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
T
Taylor Cramer 已提交
1719 1720 1721 1722 1723
                gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
            }
            ast::ExprKind::Async(..) => {
                gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
            }
1724 1725
            _ => {}
        }
1726
        visit::walk_expr(self, e);
1727
    }
1728

M
Matt Ickstadt 已提交
1729
    fn visit_arm(&mut self, arm: &'a ast::Arm) {
M
Matt Ickstadt 已提交
1730
        visit::walk_arm(self, arm)
M
Matt Ickstadt 已提交
1731 1732
    }

1733
    fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1734
        match pattern.node {
1735
            PatKind::Slice(_, Some(ref subslice), _) => {
1736
                gate_feature_post!(&self, slice_patterns,
1737 1738
                                   subslice.span,
                                   "syntax for subslices in slice patterns is not yet stabilized");
1739
            }
1740
            PatKind::Box(..) => {
1741
                gate_feature_post!(&self, box_patterns,
1742
                                  pattern.span,
1743
                                  "box pattern syntax is experimental");
1744
            }
1745
            PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => {
1746 1747 1748
                gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
                                   "exclusive range pattern syntax is experimental");
            }
1749 1750 1751 1752
            PatKind::Paren(..) => {
                gate_feature_post!(&self, pattern_parentheses, pattern.span,
                                   "parentheses in patterns are unstable");
            }
1753 1754
            _ => {}
        }
1755
        visit::walk_pat(self, pattern)
1756 1757
    }

1758
    fn visit_fn(&mut self,
1759 1760
                fn_kind: FnKind<'a>,
                fn_decl: &'a ast::FnDecl,
1761
                span: Span,
1762
                _node_id: NodeId) {
1763
        match fn_kind {
W
Without Boats 已提交
1764 1765
            FnKind::ItemFn(_, header, _, _) => {
                // check for const fn and async fn declarations
T
Taylor Cramer 已提交
1766
                if header.asyncness.is_async() {
W
Without Boats 已提交
1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780
                    gate_feature_post!(&self, async_await, span, "async fn is unstable");
                }
                if header.constness.node == ast::Constness::Const {
                    gate_feature_post!(&self, const_fn, span, "const fn is unstable");
                }
                // stability of const fn methods are covered in
                // visit_trait_item and visit_impl_item below; this is
                // because default methods don't pass through this
                // point.

                self.check_abi(header.abi, span);
            }
            FnKind::Method(_, sig, _, _) => {
                self.check_abi(sig.header.abi, span);
1781
            }
1782 1783
            _ => {}
        }
1784
        visit::walk_fn(self, fn_kind, fn_decl, span);
1785
    }
1786

1787
    fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1788
        match ti.node {
1789 1790
            ast::TraitItemKind::Method(ref sig, ref block) => {
                if block.is_none() {
W
Without Boats 已提交
1791
                    self.check_abi(sig.header.abi, ti.span);
1792
                }
W
Without Boats 已提交
1793
                if sig.header.constness.node == ast::Constness::Const {
1794
                    gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
N
Niko Matsakis 已提交
1795 1796
                }
            }
1797
            ast::TraitItemKind::Type(_, ref default) => {
1798 1799
                // We use three if statements instead of something like match guards so that all
                // of these errors can be emitted if all cases apply.
1800 1801 1802 1803
                if default.is_some() {
                    gate_feature_post!(&self, associated_type_defaults, ti.span,
                                       "associated type defaults are unstable");
                }
1804
                if !ti.generics.params.is_empty() {
1805 1806 1807
                    gate_feature_post!(&self, generic_associated_types, ti.span,
                                       "generic associated types are unstable");
                }
1808 1809 1810 1811
                if !ti.generics.where_clause.predicates.is_empty() {
                    gate_feature_post!(&self, generic_associated_types, ti.span,
                                       "where clauses on associated types are unstable");
                }
S
Sunjay Varma 已提交
1812
            }
1813 1814 1815 1816 1817
            _ => {}
        }
        visit::walk_trait_item(self, ti);
    }

1818
    fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
A
Aaron Turon 已提交
1819
        if ii.defaultness == ast::Defaultness::Default {
1820
            gate_feature_post!(&self, specialization,
A
Aaron Turon 已提交
1821 1822 1823 1824
                              ii.span,
                              "specialization is unstable");
        }

1825
        match ii.node {
1826
            ast::ImplItemKind::Method(ref sig, _) => {
W
Without Boats 已提交
1827
                if sig.header.constness.node == ast::Constness::Const {
1828
                    gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
N
Niko Matsakis 已提交
1829 1830
                }
            }
O
Oliver Schneider 已提交
1831 1832 1833 1834 1835 1836 1837 1838
            ast::ImplItemKind::Existential(..) => {
                gate_feature_post!(
                    &self,
                    existential_type,
                    ii.span,
                    "existential types are unstable"
                );
            }
1839 1840 1841 1842 1843 1844 1845 1846 1847
            ast::ImplItemKind::Type(_) => {
                if !ii.generics.params.is_empty() {
                    gate_feature_post!(&self, generic_associated_types, ii.span,
                                       "generic associated types are unstable");
                }
                if !ii.generics.where_clause.predicates.is_empty() {
                    gate_feature_post!(&self, generic_associated_types, ii.span,
                                       "where clauses on associated types are unstable");
                }
S
Sunjay Varma 已提交
1848
            }
1849 1850 1851 1852
            _ => {}
        }
        visit::walk_impl_item(self, ii);
    }
1853

V
Vadim Petrochenkov 已提交
1854 1855
    fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) {
        for segment in &path.segments {
1856 1857 1858 1859 1860 1861 1862 1863
            // Identifiers we are going to check could come from a legacy macro (e.g. `#[test]`).
            // For such macros identifiers must have empty context, because this context is
            // used during name resolution and produced names must be unhygienic for compatibility.
            // On the other hand, we need the actual non-empty context for feature gate checking
            // because it's hygienic even for legacy macros. As previously stated, such context
            // cannot be kept in identifiers, so it's kept in paths instead and we take it from
            // there while keeping location info from the ident span.
            let span = segment.ident.span.with_ctxt(path.span.ctxt());
1864
            if segment.ident.name == keywords::Crate.name() {
1865
                gate_feature_post!(&self, crate_in_paths, span,
V
Vadim Petrochenkov 已提交
1866
                                   "`crate` in paths is experimental");
1867
            } else if segment.ident.name == keywords::Extern.name() {
1868
                gate_feature_post!(&self, extern_in_paths, span,
V
Vadim Petrochenkov 已提交
1869
                                   "`extern` in paths is experimental");
V
Vadim Petrochenkov 已提交
1870 1871 1872 1873 1874 1875
            }
        }

        visit::walk_path(self, path);
    }

1876
    fn visit_vis(&mut self, vis: &'a ast::Visibility) {
1877 1878
        if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node {
            gate_feature_post!(&self, crate_visibility_modifier, vis.span,
1879 1880 1881 1882
                               "`crate` visibility modifier is experimental");
        }
        visit::walk_vis(self, vis);
    }
1883 1884
}

1885
pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
1886
                    crate_edition: Edition) -> Features {
1887 1888 1889 1890 1891 1892
    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
        if let Some(reason) = reason {
            err.span_note(span, reason);
        }
        err.emit();
1893 1894
    }

1895 1896 1897 1898 1899
    // Some features are known to be incomplete and using them is likely to have
    // unanticipated results, such as compiler crashes. We warn the user about these
    // to alert them.
    let incomplete_features = ["generic_associated_types"];

1900
    let mut features = Features::new();
1901 1902
    let mut edition_enabled_features = FxHashMap();

1903 1904 1905 1906 1907 1908 1909 1910
    for &edition in ALL_EDITIONS {
        if edition <= crate_edition {
            // The `crate_edition` implies its respective umbrella feature-gate
            // (i.e. `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
            edition_enabled_features.insert(Symbol::intern(edition.feature_name()), edition);
        }
    }

1911
    for &(name, .., f_edition, set) in ACTIVE_FEATURES {
1912 1913 1914
        if let Some(f_edition) = f_edition {
            if f_edition <= crate_edition {
                set(&mut features, DUMMY_SP);
1915
                edition_enabled_features.insert(Symbol::intern(name), crate_edition);
1916
            }
1917 1918 1919
        }
    }

1920 1921
    // Process the edition umbrella feature-gates first, to ensure
    // `edition_enabled_features` is completed before it's queried.
J
Jeffrey Seyfried 已提交
1922
    for attr in krate_attrs {
S
Steven Fackler 已提交
1923
        if !attr.check_name("feature") {
1924 1925
            continue
        }
1926

1927 1928
        let list = match attr.meta_item_list() {
            Some(list) => list,
1929
            None => continue,
1930 1931 1932 1933 1934 1935 1936 1937 1938
        };

        for mi in list {
            let name = if let Some(word) = mi.word() {
                word.name()
            } else {
                continue
            };

1939 1940 1941 1942 1943 1944 1945 1946 1947 1948
            if incomplete_features.iter().any(|f| *f == name.as_str()) {
                span_handler.struct_span_warn(
                    mi.span,
                    &format!(
                        "the feature `{}` is incomplete and may cause the compiler to crash",
                        name
                    )
                ).emit();
            }

1949 1950
            if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) {
                if *edition <= crate_edition {
1951
                    continue;
1952 1953
                }

1954
                for &(name, .., f_edition, set) in ACTIVE_FEATURES {
1955 1956 1957 1958 1959 1960 1961 1962 1963
                    if let Some(f_edition) = f_edition {
                        if f_edition <= *edition {
                            // FIXME(Manishearth) there is currently no way to set
                            // lib features by edition
                            set(&mut features, DUMMY_SP);
                            edition_enabled_features.insert(Symbol::intern(name), *edition);
                        }
                    }
                }
1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980
            }
        }
    }

    for attr in krate_attrs {
        if !attr.check_name("feature") {
            continue
        }

        let list = match attr.meta_item_list() {
            Some(list) => list,
            None => {
                span_err!(span_handler, attr.span, E0555,
                          "malformed feature attribute, expected #![feature(...)]");
                continue
            }
        };
1981

1982 1983 1984 1985 1986 1987
        for mi in list {
            let name = if let Some(word) = mi.word() {
                word.name()
            } else {
                span_err!(span_handler, mi.span, E0556,
                          "malformed feature, expected just one word");
1988
                continue
1989 1990
            };

1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
            if let Some(edition) = edition_enabled_features.get(&name) {
                struct_span_warn!(
                    span_handler,
                    mi.span,
                    E0705,
                    "the feature `{}` is included in the Rust {} edition",
                    name,
                    edition,
                ).emit();
                continue;
            }

2003 2004 2005
            if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
                // Handled in the separate loop above.
                continue;
2006 2007
            }

2008
            if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
2009 2010
                set(&mut features, mi.span);
                features.declared_lang_features.push((name, mi.span, None));
2011
                continue
2012
            }
2013

2014 2015 2016 2017 2018 2019 2020
            let removed = REMOVED_FEATURES.iter().find(|f| name == f.0);
            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0);
            if let Some((.., reason)) = removed.or(stable_removed) {
                feature_removed(span_handler, mi.span, *reason);
                continue
            }

V
varkor 已提交
2021 2022 2023
            if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) {
                let since = Some(Symbol::intern(since));
                features.declared_lang_features.push((name, mi.span, since));
2024 2025 2026 2027
                continue
            }

            features.declared_lib_features.push((name, mi.span));
2028 2029 2030
        }
    }

L
Leo Testard 已提交
2031
    features
C
Corey Richardson 已提交
2032 2033
}

J
Jeffrey Seyfried 已提交
2034 2035 2036
pub fn check_crate(krate: &ast::Crate,
                   sess: &ParseSess,
                   features: &Features,
2037
                   plugin_attributes: &[(String, AttributeType)],
J
Jeffrey Seyfried 已提交
2038 2039 2040
                   unstable: UnstableFeatures) {
    maybe_stage_features(&sess.span_diagnostic, krate, unstable);
    let ctx = Context {
2041
        features,
2042
        parse_sess: sess,
2043
        plugin_attributes,
J
Jeffrey Seyfried 已提交
2044
    };
L
Lymia Aluysia 已提交
2045

2046
    let visitor = &mut PostExpansionVisitor { context: &ctx };
2047
    visitor.whole_crate_feature_gates(krate);
2048
    visit::walk_crate(visitor, krate);
C
Corey Richardson 已提交
2049
}
2050

2051
#[derive(Clone, Copy, Hash)]
2052 2053 2054 2055
pub enum UnstableFeatures {
    /// Hard errors for unstable features are active, as on
    /// beta/stable channels.
    Disallow,
J
John Hodge 已提交
2056
    /// Allow features to be activated, as on nightly.
2057 2058 2059 2060
    Allow,
    /// Errors are bypassed for bootstrapping. This is required any time
    /// during the build that feature-related lints are set to warn or above
    /// because the build turns on warnings-as-errors and uses lots of unstable
2061
    /// features. As a result, this is always required for building Rust itself.
2062 2063 2064
    Cheat
}

T
Tim Neumann 已提交
2065 2066 2067 2068
impl UnstableFeatures {
    pub fn from_environment() -> UnstableFeatures {
        // Whether this is a feature-staged build, i.e. on the beta or stable channel
        let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
2069 2070 2071 2072 2073 2074
        // Whether we should enable unstable features for bootstrapping
        let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
        match (disable_unstable_features, bootstrap) {
            (_, true) => UnstableFeatures::Cheat,
            (true, _) => UnstableFeatures::Disallow,
            (false, _) => UnstableFeatures::Allow
T
Tim Neumann 已提交
2075 2076
        }
    }
2077 2078 2079 2080 2081 2082 2083

    pub fn is_nightly_build(&self) -> bool {
        match *self {
            UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
            _ => false,
        }
    }
T
Tim Neumann 已提交
2084 2085
}

2086
fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
2087 2088 2089 2090 2091 2092 2093 2094 2095 2096
                        unstable: UnstableFeatures) {
    let allow_features = match unstable {
        UnstableFeatures::Allow => true,
        UnstableFeatures::Disallow => false,
        UnstableFeatures::Cheat => true
    };
    if !allow_features {
        for attr in &krate.attrs {
            if attr.check_name("feature") {
                let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
G
ggomez 已提交
2097
                span_err!(span_handler, attr.span, E0554,
2098
                          "#![feature] may not be used on the {} release channel",
G
ggomez 已提交
2099
                          release_channel);
2100 2101 2102 2103
            }
        }
    }
}