]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/feature_gate.rs
Stabilize match_default_bindings
[rust.git] / src / libsyntax / feature_gate.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Feature gating
12 //!
13 //! This module implements the gating necessary for preventing certain compiler
14 //! features from being used by default. This module will crawl a pre-expanded
15 //! AST to ensure that there are no features which are used that are not
16 //! enabled.
17 //!
18 //! Features are enabled in programs via the crate-level attributes of
19 //! `#![feature(...)]` with a comma-separated list of features.
20 //!
21 //! For the purpose of future feature-tracking, once code for detection of feature
22 //! gate usage is added, *do not remove it again* even once the feature
23 //! becomes stable.
24
25 use self::AttributeType::*;
26 use self::AttributeGate::*;
27
28 use abi::Abi;
29 use ast::{self, NodeId, PatKind, RangeEnd};
30 use attr;
31 use edition::Edition;
32 use codemap::Spanned;
33 use syntax_pos::{Span, DUMMY_SP};
34 use errors::{DiagnosticBuilder, Handler, FatalError};
35 use visit::{self, FnKind, Visitor};
36 use parse::ParseSess;
37 use symbol::{keywords, Symbol};
38
39 use std::{env, path};
40
41 macro_rules! set {
42     (proc_macro) => {{
43         fn f(features: &mut Features, span: Span) {
44             features.declared_lib_features.push((Symbol::intern("proc_macro"), span));
45             features.proc_macro = true;
46         }
47         f as fn(&mut Features, Span)
48     }};
49     ($field: ident) => {{
50         fn f(features: &mut Features, _: Span) {
51             features.$field = true;
52         }
53         f as fn(&mut Features, Span)
54     }}
55 }
56
57 macro_rules! declare_features {
58     ($((active, $feature: ident, $ver: expr, $issue: expr, $edition: expr),)+) => {
59         /// Represents active features that are currently being implemented or
60         /// currently being considered for addition/removal.
61         const ACTIVE_FEATURES:
62                 &'static [(&'static str, &'static str, Option<u32>,
63                            Option<Edition>, fn(&mut Features, Span))] =
64             &[$((stringify!($feature), $ver, $issue, $edition, set!($feature))),+];
65
66         /// A set of features to be used by later passes.
67         #[derive(Clone)]
68         pub struct Features {
69             /// `#![feature]` attrs for stable language features, for error reporting
70             pub declared_stable_lang_features: Vec<(Symbol, Span)>,
71             /// `#![feature]` attrs for non-language (library) features
72             pub declared_lib_features: Vec<(Symbol, Span)>,
73             $(pub $feature: bool),+
74         }
75
76         impl Features {
77             pub fn new() -> Features {
78                 Features {
79                     declared_stable_lang_features: Vec::new(),
80                     declared_lib_features: Vec::new(),
81                     $($feature: false),+
82                 }
83             }
84
85             pub fn walk_feature_fields<F>(&self, mut f: F)
86                 where F: FnMut(&str, bool)
87             {
88                 $(f(stringify!($feature), self.$feature);)+
89             }
90         }
91     };
92
93     ($((removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => {
94         /// Represents unstable features which have since been removed (it was once Active)
95         const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
96             $((stringify!($feature), $ver, $issue)),+
97         ];
98     };
99
100     ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => {
101         /// Represents stable features which have since been removed (it was once Accepted)
102         const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
103             $((stringify!($feature), $ver, $issue)),+
104         ];
105     };
106
107     ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => {
108         /// Those language feature has since been Accepted (it was once Active)
109         const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
110             $((stringify!($feature), $ver, $issue)),+
111         ];
112     }
113 }
114
115 // If you change this, please modify src/doc/unstable-book as well.
116 //
117 // Don't ever remove anything from this list; set them to 'Removed'.
118 //
119 // The version numbers here correspond to the version in which the current status
120 // was set. This is most important for knowing when a particular feature became
121 // stable (active).
122 //
123 // NB: tools/tidy/src/features.rs parses this information directly out of the
124 // source, so take care when modifying it.
125
126 declare_features! (
127     (active, asm, "1.0.0", Some(29722), None),
128     (active, concat_idents, "1.0.0", Some(29599), None),
129     (active, link_args, "1.0.0", Some(29596), None),
130     (active, log_syntax, "1.0.0", Some(29598), None),
131     (active, non_ascii_idents, "1.0.0", Some(28979), None),
132     (active, plugin_registrar, "1.0.0", Some(29597), None),
133     (active, thread_local, "1.0.0", Some(29594), None),
134     (active, trace_macros, "1.0.0", Some(29598), None),
135
136     // rustc internal, for now:
137     (active, intrinsics, "1.0.0", None, None),
138     (active, lang_items, "1.0.0", None, None),
139
140     (active, link_llvm_intrinsics, "1.0.0", Some(29602), None),
141     (active, linkage, "1.0.0", Some(29603), None),
142     (active, quote, "1.0.0", Some(29601), None),
143
144
145     // rustc internal
146     (active, rustc_diagnostic_macros, "1.0.0", None, None),
147     (active, rustc_const_unstable, "1.0.0", None, None),
148     (active, box_syntax, "1.0.0", Some(27779), None),
149     (active, placement_in_syntax, "1.0.0", Some(27779), None),
150     (active, unboxed_closures, "1.0.0", Some(29625), None),
151
152     (active, fundamental, "1.0.0", Some(29635), None),
153     (active, main, "1.0.0", Some(29634), None),
154     (active, needs_allocator, "1.4.0", Some(27389), None),
155     (active, on_unimplemented, "1.0.0", Some(29628), None),
156     (active, plugin, "1.0.0", Some(29597), None),
157     (active, simd_ffi, "1.0.0", Some(27731), None),
158     (active, start, "1.0.0", Some(29633), None),
159     (active, structural_match, "1.8.0", Some(31434), None),
160     (active, panic_runtime, "1.10.0", Some(32837), None),
161     (active, needs_panic_runtime, "1.10.0", Some(32837), None),
162
163     // OIBIT specific features
164     (active, optin_builtin_traits, "1.0.0", Some(13231), None),
165
166     // macro re-export needs more discussion and stabilization
167     (active, macro_reexport, "1.0.0", Some(29638), None),
168
169     // Allows use of #[staged_api]
170     // rustc internal
171     (active, staged_api, "1.0.0", None, None),
172
173     // Allows using #![no_core]
174     (active, no_core, "1.3.0", Some(29639), None),
175
176     // Allows using `box` in patterns; RFC 469
177     (active, box_patterns, "1.0.0", Some(29641), None),
178
179     // Allows using the unsafe_destructor_blind_to_params attribute;
180     // RFC 1238
181     (active, dropck_parametricity, "1.3.0", Some(28498), None),
182
183     // Allows using the may_dangle attribute; RFC 1327
184     (active, dropck_eyepatch, "1.10.0", Some(34761), None),
185
186     // Allows the use of custom attributes; RFC 572
187     (active, custom_attribute, "1.0.0", Some(29642), None),
188
189     // Allows the use of #[derive(Anything)] as sugar for
190     // #[derive_Anything].
191     (active, custom_derive, "1.0.0", Some(29644), None),
192
193     // Allows the use of rustc_* attributes; RFC 572
194     (active, rustc_attrs, "1.0.0", Some(29642), None),
195
196     // Allows the use of non lexical lifetimes; RFC 2094
197     (active, nll, "1.0.0", Some(43234), None),
198
199     // Allows the use of #[allow_internal_unstable]. This is an
200     // attribute on macro_rules! and can't use the attribute handling
201     // below (it has to be checked before expansion possibly makes
202     // macros disappear).
203     //
204     // rustc internal
205     (active, allow_internal_unstable, "1.0.0", None, None),
206
207     // Allows the use of #[allow_internal_unsafe]. This is an
208     // attribute on macro_rules! and can't use the attribute handling
209     // below (it has to be checked before expansion possibly makes
210     // macros disappear).
211     //
212     // rustc internal
213     (active, allow_internal_unsafe, "1.0.0", None, None),
214
215     // #23121. Array patterns have some hazards yet.
216     (active, slice_patterns, "1.0.0", Some(23121), None),
217
218     // Allows the definition of `const fn` functions.
219     (active, const_fn, "1.2.0", Some(24111), None),
220
221     // Allows using #[prelude_import] on glob `use` items.
222     //
223     // rustc internal
224     (active, prelude_import, "1.2.0", None, None),
225
226     // Allows default type parameters to influence type inference.
227     (active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
228
229     // Allows associated type defaults
230     (active, associated_type_defaults, "1.2.0", Some(29661), None),
231
232     // allow `repr(simd)`, and importing the various simd intrinsics
233     (active, repr_simd, "1.4.0", Some(27731), None),
234
235     // Allows cfg(target_feature = "...").
236     (active, cfg_target_feature, "1.4.0", Some(29717), None),
237
238     // allow `extern "platform-intrinsic" { ... }`
239     (active, platform_intrinsics, "1.4.0", Some(27731), None),
240
241     // allow `#[unwind(..)]`
242     // rust runtime internal
243     (active, unwind_attributes, "1.4.0", None, None),
244
245     // allow the use of `#[naked]` on functions.
246     (active, naked_functions, "1.9.0", Some(32408), None),
247
248     // allow `#[no_debug]`
249     (active, no_debug, "1.5.0", Some(29721), None),
250
251     // allow `#[omit_gdb_pretty_printer_section]`
252     // rustc internal.
253     (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
254
255     // Allows cfg(target_vendor = "...").
256     (active, cfg_target_vendor, "1.5.0", Some(29718), None),
257
258     // Allow attributes on expressions and non-item statements
259     (active, stmt_expr_attributes, "1.6.0", Some(15701), None),
260
261     // allow using type ascription in expressions
262     (active, type_ascription, "1.6.0", Some(23416), None),
263
264     // Allows cfg(target_thread_local)
265     (active, cfg_target_thread_local, "1.7.0", Some(29594), None),
266
267     // rustc internal
268     (active, abi_vectorcall, "1.7.0", None, None),
269
270     // X..Y patterns
271     (active, exclusive_range_pattern, "1.11.0", Some(37854), None),
272
273     // impl specialization (RFC 1210)
274     (active, specialization, "1.7.0", Some(31844), None),
275
276     // Allows cfg(target_has_atomic = "...").
277     (active, cfg_target_has_atomic, "1.9.0", Some(32976), None),
278
279     // Allows exhaustive pattern matching on types that contain uninhabited types.
280     (active, exhaustive_patterns, "1.13.0", None, None),
281
282     // Allows all literals in attribute lists and values of key-value pairs.
283     (active, attr_literals, "1.13.0", Some(34981), None),
284
285     // Allows untagged unions `union U { ... }`
286     (active, untagged_unions, "1.13.0", Some(32836), None),
287
288     // Used to identify the `compiler_builtins` crate
289     // rustc internal
290     (active, compiler_builtins, "1.13.0", None, None),
291
292     // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
293     (active, generic_param_attrs, "1.11.0", Some(34761), None),
294
295     // Allows #[link(..., cfg(..))]
296     (active, link_cfg, "1.14.0", Some(37406), None),
297
298     (active, use_extern_macros, "1.15.0", Some(35896), None),
299
300     // Allows #[target_feature(...)]
301     (active, target_feature, "1.15.0", None, None),
302
303     // `extern "ptx-*" fn()`
304     (active, abi_ptx, "1.15.0", None, None),
305
306     // The `repr(i128)` annotation for enums
307     (active, repr128, "1.16.0", Some(35118), None),
308
309     // The `unadjusted` ABI. Perma unstable.
310     (active, abi_unadjusted, "1.16.0", None, None),
311
312     // Procedural macros 2.0.
313     (active, proc_macro, "1.16.0", Some(38356), None),
314
315     // Declarative macros 2.0 (`macro`).
316     (active, decl_macro, "1.17.0", Some(39412), None),
317
318     // Allows #[link(kind="static-nobundle"...]
319     (active, static_nobundle, "1.16.0", Some(37403), None),
320
321     // `extern "msp430-interrupt" fn()`
322     (active, abi_msp430_interrupt, "1.16.0", Some(38487), None),
323
324     // Used to identify crates that contain sanitizer runtimes
325     // rustc internal
326     (active, sanitizer_runtime, "1.17.0", None, None),
327
328     // Used to identify crates that contain the profiler runtime
329     // rustc internal
330     (active, profiler_runtime, "1.18.0", None, None),
331
332     // `extern "x86-interrupt" fn()`
333     (active, abi_x86_interrupt, "1.17.0", Some(40180), None),
334
335
336     // Allows the `catch {...}` expression
337     (active, catch_expr, "1.17.0", Some(31436), None),
338
339     // Used to preserve symbols (see llvm.used)
340     (active, used, "1.18.0", Some(40289), None),
341
342     // Allows module-level inline assembly by way of global_asm!()
343     (active, global_asm, "1.18.0", Some(35119), None),
344
345     // Allows overlapping impls of marker traits
346     (active, overlapping_marker_traits, "1.18.0", Some(29864), None),
347
348     // Allows use of the :vis macro fragment specifier
349     (active, macro_vis_matcher, "1.18.0", Some(41022), None),
350
351     // rustc internal
352     (active, abi_thiscall, "1.19.0", None, None),
353
354     // Allows a test to fail without failing the whole suite
355     (active, allow_fail, "1.19.0", Some(42219), None),
356
357     // Allows unsized tuple coercion.
358     (active, unsized_tuple_coercion, "1.20.0", Some(42877), None),
359
360     // Generators
361     (active, generators, "1.21.0", None, None),
362
363     // Trait aliases
364     (active, trait_alias, "1.24.0", Some(41517), None),
365
366     // global allocators and their internals
367     (active, global_allocator, "1.20.0", None, None),
368     (active, allocator_internals, "1.20.0", None, None),
369
370     // #[doc(cfg(...))]
371     (active, doc_cfg, "1.21.0", Some(43781), None),
372     // #[doc(masked)]
373     (active, doc_masked, "1.21.0", Some(44027), None),
374     // #[doc(spotlight)]
375     (active, doc_spotlight, "1.22.0", Some(45040), None),
376     // #[doc(include="some-file")]
377     (active, external_doc, "1.22.0", Some(44732), None),
378
379     // allow `#[must_use]` on functions and comparison operators (RFC 1940)
380     (active, fn_must_use, "1.21.0", Some(43302), None),
381
382     // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
383     (active, non_exhaustive, "1.22.0", Some(44109), None),
384
385     // allow `'_` placeholder lifetimes
386     (active, underscore_lifetimes, "1.22.0", Some(44524), None),
387
388     // Trait object syntax with `dyn` prefix
389     (active, dyn_trait, "1.22.0", Some(44662), Some(Edition::Edition2018)),
390
391     // `crate` as visibility modifier, synonymous to `pub(crate)`
392     (active, crate_visibility_modifier, "1.23.0", Some(45388), None),
393
394     // extern types
395     (active, extern_types, "1.23.0", Some(43467), None),
396
397     // Allow trait methods with arbitrary self types
398     (active, arbitrary_self_types, "1.23.0", Some(44874), None),
399
400     // `crate` in paths
401     (active, crate_in_paths, "1.23.0", Some(45477), None),
402
403     // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`)
404     (active, in_band_lifetimes, "1.23.0", Some(44524), None),
405
406     // generic associated types (RFC 1598)
407     (active, generic_associated_types, "1.23.0", Some(44265), None),
408
409     // Resolve absolute paths as paths from other crates
410     (active, extern_absolute_paths, "1.24.0", Some(44660), None),
411
412     // `foo.rs` as an alternative to `foo/mod.rs`
413     (active, non_modrs_mods, "1.24.0", Some(44660), None),
414
415     // Termination trait in tests (RFC 1937)
416     (active, termination_trait_test, "1.24.0", Some(48854), None),
417
418     // Allows use of the :lifetime macro fragment specifier
419     (active, macro_lifetime_matcher, "1.24.0", Some(46895), None),
420
421     // `extern` in paths
422     (active, extern_in_paths, "1.23.0", Some(44660), None),
423
424     // Allows `#[repr(transparent)]` attribute on newtype structs
425     (active, repr_transparent, "1.25.0", Some(43036), None),
426
427     // Use `?` as the Kleene "at most one" operator
428     (active, macro_at_most_once_rep, "1.25.0", Some(48075), None),
429
430     // Multiple patterns with `|` in `if let` and `while let`
431     (active, if_while_or_patterns, "1.26.0", Some(48215), None),
432
433     // Parentheses in patterns
434     (active, pattern_parentheses, "1.26.0", None, None),
435
436     // `use path as _;` and `extern crate c as _;`
437     (active, underscore_imports, "1.26.0", Some(48216), None),
438
439     // The #[wasm_custom_section] attribute
440     (active, wasm_custom_section, "1.26.0", None, None),
441
442     // The #![wasm_import_module] attribute
443     (active, wasm_import_module, "1.26.0", None, None),
444
445     // Allows keywords to be escaped for use as identifiers
446     (active, raw_identifiers, "1.26.0", Some(48589), None),
447 );
448
449 declare_features! (
450     (removed, import_shadowing, "1.0.0", None, None),
451     (removed, managed_boxes, "1.0.0", None, None),
452     // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
453     (removed, negate_unsigned, "1.0.0", Some(29645), None),
454     (removed, reflect, "1.0.0", Some(27749), None),
455     // A way to temporarily opt out of opt in copy. This will *never* be accepted.
456     (removed, opt_out_copy, "1.0.0", None, None),
457     (removed, quad_precision_float, "1.0.0", None, None),
458     (removed, struct_inherit, "1.0.0", None, None),
459     (removed, test_removed_feature, "1.0.0", None, None),
460     (removed, visible_private_types, "1.0.0", None, None),
461     (removed, unsafe_no_drop_flag, "1.0.0", None, None),
462     // Allows using items which are missing stability attributes
463     // rustc internal
464     (removed, unmarked_api, "1.0.0", None, None),
465     (removed, pushpop_unsafe, "1.2.0", None, None),
466     (removed, allocator, "1.0.0", None, None),
467     // Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]`
468     (removed, simd, "1.0.0", Some(27731), None),
469     // Merged into `slice_patterns`
470     (removed, advanced_slice_patterns, "1.0.0", Some(23121), None),
471 );
472
473 declare_features! (
474     (stable_removed, no_stack_check, "1.0.0", None, None),
475 );
476
477 declare_features! (
478     (accepted, associated_types, "1.0.0", None, None),
479     // allow overloading augmented assignment operations like `a += b`
480     (accepted, augmented_assignments, "1.8.0", Some(28235), None),
481     // allow empty structs and enum variants with braces
482     (accepted, braced_empty_structs, "1.8.0", Some(29720), None),
483     // Allows indexing into constant arrays.
484     (accepted, const_indexing, "1.24.0", Some(29947), None),
485     (accepted, default_type_params, "1.0.0", None, None),
486     (accepted, globs, "1.0.0", None, None),
487     (accepted, if_let, "1.0.0", None, None),
488     // A temporary feature gate used to enable parser extensions needed
489     // to bootstrap fix for #5723.
490     (accepted, issue_5723_bootstrap, "1.0.0", None, None),
491     (accepted, macro_rules, "1.0.0", None, None),
492     // Allows using #![no_std]
493     (accepted, no_std, "1.6.0", None, None),
494     (accepted, slicing_syntax, "1.0.0", None, None),
495     (accepted, struct_variant, "1.0.0", None, None),
496     // These are used to test this portion of the compiler, they don't actually
497     // mean anything
498     (accepted, test_accepted_feature, "1.0.0", None, None),
499     (accepted, tuple_indexing, "1.0.0", None, None),
500     // Allows macros to appear in the type position.
501     (accepted, type_macros, "1.13.0", Some(27245), None),
502     (accepted, while_let, "1.0.0", None, None),
503     // Allows `#[deprecated]` attribute
504     (accepted, deprecated, "1.9.0", Some(29935), None),
505     // `expr?`
506     (accepted, question_mark, "1.13.0", Some(31436), None),
507     // Allows `..` in tuple (struct) patterns
508     (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None),
509     (accepted, item_like_imports, "1.15.0", Some(35120), None),
510     // Allows using `Self` and associated types in struct expressions and patterns.
511     (accepted, more_struct_aliases, "1.16.0", Some(37544), None),
512     // elide `'static` lifetimes in `static`s and `const`s
513     (accepted, static_in_const, "1.17.0", Some(35897), None),
514     // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
515     (accepted, field_init_shorthand, "1.17.0", Some(37340), None),
516     // Allows the definition recursive static items.
517     (accepted, static_recursion, "1.17.0", Some(29719), None),
518     // pub(restricted) visibilities (RFC 1422)
519     (accepted, pub_restricted, "1.18.0", Some(32409), None),
520     // The #![windows_subsystem] attribute
521     (accepted, windows_subsystem, "1.18.0", Some(37499), None),
522     // Allows `break {expr}` with a value inside `loop`s.
523     (accepted, loop_break_value, "1.19.0", Some(37339), None),
524     // Permits numeric fields in struct expressions and patterns.
525     (accepted, relaxed_adts, "1.19.0", Some(35626), None),
526     // Coerces non capturing closures to function pointers
527     (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
528     // Allows attributes on struct literal fields.
529     (accepted, struct_field_attributes, "1.20.0", Some(38814), None),
530     // Allows the definition of associated constants in `trait` or `impl`
531     // blocks.
532     (accepted, associated_consts, "1.20.0", Some(29646), None),
533     // Usage of the `compile_error!` macro
534     (accepted, compile_error, "1.20.0", Some(40872), None),
535     // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
536     (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None),
537     // Allow Drop types in constants (RFC 1440)
538     (accepted, drop_types_in_const, "1.22.0", Some(33156), None),
539     // Allows the sysV64 ABI to be specified on all platforms
540     // instead of just the platforms on which it is the C ABI
541     (accepted, abi_sysv64, "1.24.0", Some(36167), None),
542     // Allows `repr(align(16))` struct attribute (RFC 1358)
543     (accepted, repr_align, "1.25.0", Some(33626), None),
544     // allow '|' at beginning of match arms (RFC 1925)
545     (accepted, match_beginning_vert, "1.25.0", Some(44101), None),
546     // Nested groups in `use` (RFC 2128)
547     (accepted, use_nested_groups, "1.25.0", Some(44494), None),
548     // a..=b and ..=b
549     (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None),
550     // allow `..=` in patterns (RFC 1192)
551     (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None),
552     // Termination trait in main (RFC 1937)
553     (accepted, termination_trait, "1.26.0", Some(43301), None),
554     // Copy/Clone closures (RFC 2132)
555     (accepted, clone_closures, "1.26.0", Some(44490), None),
556     (accepted, copy_closures, "1.26.0", Some(44490), None),
557     // Allows `impl Trait` in function arguments.
558     (accepted, universal_impl_trait, "1.26.0", Some(34511), None),
559     // Allows `impl Trait` in function return types.
560     (accepted, conservative_impl_trait, "1.26.0", Some(34511), None),
561     // The `i128` type
562     (accepted, i128_type, "1.26.0", Some(35118), None),
563     // Default match binding modes (RFC 2005)
564     (accepted, match_default_bindings, "1.26.0", Some(42640), None),
565 );
566
567 // If you change this, please modify src/doc/unstable-book as well. You must
568 // move that documentation into the relevant place in the other docs, and
569 // remove the chapter on the flag.
570
571 #[derive(PartialEq, Copy, Clone, Debug)]
572 pub enum AttributeType {
573     /// Normal, builtin attribute that is consumed
574     /// by the compiler before the unused_attribute check
575     Normal,
576
577     /// Builtin attribute that may not be consumed by the compiler
578     /// before the unused_attribute check. These attributes
579     /// will be ignored by the unused_attribute lint
580     Whitelisted,
581
582     /// Builtin attribute that is only allowed at the crate level
583     CrateLevel,
584 }
585
586 pub enum AttributeGate {
587     /// Is gated by a given feature gate, reason
588     /// and function to check if enabled
589     Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
590
591     /// Ungated attribute, can be used on all release channels
592     Ungated,
593 }
594
595 impl AttributeGate {
596     fn is_deprecated(&self) -> bool {
597         match *self {
598             Gated(Stability::Deprecated(_), ..) => true,
599             _ => false,
600         }
601     }
602 }
603
604 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
605 pub enum Stability {
606     Unstable,
607     // Argument is tracking issue link.
608     Deprecated(&'static str),
609 }
610
611 // fn() is not Debug
612 impl ::std::fmt::Debug for AttributeGate {
613     fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
614         match *self {
615             Gated(ref stab, name, expl, _) =>
616                 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
617             Ungated => write!(fmt, "Ungated")
618         }
619     }
620 }
621
622 macro_rules! cfg_fn {
623     ($field: ident) => {{
624         fn f(features: &Features) -> bool {
625             features.$field
626         }
627         f as fn(&Features) -> bool
628     }}
629 }
630
631 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
632     BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
633 }
634
635 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
636     BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
637 }
638
639 // Attributes that have a special meaning to rustc or rustdoc
640 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
641     // Normal attributes
642
643     ("warn", Normal, Ungated),
644     ("allow", Normal, Ungated),
645     ("forbid", Normal, Ungated),
646     ("deny", Normal, Ungated),
647
648     ("macro_reexport", Normal, Ungated),
649     ("macro_use", Normal, Ungated),
650     ("macro_export", Normal, Ungated),
651     ("plugin_registrar", Normal, Ungated),
652
653     ("cfg", Normal, Ungated),
654     ("cfg_attr", Normal, Ungated),
655     ("main", Normal, Ungated),
656     ("start", Normal, Ungated),
657     ("test", Normal, Ungated),
658     ("bench", Normal, Ungated),
659     ("repr", Normal, Ungated),
660     ("path", Normal, Ungated),
661     ("abi", Normal, Ungated),
662     ("automatically_derived", Normal, Ungated),
663     ("no_mangle", Normal, Ungated),
664     ("no_link", Normal, Ungated),
665     ("derive", Normal, Ungated),
666     ("should_panic", Normal, Ungated),
667     ("ignore", Normal, Ungated),
668     ("no_implicit_prelude", Normal, Ungated),
669     ("reexport_test_harness_main", Normal, Ungated),
670     ("link_args", Normal, Gated(Stability::Unstable,
671                                 "link_args",
672                                 "the `link_args` attribute is experimental and not \
673                                  portable across platforms, it is recommended to \
674                                  use `#[link(name = \"foo\")] instead",
675                                 cfg_fn!(link_args))),
676     ("macro_escape", Normal, Ungated),
677
678     // RFC #1445.
679     ("structural_match", Whitelisted, Gated(Stability::Unstable,
680                                             "structural_match",
681                                             "the semantics of constant patterns is \
682                                              not yet settled",
683                                             cfg_fn!(structural_match))),
684
685     // RFC #2008
686     ("non_exhaustive", Whitelisted, Gated(Stability::Unstable,
687                                           "non_exhaustive",
688                                           "non exhaustive is an experimental feature",
689                                           cfg_fn!(non_exhaustive))),
690
691     ("plugin", CrateLevel, Gated(Stability::Unstable,
692                                  "plugin",
693                                  "compiler plugins are experimental \
694                                   and possibly buggy",
695                                  cfg_fn!(plugin))),
696
697     ("no_std", CrateLevel, Ungated),
698     ("no_core", CrateLevel, Gated(Stability::Unstable,
699                                   "no_core",
700                                   "no_core is experimental",
701                                   cfg_fn!(no_core))),
702     ("lang", Normal, Gated(Stability::Unstable,
703                            "lang_items",
704                            "language items are subject to change",
705                            cfg_fn!(lang_items))),
706     ("linkage", Whitelisted, Gated(Stability::Unstable,
707                                    "linkage",
708                                    "the `linkage` attribute is experimental \
709                                     and not portable across platforms",
710                                    cfg_fn!(linkage))),
711     ("thread_local", Whitelisted, Gated(Stability::Unstable,
712                                         "thread_local",
713                                         "`#[thread_local]` is an experimental feature, and does \
714                                          not currently handle destructors.",
715                                         cfg_fn!(thread_local))),
716
717     ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
718                                              "on_unimplemented",
719                                              "the `#[rustc_on_unimplemented]` attribute \
720                                               is an experimental feature",
721                                              cfg_fn!(on_unimplemented))),
722     ("rustc_const_unstable", Normal, Gated(Stability::Unstable,
723                                              "rustc_const_unstable",
724                                              "the `#[rustc_const_unstable]` attribute \
725                                               is an internal feature",
726                                              cfg_fn!(rustc_const_unstable))),
727     ("global_allocator", Normal, Gated(Stability::Unstable,
728                                        "global_allocator",
729                                        "the `#[global_allocator]` attribute is \
730                                         an experimental feature",
731                                        cfg_fn!(global_allocator))),
732     ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
733                                             "allocator_internals",
734                                             "the `#[default_lib_allocator]` \
735                                              attribute is an experimental feature",
736                                             cfg_fn!(allocator_internals))),
737     ("needs_allocator", Normal, Gated(Stability::Unstable,
738                                       "allocator_internals",
739                                       "the `#[needs_allocator]` \
740                                        attribute is an experimental \
741                                        feature",
742                                       cfg_fn!(allocator_internals))),
743     ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
744                                          "panic_runtime",
745                                          "the `#[panic_runtime]` attribute is \
746                                           an experimental feature",
747                                          cfg_fn!(panic_runtime))),
748     ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
749                                                "needs_panic_runtime",
750                                                "the `#[needs_panic_runtime]` \
751                                                 attribute is an experimental \
752                                                 feature",
753                                                cfg_fn!(needs_panic_runtime))),
754     ("rustc_variance", Normal, Gated(Stability::Unstable,
755                                      "rustc_attrs",
756                                      "the `#[rustc_variance]` attribute \
757                                       is just used for rustc unit tests \
758                                       and will never be stable",
759                                      cfg_fn!(rustc_attrs))),
760     ("rustc_regions", Normal, Gated(Stability::Unstable,
761                                     "rustc_attrs",
762                                     "the `#[rustc_regions]` attribute \
763                                      is just used for rustc unit tests \
764                                      and will never be stable",
765                                     cfg_fn!(rustc_attrs))),
766     ("rustc_error", Whitelisted, Gated(Stability::Unstable,
767                                        "rustc_attrs",
768                                        "the `#[rustc_error]` attribute \
769                                         is just used for rustc unit tests \
770                                         and will never be stable",
771                                        cfg_fn!(rustc_attrs))),
772     ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
773                                                  "rustc_attrs",
774                                                  "the `#[rustc_if_this_changed]` attribute \
775                                                   is just used for rustc unit tests \
776                                                   and will never be stable",
777                                                  cfg_fn!(rustc_attrs))),
778     ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
779                                                       "rustc_attrs",
780                                                       "the `#[rustc_if_this_changed]` attribute \
781                                                        is just used for rustc unit tests \
782                                                        and will never be stable",
783                                                       cfg_fn!(rustc_attrs))),
784     ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
785                                        "rustc_attrs",
786                                        "the `#[rustc_dirty]` attribute \
787                                         is just used for rustc unit tests \
788                                         and will never be stable",
789                                        cfg_fn!(rustc_attrs))),
790     ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
791                                        "rustc_attrs",
792                                        "the `#[rustc_clean]` attribute \
793                                         is just used for rustc unit tests \
794                                         and will never be stable",
795                                        cfg_fn!(rustc_attrs))),
796     ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
797                                                   "rustc_attrs",
798                                                   "this attribute \
799                                                    is just used for rustc unit tests \
800                                                    and will never be stable",
801                                                   cfg_fn!(rustc_attrs))),
802     ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
803                                                       "rustc_attrs",
804                                                       "this attribute \
805                                                        is just used for rustc unit tests \
806                                                        and will never be stable",
807                                                       cfg_fn!(rustc_attrs))),
808     ("rustc_serialize_exclude_null", Normal, Gated(Stability::Unstable,
809                                              "rustc_attrs",
810                                              "the `#[rustc_serialize_exclude_null]` attribute \
811                                               is an internal-only feature",
812                                              cfg_fn!(rustc_attrs))),
813     ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable,
814                                                       "rustc_attrs",
815                                                       "this attribute \
816                                                        is just used for rustc unit tests \
817                                                        and will never be stable",
818                                                       cfg_fn!(rustc_attrs))),
819     ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
820                                              "rustc_attrs",
821                                              "internal rustc attributes will never be stable",
822                                              cfg_fn!(rustc_attrs))),
823     ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
824                                            "rustc_attrs",
825                                            "internal rustc attributes will never be stable",
826                                            cfg_fn!(rustc_attrs))),
827     ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
828                                      "rustc_attrs",
829                                      "the `#[rustc_mir]` attribute \
830                                       is just used for rustc unit tests \
831                                       and will never be stable",
832                                      cfg_fn!(rustc_attrs))),
833     ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
834                                                          "rustc_attrs",
835                                                          "the `#[rustc_inherit_overflow_checks]` \
836                                                           attribute is just used to control \
837                                                           overflow checking behavior of several \
838                                                           libcore functions that are inlined \
839                                                           across crates and will never be stable",
840                                                           cfg_fn!(rustc_attrs))),
841
842     ("rustc_dump_program_clauses", Whitelisted, Gated(Stability::Unstable,
843                                                      "rustc_attrs",
844                                                      "the `#[rustc_dump_program_clauses]` \
845                                                       attribute is just used for rustc unit \
846                                                       tests and will never be stable",
847                                                      cfg_fn!(rustc_attrs))),
848
849     // RFC #2094
850     ("nll", Whitelisted, Gated(Stability::Unstable,
851                                "nll",
852                                "Non lexical lifetimes",
853                                cfg_fn!(nll))),
854     ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
855                                              "compiler_builtins",
856                                              "the `#[compiler_builtins]` attribute is used to \
857                                               identify the `compiler_builtins` crate which \
858                                               contains compiler-rt intrinsics and will never be \
859                                               stable",
860                                           cfg_fn!(compiler_builtins))),
861     ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
862                                              "sanitizer_runtime",
863                                              "the `#[sanitizer_runtime]` attribute is used to \
864                                               identify crates that contain the runtime of a \
865                                               sanitizer and will never be stable",
866                                              cfg_fn!(sanitizer_runtime))),
867     ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
868                                              "profiler_runtime",
869                                              "the `#[profiler_runtime]` attribute is used to \
870                                               identify the `profiler_builtins` crate which \
871                                               contains the profiler runtime and will never be \
872                                               stable",
873                                              cfg_fn!(profiler_runtime))),
874
875     ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
876                                               "allow_internal_unstable",
877                                               EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
878                                               cfg_fn!(allow_internal_unstable))),
879
880     ("allow_internal_unsafe", Normal, Gated(Stability::Unstable,
881                                             "allow_internal_unsafe",
882                                             EXPLAIN_ALLOW_INTERNAL_UNSAFE,
883                                             cfg_fn!(allow_internal_unsafe))),
884
885     ("fundamental", Whitelisted, Gated(Stability::Unstable,
886                                        "fundamental",
887                                        "the `#[fundamental]` attribute \
888                                         is an experimental feature",
889                                        cfg_fn!(fundamental))),
890
891     ("proc_macro_derive", Normal, Ungated),
892
893     ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
894                                                    "rustc_attrs",
895                                                    "internal implementation detail",
896                                                    cfg_fn!(rustc_attrs))),
897
898     // FIXME: #14408 whitelist docs since rustdoc looks at them
899     ("doc", Whitelisted, Ungated),
900
901     // FIXME: #14406 these are processed in trans, which happens after the
902     // lint pass
903     ("cold", Whitelisted, Ungated),
904     ("naked", Whitelisted, Gated(Stability::Unstable,
905                                  "naked_functions",
906                                  "the `#[naked]` attribute \
907                                   is an experimental feature",
908                                  cfg_fn!(naked_functions))),
909     ("target_feature", Whitelisted, Gated(
910         Stability::Unstable, "target_feature",
911         "the `#[target_feature]` attribute is an experimental feature",
912         cfg_fn!(target_feature))),
913     ("export_name", Whitelisted, Ungated),
914     ("inline", Whitelisted, Ungated),
915     ("link", Whitelisted, Ungated),
916     ("link_name", Whitelisted, Ungated),
917     ("link_section", Whitelisted, Ungated),
918     ("no_builtins", Whitelisted, Ungated),
919     ("no_mangle", Whitelisted, Ungated),
920     ("no_debug", Whitelisted, Gated(
921         Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
922         "no_debug",
923         "the `#[no_debug]` attribute was an experimental feature that has been \
924          deprecated due to lack of demand",
925         cfg_fn!(no_debug))),
926     ("wasm_import_module", Normal, Gated(Stability::Unstable,
927                                  "wasm_import_module",
928                                  "experimental attribute",
929                                  cfg_fn!(wasm_import_module))),
930     ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
931                                                        "omit_gdb_pretty_printer_section",
932                                                        "the `#[omit_gdb_pretty_printer_section]` \
933                                                         attribute is just used for the Rust test \
934                                                         suite",
935                                                        cfg_fn!(omit_gdb_pretty_printer_section))),
936     ("unsafe_destructor_blind_to_params",
937      Normal,
938      Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
939            "dropck_parametricity",
940            "unsafe_destructor_blind_to_params has been replaced by \
941             may_dangle and will be removed in the future",
942            cfg_fn!(dropck_parametricity))),
943     ("may_dangle",
944      Normal,
945      Gated(Stability::Unstable,
946            "dropck_eyepatch",
947            "may_dangle has unstable semantics and may be removed in the future",
948            cfg_fn!(dropck_eyepatch))),
949     ("unwind", Whitelisted, Gated(Stability::Unstable,
950                                   "unwind_attributes",
951                                   "#[unwind] is experimental",
952                                   cfg_fn!(unwind_attributes))),
953     ("used", Whitelisted, Gated(
954         Stability::Unstable, "used",
955         "the `#[used]` attribute is an experimental feature",
956         cfg_fn!(used))),
957
958     // used in resolve
959     ("prelude_import", Whitelisted, Gated(Stability::Unstable,
960                                           "prelude_import",
961                                           "`#[prelude_import]` is for use by rustc only",
962                                           cfg_fn!(prelude_import))),
963
964     // FIXME: #14407 these are only looked at on-demand so we can't
965     // guarantee they'll have already been checked
966     ("rustc_deprecated", Whitelisted, Ungated),
967     ("must_use", Whitelisted, Ungated),
968     ("stable", Whitelisted, Ungated),
969     ("unstable", Whitelisted, Ungated),
970     ("deprecated", Normal, Ungated),
971
972     ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
973                                         "unboxed_closures",
974                                         "unboxed_closures are still evolving",
975                                         cfg_fn!(unboxed_closures))),
976
977     ("windows_subsystem", Whitelisted, Ungated),
978
979     ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
980                                            "proc_macro",
981                                            "attribute proc macros are currently unstable",
982                                            cfg_fn!(proc_macro))),
983
984     ("proc_macro", Normal, Gated(Stability::Unstable,
985                                  "proc_macro",
986                                  "function-like proc macros are currently unstable",
987                                  cfg_fn!(proc_macro))),
988
989     ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
990                                              "rustc_derive_registrar",
991                                              "used internally by rustc",
992                                              cfg_fn!(rustc_attrs))),
993
994     ("allow_fail", Normal, Gated(Stability::Unstable,
995                                  "allow_fail",
996                                  "allow_fail attribute is currently unstable",
997                                  cfg_fn!(allow_fail))),
998
999     ("rustc_std_internal_symbol", Whitelisted, Gated(Stability::Unstable,
1000                                      "rustc_attrs",
1001                                      "this is an internal attribute that will \
1002                                       never be stable",
1003                                      cfg_fn!(rustc_attrs))),
1004
1005     // whitelists "identity-like" conversion methods to suggest on type mismatch
1006     ("rustc_conversion_suggestion", Whitelisted, Gated(Stability::Unstable,
1007                                                        "rustc_attrs",
1008                                                        "this is an internal attribute that will \
1009                                                         never be stable",
1010                                                        cfg_fn!(rustc_attrs))),
1011
1012     ("rustc_args_required_const", Whitelisted, Gated(Stability::Unstable,
1013                                  "rustc_attrs",
1014                                  "never will be stable",
1015                                  cfg_fn!(rustc_attrs))),
1016
1017     ("wasm_custom_section", Whitelisted, Gated(Stability::Unstable,
1018                                  "wasm_custom_section",
1019                                  "attribute is currently unstable",
1020                                  cfg_fn!(wasm_custom_section))),
1021
1022     // Crate level attributes
1023     ("crate_name", CrateLevel, Ungated),
1024     ("crate_type", CrateLevel, Ungated),
1025     ("crate_id", CrateLevel, Ungated),
1026     ("feature", CrateLevel, Ungated),
1027     ("no_start", CrateLevel, Ungated),
1028     ("no_main", CrateLevel, Ungated),
1029     ("no_builtins", CrateLevel, Ungated),
1030     ("recursion_limit", CrateLevel, Ungated),
1031     ("type_length_limit", CrateLevel, Ungated),
1032 ];
1033
1034 // cfg(...)'s that are feature gated
1035 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
1036     // (name in cfg, feature, function to check if the feature is enabled)
1037     ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
1038     ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
1039     ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
1040     ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
1041 ];
1042
1043 #[derive(Debug, Eq, PartialEq)]
1044 pub struct GatedCfg {
1045     span: Span,
1046     index: usize,
1047 }
1048
1049 impl GatedCfg {
1050     pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
1051         let name = cfg.name().as_str();
1052         GATED_CFGS.iter()
1053                   .position(|info| info.0 == name)
1054                   .map(|idx| {
1055                       GatedCfg {
1056                           span: cfg.span,
1057                           index: idx
1058                       }
1059                   })
1060     }
1061
1062     pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
1063         let (cfg, feature, has_feature) = GATED_CFGS[self.index];
1064         if !has_feature(features) && !self.span.allows_unstable() {
1065             let explain = format!("`cfg({})` is experimental and subject to change", cfg);
1066             emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
1067         }
1068     }
1069 }
1070
1071 struct Context<'a> {
1072     features: &'a Features,
1073     parse_sess: &'a ParseSess,
1074     plugin_attributes: &'a [(String, AttributeType)],
1075 }
1076
1077 macro_rules! gate_feature_fn {
1078     ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
1079         let (cx, has_feature, span,
1080              name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
1081         let has_feature: bool = has_feature(&$cx.features);
1082         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
1083         if !has_feature && !span.allows_unstable() {
1084             leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
1085                 .emit();
1086         }
1087     }}
1088 }
1089
1090 macro_rules! gate_feature {
1091     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
1092         gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
1093                          stringify!($feature), $explain, GateStrength::Hard)
1094     };
1095     ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
1096         gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
1097                          stringify!($feature), $explain, $level)
1098     };
1099 }
1100
1101 impl<'a> Context<'a> {
1102     fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
1103         debug!("check_attribute(attr = {:?})", attr);
1104         let name = unwrap_or!(attr.name(), return).as_str();
1105         for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
1106             if name == n {
1107                 if let Gated(_, name, desc, ref has_feature) = *gateage {
1108                     gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
1109                 } else if name == "doc" {
1110                     if let Some(content) = attr.meta_item_list() {
1111                         if content.iter().any(|c| c.check_name("include")) {
1112                             gate_feature!(self, external_doc, attr.span,
1113                                 "#[doc(include = \"...\")] is experimental"
1114                             );
1115                         }
1116                     }
1117                 }
1118                 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
1119                 return;
1120             }
1121         }
1122         for &(ref n, ref ty) in self.plugin_attributes {
1123             if attr.path == &**n {
1124                 // Plugins can't gate attributes, so we don't check for it
1125                 // unlike the code above; we only use this loop to
1126                 // short-circuit to avoid the checks below
1127                 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
1128                 return;
1129             }
1130         }
1131         if name.starts_with("rustc_") {
1132             gate_feature!(self, rustc_attrs, attr.span,
1133                           "unless otherwise specified, attributes \
1134                            with the prefix `rustc_` \
1135                            are reserved for internal compiler diagnostics");
1136         } else if name.starts_with("derive_") {
1137             gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
1138         } else if !attr::is_known(attr) {
1139             // Only run the custom attribute lint during regular
1140             // feature gate checking. Macro gating runs
1141             // before the plugin attributes are registered
1142             // so we skip this then
1143             if !is_macro {
1144                 gate_feature!(self, custom_attribute, attr.span,
1145                               &format!("The attribute `{}` is currently \
1146                                         unknown to the compiler and \
1147                                         may have meaning \
1148                                         added to it in the future",
1149                                        attr.path));
1150             }
1151         }
1152     }
1153 }
1154
1155 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
1156     let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
1157     cx.check_attribute(attr, true);
1158 }
1159
1160 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
1161     ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
1162 }
1163
1164 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
1165     if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
1166         let issue = info.2;
1167         // FIXME (#28244): enforce that active features have issue numbers
1168         // assert!(issue.is_some())
1169         issue
1170     } else {
1171         // search in Accepted, Removed, or Stable Removed features
1172         let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
1173             .find(|t| t.0 == feature);
1174         match found {
1175             Some(&(_, _, issue)) => issue,
1176             None => panic!("Feature `{}` is not declared anywhere", feature),
1177         }
1178     }
1179 }
1180
1181 pub enum GateIssue {
1182     Language,
1183     Library(Option<u32>)
1184 }
1185
1186 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1187 pub enum GateStrength {
1188     /// A hard error. (Most feature gates should use this.)
1189     Hard,
1190     /// Only a warning. (Use this only as backwards-compatibility demands.)
1191     Soft,
1192 }
1193
1194 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
1195                         explain: &str) {
1196     feature_err(sess, feature, span, issue, explain).emit();
1197 }
1198
1199 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1200                        explain: &str) -> DiagnosticBuilder<'a> {
1201     leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
1202 }
1203
1204 fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
1205                            explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
1206     let diag = &sess.span_diagnostic;
1207
1208     let issue = match issue {
1209         GateIssue::Language => find_lang_feature_issue(feature),
1210         GateIssue::Library(lib) => lib,
1211     };
1212
1213     let explanation = if let Some(n) = issue {
1214         format!("{} (see issue #{})", explain, n)
1215     } else {
1216         explain.to_owned()
1217     };
1218
1219     let mut err = match level {
1220         GateStrength::Hard => {
1221             diag.struct_span_err_with_code(span, &explanation, stringify_error_code!(E0658))
1222         }
1223         GateStrength::Soft => diag.struct_span_warn(span, &explanation),
1224     };
1225
1226     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1227     if sess.unstable_features.is_nightly_build() {
1228         err.help(&format!("add #![feature({})] to the \
1229                            crate attributes to enable",
1230                           feature));
1231     }
1232
1233     // If we're on stable and only emitting a "soft" warning, add a note to
1234     // clarify that the feature isn't "on" (rather than being on but
1235     // warning-worthy).
1236     if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
1237         err.help("a nightly build of the compiler is required to enable this feature");
1238     }
1239
1240     err
1241
1242 }
1243
1244 const EXPLAIN_BOX_SYNTAX: &'static str =
1245     "box expression syntax is experimental; you can call `Box::new` instead.";
1246
1247 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1248     "attributes on non-item statements and expressions are experimental.";
1249
1250 pub const EXPLAIN_ASM: &'static str =
1251     "inline assembly is not stable enough for use and is subject to change";
1252
1253 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1254     "`global_asm!` is not stable enough for use and is subject to change";
1255
1256 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1257     "`log_syntax!` is not stable enough for use and is subject to change";
1258
1259 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1260     "`concat_idents` is not stable enough for use and is subject to change";
1261
1262 pub const EXPLAIN_TRACE_MACROS: &'static str =
1263     "`trace_macros` is not stable enough for use and is subject to change";
1264 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1265     "allow_internal_unstable side-steps feature gating and stability checks";
1266 pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str =
1267     "allow_internal_unsafe side-steps the unsafe_code lint";
1268
1269 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1270     "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1271
1272 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1273     "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1274     Prefer using procedural macro custom derive.";
1275
1276 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1277     "attributes of the form `#[derive_*]` are reserved for the compiler";
1278
1279 pub const EXPLAIN_VIS_MATCHER: &'static str =
1280     ":vis fragment specifier is experimental and subject to change";
1281
1282 pub const EXPLAIN_LIFETIME_MATCHER: &'static str =
1283     ":lifetime fragment specifier is experimental and subject to change";
1284
1285 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1286     "placement-in expression syntax is experimental and subject to change.";
1287
1288 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1289     "Unsized tuple coercion is not stable enough for use and is subject to change";
1290
1291 pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str =
1292     "Using the `?` macro Kleene operator for \"at most one\" repetition is unstable";
1293
1294 struct PostExpansionVisitor<'a> {
1295     context: &'a Context<'a>,
1296 }
1297
1298 macro_rules! gate_feature_post {
1299     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1300         let (cx, span) = ($cx, $span);
1301         if !span.allows_unstable() {
1302             gate_feature!(cx.context, $feature, span, $explain)
1303         }
1304     }};
1305     ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
1306         let (cx, span) = ($cx, $span);
1307         if !span.allows_unstable() {
1308             gate_feature!(cx.context, $feature, span, $explain, $level)
1309         }
1310     }}
1311 }
1312
1313 impl<'a> PostExpansionVisitor<'a> {
1314     fn check_abi(&self, abi: Abi, span: Span) {
1315         match abi {
1316             Abi::RustIntrinsic => {
1317                 gate_feature_post!(&self, intrinsics, span,
1318                                    "intrinsics are subject to change");
1319             },
1320             Abi::PlatformIntrinsic => {
1321                 gate_feature_post!(&self, platform_intrinsics, span,
1322                                    "platform intrinsics are experimental and possibly buggy");
1323             },
1324             Abi::Vectorcall => {
1325                 gate_feature_post!(&self, abi_vectorcall, span,
1326                                    "vectorcall is experimental and subject to change");
1327             },
1328             Abi::Thiscall => {
1329                 gate_feature_post!(&self, abi_thiscall, span,
1330                                    "thiscall is experimental and subject to change");
1331             },
1332             Abi::RustCall => {
1333                 gate_feature_post!(&self, unboxed_closures, span,
1334                                    "rust-call ABI is subject to change");
1335             },
1336             Abi::PtxKernel => {
1337                 gate_feature_post!(&self, abi_ptx, span,
1338                                    "PTX ABIs are experimental and subject to change");
1339             },
1340             Abi::Unadjusted => {
1341                 gate_feature_post!(&self, abi_unadjusted, span,
1342                                    "unadjusted ABI is an implementation detail and perma-unstable");
1343             },
1344             Abi::Msp430Interrupt => {
1345                 gate_feature_post!(&self, abi_msp430_interrupt, span,
1346                                    "msp430-interrupt ABI is experimental and subject to change");
1347             },
1348             Abi::X86Interrupt => {
1349                 gate_feature_post!(&self, abi_x86_interrupt, span,
1350                                    "x86-interrupt ABI is experimental and subject to change");
1351             },
1352             // Stable
1353             Abi::Cdecl |
1354             Abi::Stdcall |
1355             Abi::Fastcall |
1356             Abi::Aapcs |
1357             Abi::Win64 |
1358             Abi::SysV64 |
1359             Abi::Rust |
1360             Abi::C |
1361             Abi::System => {}
1362         }
1363     }
1364 }
1365
1366 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1367     use ast::MetaItemKind::*;
1368     use ast::NestedMetaItemKind::*;
1369
1370     match item.node {
1371         Word => false,
1372         NameValue(ref lit) => !lit.node.is_str(),
1373         List(ref list) => list.iter().any(|li| {
1374             match li.node {
1375                 MetaItem(ref mi) => contains_novel_literal(mi),
1376                 Literal(_) => true,
1377             }
1378         }),
1379     }
1380 }
1381
1382 impl<'a> PostExpansionVisitor<'a> {
1383     fn whole_crate_feature_gates(&mut self, _krate: &ast::Crate) {
1384         for &(ident, span) in &*self.context.parse_sess.non_modrs_mods.borrow() {
1385             if !span.allows_unstable() {
1386                 let cx = &self.context;
1387                 let level = GateStrength::Hard;
1388                 let has_feature = cx.features.non_modrs_mods;
1389                 let name = "non_modrs_mods";
1390                 debug!("gate_feature(feature = {:?}, span = {:?}); has? {}",
1391                         name, span, has_feature);
1392
1393                 if !has_feature && !span.allows_unstable() {
1394                     leveled_feature_err(
1395                         cx.parse_sess, name, span, GateIssue::Language,
1396                         "mod statements in non-mod.rs files are unstable", level
1397                     )
1398                     .help(&format!("on stable builds, rename this file to {}{}mod.rs",
1399                                    ident, path::MAIN_SEPARATOR))
1400                     .emit();
1401                 }
1402             }
1403         }
1404     }
1405 }
1406
1407 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1408     fn visit_attribute(&mut self, attr: &ast::Attribute) {
1409         if !attr.span.allows_unstable() {
1410             // check for gated attributes
1411             self.context.check_attribute(attr, false);
1412         }
1413
1414         if attr.check_name("doc") {
1415             if let Some(content) = attr.meta_item_list() {
1416                 if content.len() == 1 && content[0].check_name("cfg") {
1417                     gate_feature_post!(&self, doc_cfg, attr.span,
1418                         "#[doc(cfg(...))] is experimental"
1419                     );
1420                 } else if content.iter().any(|c| c.check_name("masked")) {
1421                     gate_feature_post!(&self, doc_masked, attr.span,
1422                         "#[doc(masked)] is experimental"
1423                     );
1424                 } else if content.iter().any(|c| c.check_name("spotlight")) {
1425                     gate_feature_post!(&self, doc_spotlight, attr.span,
1426                         "#[doc(spotlight)] is experimental"
1427                     );
1428                 }
1429             }
1430         }
1431
1432         // allow attr_literals in #[repr(align(x))]
1433         let mut is_repr_align = false;
1434         if attr.path == "repr" {
1435             if let Some(content) = attr.meta_item_list() {
1436                 is_repr_align = content.iter().any(|c| c.check_name("align"));
1437             }
1438         }
1439
1440         if self.context.features.proc_macro && attr::is_known(attr) {
1441             return
1442         }
1443
1444         if !is_repr_align {
1445             let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1446             if contains_novel_literal(&meta) {
1447                 gate_feature_post!(&self, attr_literals, attr.span,
1448                                    "non-string literals in attributes, or string \
1449                                    literals in top-level positions, are experimental");
1450             }
1451         }
1452     }
1453
1454     fn visit_name(&mut self, sp: Span, name: ast::Name) {
1455         if !name.as_str().is_ascii() {
1456             gate_feature_post!(&self,
1457                                non_ascii_idents,
1458                                self.context.parse_sess.codemap().def_span(sp),
1459                                "non-ascii idents are not fully supported.");
1460         }
1461     }
1462
1463     fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) {
1464         if let ast::UseTreeKind::Simple(Some(ident)) = use_tree.kind {
1465             if ident.name == "_" {
1466                 gate_feature_post!(&self, underscore_imports, use_tree.span,
1467                                    "renaming imports with `_` is unstable");
1468             }
1469         }
1470
1471         visit::walk_use_tree(self, use_tree, id);
1472     }
1473
1474     fn visit_item(&mut self, i: &'a ast::Item) {
1475         match i.node {
1476             ast::ItemKind::ExternCrate(_) => {
1477                 if i.ident.name == "_" {
1478                     gate_feature_post!(&self, underscore_imports, i.span,
1479                                        "renaming extern crates with `_` is unstable");
1480                 }
1481                 if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
1482                     gate_feature_post!(&self, macro_reexport, attr.span,
1483                                        "macros re-exports are experimental \
1484                                         and possibly buggy");
1485                 }
1486             }
1487
1488             ast::ItemKind::ForeignMod(ref foreign_module) => {
1489                 self.check_abi(foreign_module.abi, i.span);
1490             }
1491
1492             ast::ItemKind::Fn(..) => {
1493                 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1494                     gate_feature_post!(&self, plugin_registrar, i.span,
1495                                        "compiler plugins are experimental and possibly buggy");
1496                 }
1497                 if attr::contains_name(&i.attrs[..], "start") {
1498                     gate_feature_post!(&self, start, i.span,
1499                                       "a #[start] function is an experimental \
1500                                        feature whose signature may change \
1501                                        over time");
1502                 }
1503                 if attr::contains_name(&i.attrs[..], "main") {
1504                     gate_feature_post!(&self, main, i.span,
1505                                        "declaration of a nonstandard #[main] \
1506                                         function may change over time, for now \
1507                                         a top-level `fn main()` is required");
1508                 }
1509                 if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") {
1510                     gate_feature_post!(&self, fn_must_use, attr.span,
1511                                        "`#[must_use]` on functions is experimental",
1512                                        GateStrength::Soft);
1513                 }
1514             }
1515
1516             ast::ItemKind::Struct(..) => {
1517                 if let Some(attr) = attr::find_by_name(&i.attrs[..], "repr") {
1518                     for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1519                         if item.check_name("simd") {
1520                             gate_feature_post!(&self, repr_simd, attr.span,
1521                                                "SIMD types are experimental and possibly buggy");
1522                         }
1523                         if item.check_name("transparent") {
1524                             gate_feature_post!(&self, repr_transparent, attr.span,
1525                                                "the `#[repr(transparent)]` attribute \
1526                                                is experimental");
1527                         }
1528                     }
1529                 }
1530             }
1531
1532             ast::ItemKind::TraitAlias(..) => {
1533                 gate_feature_post!(&self, trait_alias,
1534                                    i.span,
1535                                    "trait aliases are not yet fully implemented");
1536             }
1537
1538             ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
1539                 if polarity == ast::ImplPolarity::Negative {
1540                     gate_feature_post!(&self, optin_builtin_traits,
1541                                        i.span,
1542                                        "negative trait bounds are not yet fully implemented; \
1543                                         use marker types for now");
1544                 }
1545
1546                 if let ast::Defaultness::Default = defaultness {
1547                     gate_feature_post!(&self, specialization,
1548                                        i.span,
1549                                        "specialization is unstable");
1550                 }
1551
1552                 for impl_item in impl_items {
1553                     if let ast::ImplItemKind::Method(..) = impl_item.node {
1554                         if let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") {
1555                             gate_feature_post!(&self, fn_must_use, attr.span,
1556                                                "`#[must_use]` on methods is experimental",
1557                                                GateStrength::Soft);
1558                         }
1559                     }
1560                 }
1561             }
1562
1563             ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
1564                 gate_feature_post!(&self, optin_builtin_traits,
1565                                    i.span,
1566                                    "auto traits are experimental and possibly buggy");
1567             }
1568
1569             ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1570                 let msg = "`macro` is experimental";
1571                 gate_feature_post!(&self, decl_macro, i.span, msg);
1572             }
1573
1574             _ => {}
1575         }
1576
1577         visit::walk_item(self, i);
1578     }
1579
1580     fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1581         match i.node {
1582             ast::ForeignItemKind::Fn(..) |
1583             ast::ForeignItemKind::Static(..) => {
1584                 let link_name = attr::first_attr_value_str_by_name(&i.attrs, "link_name");
1585                 let links_to_llvm = match link_name {
1586                     Some(val) => val.as_str().starts_with("llvm."),
1587                     _ => false
1588                 };
1589                 if links_to_llvm {
1590                     gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1591                                        "linking to LLVM intrinsics is experimental");
1592                 }
1593             }
1594             ast::ForeignItemKind::Ty => {
1595                     gate_feature_post!(&self, extern_types, i.span,
1596                                        "extern types are experimental");
1597             }
1598         }
1599
1600         visit::walk_foreign_item(self, i)
1601     }
1602
1603     fn visit_ty(&mut self, ty: &'a ast::Ty) {
1604         match ty.node {
1605             ast::TyKind::BareFn(ref bare_fn_ty) => {
1606                 self.check_abi(bare_fn_ty.abi, ty.span);
1607             }
1608             ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => {
1609                 gate_feature_post!(&self, dyn_trait, ty.span,
1610                                    "`dyn Trait` syntax is unstable");
1611             }
1612             _ => {}
1613         }
1614         visit::walk_ty(self, ty)
1615     }
1616
1617     fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1618         if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1619             if output_ty.node != ast::TyKind::Never {
1620                 self.visit_ty(output_ty)
1621             }
1622         }
1623     }
1624
1625     fn visit_expr(&mut self, e: &'a ast::Expr) {
1626         match e.node {
1627             ast::ExprKind::Box(_) => {
1628                 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1629             }
1630             ast::ExprKind::Type(..) => {
1631                 gate_feature_post!(&self, type_ascription, e.span,
1632                                   "type ascription is experimental");
1633             }
1634             ast::ExprKind::InPlace(..) => {
1635                 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1636             }
1637             ast::ExprKind::Yield(..) => {
1638                 gate_feature_post!(&self, generators,
1639                                   e.span,
1640                                   "yield syntax is experimental");
1641             }
1642             ast::ExprKind::Catch(_) => {
1643                 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1644             }
1645             ast::ExprKind::IfLet(ref pats, ..) | ast::ExprKind::WhileLet(ref pats, ..) => {
1646                 if pats.len() > 1 {
1647                     gate_feature_post!(&self, if_while_or_patterns, e.span,
1648                                     "multiple patterns in `if let` and `while let` are unstable");
1649                 }
1650             }
1651             _ => {}
1652         }
1653         visit::walk_expr(self, e);
1654     }
1655
1656     fn visit_arm(&mut self, arm: &'a ast::Arm) {
1657         visit::walk_arm(self, arm)
1658     }
1659
1660     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1661         match pattern.node {
1662             PatKind::Slice(_, Some(ref subslice), _) => {
1663                 gate_feature_post!(&self, slice_patterns,
1664                                    subslice.span,
1665                                    "syntax for subslices in slice patterns is not yet stabilized");
1666             }
1667             PatKind::Box(..) => {
1668                 gate_feature_post!(&self, box_patterns,
1669                                   pattern.span,
1670                                   "box pattern syntax is experimental");
1671             }
1672             PatKind::Range(_, _, RangeEnd::Excluded) => {
1673                 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1674                                    "exclusive range pattern syntax is experimental");
1675             }
1676             PatKind::Paren(..) => {
1677                 gate_feature_post!(&self, pattern_parentheses, pattern.span,
1678                                    "parentheses in patterns are unstable");
1679             }
1680             _ => {}
1681         }
1682         visit::walk_pat(self, pattern)
1683     }
1684
1685     fn visit_fn(&mut self,
1686                 fn_kind: FnKind<'a>,
1687                 fn_decl: &'a ast::FnDecl,
1688                 span: Span,
1689                 _node_id: NodeId) {
1690         // check for const fn declarations
1691         if let FnKind::ItemFn(_, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1692             fn_kind {
1693             gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1694         }
1695         // stability of const fn methods are covered in
1696         // visit_trait_item and visit_impl_item below; this is
1697         // because default methods don't pass through this
1698         // point.
1699
1700         match fn_kind {
1701             FnKind::ItemFn(_, _, _, abi, _, _) |
1702             FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1703                 self.check_abi(abi, span);
1704             }
1705             _ => {}
1706         }
1707         visit::walk_fn(self, fn_kind, fn_decl, span);
1708     }
1709
1710     fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1711         match ti.node {
1712             ast::TraitItemKind::Method(ref sig, ref block) => {
1713                 if block.is_none() {
1714                     self.check_abi(sig.abi, ti.span);
1715                 }
1716                 if sig.constness.node == ast::Constness::Const {
1717                     gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1718                 }
1719             }
1720             ast::TraitItemKind::Type(_, ref default) => {
1721                 // We use two if statements instead of something like match guards so that both
1722                 // of these errors can be emitted if both cases apply.
1723                 if default.is_some() {
1724                     gate_feature_post!(&self, associated_type_defaults, ti.span,
1725                                        "associated type defaults are unstable");
1726                 }
1727                 if ti.generics.is_parameterized() {
1728                     gate_feature_post!(&self, generic_associated_types, ti.span,
1729                                        "generic associated types are unstable");
1730                 }
1731             }
1732             _ => {}
1733         }
1734         visit::walk_trait_item(self, ti);
1735     }
1736
1737     fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1738         if ii.defaultness == ast::Defaultness::Default {
1739             gate_feature_post!(&self, specialization,
1740                               ii.span,
1741                               "specialization is unstable");
1742         }
1743
1744         match ii.node {
1745             ast::ImplItemKind::Method(ref sig, _) => {
1746                 if sig.constness.node == ast::Constness::Const {
1747                     gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1748                 }
1749             }
1750             ast::ImplItemKind::Type(_) if ii.generics.is_parameterized() => {
1751                 gate_feature_post!(&self, generic_associated_types, ii.span,
1752                                    "generic associated types are unstable");
1753             }
1754             _ => {}
1755         }
1756         visit::walk_impl_item(self, ii);
1757     }
1758
1759     fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) {
1760         for segment in &path.segments {
1761             if segment.identifier.name == keywords::Crate.name() {
1762                 gate_feature_post!(&self, crate_in_paths, segment.span,
1763                                    "`crate` in paths is experimental");
1764             } else if segment.identifier.name == keywords::Extern.name() {
1765                 gate_feature_post!(&self, extern_in_paths, segment.span,
1766                                    "`extern` in paths is experimental");
1767             }
1768         }
1769
1770         visit::walk_path(self, path);
1771     }
1772
1773     fn visit_vis(&mut self, vis: &'a ast::Visibility) {
1774         if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node {
1775             gate_feature_post!(&self, crate_visibility_modifier, vis.span,
1776                                "`crate` visibility modifier is experimental");
1777         }
1778         visit::walk_vis(self, vis);
1779     }
1780
1781     fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
1782         let (attrs, explain) = match *param {
1783             ast::GenericParam::Lifetime(ref ld) =>
1784                 (&ld.attrs, "attributes on lifetime bindings are experimental"),
1785             ast::GenericParam::Type(ref t) =>
1786                 (&t.attrs, "attributes on type parameter bindings are experimental"),
1787         };
1788
1789         if !attrs.is_empty() {
1790             gate_feature_post!(&self, generic_param_attrs, attrs[0].span, explain);
1791         }
1792
1793         visit::walk_generic_param(self, param)
1794     }
1795
1796     fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
1797         if lt.ident.name == keywords::UnderscoreLifetime.name() {
1798             gate_feature_post!(&self, underscore_lifetimes, lt.span,
1799                                "underscore lifetimes are unstable");
1800         }
1801         visit::walk_lifetime(self, lt)
1802     }
1803 }
1804
1805 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
1806                     edition: Edition) -> Features {
1807     let mut features = Features::new();
1808
1809     let mut feature_checker = FeatureChecker::default();
1810
1811     for &(.., f_edition, set) in ACTIVE_FEATURES.iter() {
1812         if let Some(f_edition) = f_edition {
1813             if edition >= f_edition {
1814                 // FIXME(Manishearth) there is currently no way to set
1815                 // lang features by edition
1816                 set(&mut features, DUMMY_SP);
1817             }
1818         }
1819     }
1820
1821     for attr in krate_attrs {
1822         if !attr.check_name("feature") {
1823             continue
1824         }
1825
1826         match attr.meta_item_list() {
1827             None => {
1828                 span_err!(span_handler, attr.span, E0555,
1829                           "malformed feature attribute, expected #![feature(...)]");
1830             }
1831             Some(list) => {
1832                 for mi in list {
1833                     let name = if let Some(word) = mi.word() {
1834                         word.name()
1835                     } else {
1836                         span_err!(span_handler, mi.span, E0556,
1837                                   "malformed feature, expected just one word");
1838                         continue
1839                     };
1840
1841                     if let Some(&(_, _, _, _, set)) = ACTIVE_FEATURES.iter()
1842                         .find(|& &(n, ..)| name == n) {
1843                         set(&mut features, mi.span);
1844                         feature_checker.collect(&features, mi.span);
1845                     }
1846                     else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1847                             .find(|& &(n, _, _)| name == n)
1848                         .or_else(|| STABLE_REMOVED_FEATURES.iter()
1849                             .find(|& &(n, _, _)| name == n)) {
1850                         span_err!(span_handler, mi.span, E0557, "feature has been removed");
1851                     }
1852                     else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1853                         .find(|& &(n, _, _)| name == n) {
1854                         features.declared_stable_lang_features.push((name, mi.span));
1855                     } else {
1856                         features.declared_lib_features.push((name, mi.span));
1857                     }
1858                 }
1859             }
1860         }
1861     }
1862
1863     feature_checker.check(span_handler);
1864
1865     features
1866 }
1867
1868 /// A collector for mutually exclusive and interdependent features and their flag spans.
1869 #[derive(Default)]
1870 struct FeatureChecker {
1871     proc_macro: Option<Span>,
1872     custom_attribute: Option<Span>,
1873 }
1874
1875 impl FeatureChecker {
1876     // If this method turns out to be a hotspot due to branching,
1877     // the branching can be eliminated by modifying `set!()` to set these spans
1878     // only for the features that need to be checked for mutual exclusion.
1879     fn collect(&mut self, features: &Features, span: Span) {
1880         if features.proc_macro {
1881             // If self.proc_macro is None, set to Some(span)
1882             self.proc_macro = self.proc_macro.or(Some(span));
1883         }
1884
1885         if features.custom_attribute {
1886             self.custom_attribute = self.custom_attribute.or(Some(span));
1887         }
1888     }
1889
1890     fn check(self, handler: &Handler) {
1891         if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1892             handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1893                                               `#![feature(custom_attribute)] at the same time")
1894                 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1895                 .emit();
1896
1897             FatalError.raise();
1898         }
1899     }
1900 }
1901
1902 pub fn check_crate(krate: &ast::Crate,
1903                    sess: &ParseSess,
1904                    features: &Features,
1905                    plugin_attributes: &[(String, AttributeType)],
1906                    unstable: UnstableFeatures) {
1907     maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1908     let ctx = Context {
1909         features,
1910         parse_sess: sess,
1911         plugin_attributes,
1912     };
1913
1914     if !features.raw_identifiers {
1915         for &span in sess.raw_identifier_spans.borrow().iter() {
1916             if !span.allows_unstable() {
1917                 gate_feature!(&ctx, raw_identifiers, span,
1918                     "raw identifiers are experimental and subject to change"
1919                 );
1920             }
1921         }
1922     }
1923
1924     let visitor = &mut PostExpansionVisitor { context: &ctx };
1925     visitor.whole_crate_feature_gates(krate);
1926     visit::walk_crate(visitor, krate);
1927 }
1928
1929 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1930 pub enum UnstableFeatures {
1931     /// Hard errors for unstable features are active, as on
1932     /// beta/stable channels.
1933     Disallow,
1934     /// Allow features to be activated, as on nightly.
1935     Allow,
1936     /// Errors are bypassed for bootstrapping. This is required any time
1937     /// during the build that feature-related lints are set to warn or above
1938     /// because the build turns on warnings-as-errors and uses lots of unstable
1939     /// features. As a result, this is always required for building Rust itself.
1940     Cheat
1941 }
1942
1943 impl UnstableFeatures {
1944     pub fn from_environment() -> UnstableFeatures {
1945         // Whether this is a feature-staged build, i.e. on the beta or stable channel
1946         let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1947         // Whether we should enable unstable features for bootstrapping
1948         let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1949         match (disable_unstable_features, bootstrap) {
1950             (_, true) => UnstableFeatures::Cheat,
1951             (true, _) => UnstableFeatures::Disallow,
1952             (false, _) => UnstableFeatures::Allow
1953         }
1954     }
1955
1956     pub fn is_nightly_build(&self) -> bool {
1957         match *self {
1958             UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1959             _ => false,
1960         }
1961     }
1962 }
1963
1964 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1965                         unstable: UnstableFeatures) {
1966     let allow_features = match unstable {
1967         UnstableFeatures::Allow => true,
1968         UnstableFeatures::Disallow => false,
1969         UnstableFeatures::Cheat => true
1970     };
1971     if !allow_features {
1972         for attr in &krate.attrs {
1973             if attr.check_name("feature") {
1974                 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1975                 span_err!(span_handler, attr.span, E0554,
1976                           "#![feature] may not be used on the {} release channel",
1977                           release_channel);
1978             }
1979         }
1980     }
1981 }