]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/feature_gate.rs
remove associated_consts feature gate
[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 codemap::Spanned;
32 use syntax_pos::Span;
33 use errors::{DiagnosticBuilder, Handler, FatalError};
34 use visit::{self, FnKind, Visitor};
35 use parse::ParseSess;
36 use symbol::Symbol;
37
38 use std::ascii::AsciiExt;
39 use std::env;
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),)+) => {
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>, fn(&mut Features, Span))] =
63             &[$((stringify!($feature), $ver, $issue, set!($feature))),+];
64
65         /// A set of features to be used by later passes.
66         pub struct Features {
67             /// #![feature] attrs for stable language features, for error reporting
68             pub declared_stable_lang_features: Vec<(Symbol, Span)>,
69             /// #![feature] attrs for non-language (library) features
70             pub declared_lib_features: Vec<(Symbol, Span)>,
71             $(pub $feature: bool),+
72         }
73
74         impl Features {
75             pub fn new() -> Features {
76                 Features {
77                     declared_stable_lang_features: Vec::new(),
78                     declared_lib_features: Vec::new(),
79                     $($feature: false),+
80                 }
81             }
82         }
83     };
84
85     ($((removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
86         /// Represents unstable features which have since been removed (it was once Active)
87         const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
88             $((stringify!($feature), $ver, $issue)),+
89         ];
90     };
91
92     ($((stable_removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
93         /// Represents stable features which have since been removed (it was once Accepted)
94         const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
95             $((stringify!($feature), $ver, $issue)),+
96         ];
97     };
98
99     ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => {
100         /// Those language feature has since been Accepted (it was once Active)
101         const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
102             $((stringify!($feature), $ver, $issue)),+
103         ];
104     }
105 }
106
107 // If you change this, please modify src/doc/unstable-book as well.
108 //
109 // Don't ever remove anything from this list; set them to 'Removed'.
110 //
111 // The version numbers here correspond to the version in which the current status
112 // was set. This is most important for knowing when a particular feature became
113 // stable (active).
114 //
115 // NB: The featureck.py script parses this information directly out of the source
116 // so take care when modifying it.
117
118 declare_features! (
119     (active, asm, "1.0.0", Some(29722)),
120     (active, compile_error, "1.20.0", Some(40872)),
121     (active, concat_idents, "1.0.0", Some(29599)),
122     (active, link_args, "1.0.0", Some(29596)),
123     (active, log_syntax, "1.0.0", Some(29598)),
124     (active, non_ascii_idents, "1.0.0", Some(28979)),
125     (active, plugin_registrar, "1.0.0", Some(29597)),
126     (active, thread_local, "1.0.0", Some(29594)),
127     (active, trace_macros, "1.0.0", Some(29598)),
128
129     // rustc internal, for now:
130     (active, intrinsics, "1.0.0", None),
131     (active, lang_items, "1.0.0", None),
132
133     (active, link_llvm_intrinsics, "1.0.0", Some(29602)),
134     (active, linkage, "1.0.0", Some(29603)),
135     (active, quote, "1.0.0", Some(29601)),
136     (active, simd, "1.0.0", Some(27731)),
137
138
139     // rustc internal
140     (active, rustc_diagnostic_macros, "1.0.0", None),
141     (active, advanced_slice_patterns, "1.0.0", Some(23121)),
142     (active, box_syntax, "1.0.0", Some(27779)),
143     (active, placement_in_syntax, "1.0.0", Some(27779)),
144     (active, unboxed_closures, "1.0.0", Some(29625)),
145
146     (active, fundamental, "1.0.0", Some(29635)),
147     (active, main, "1.0.0", Some(29634)),
148     (active, needs_allocator, "1.4.0", Some(27389)),
149     (active, on_unimplemented, "1.0.0", Some(29628)),
150     (active, plugin, "1.0.0", Some(29597)),
151     (active, simd_ffi, "1.0.0", Some(27731)),
152     (active, start, "1.0.0", Some(29633)),
153     (active, structural_match, "1.8.0", Some(31434)),
154     (active, panic_runtime, "1.10.0", Some(32837)),
155     (active, needs_panic_runtime, "1.10.0", Some(32837)),
156
157     // OIBIT specific features
158     (active, optin_builtin_traits, "1.0.0", Some(13231)),
159
160     // macro reexport needs more discussion and stabilization
161     (active, macro_reexport, "1.0.0", Some(29638)),
162
163     // Allows use of #[staged_api]
164     // rustc internal
165     (active, staged_api, "1.0.0", None),
166
167     // Allows using #![no_core]
168     (active, no_core, "1.3.0", Some(29639)),
169
170     // Allows using `box` in patterns; RFC 469
171     (active, box_patterns, "1.0.0", Some(29641)),
172
173     // Allows using the unsafe_destructor_blind_to_params attribute;
174     // RFC 1238
175     (active, dropck_parametricity, "1.3.0", Some(28498)),
176
177     // Allows using the may_dangle attribute; RFC 1327
178     (active, dropck_eyepatch, "1.10.0", Some(34761)),
179
180     // Allows the use of custom attributes; RFC 572
181     (active, custom_attribute, "1.0.0", Some(29642)),
182
183     // Allows the use of #[derive(Anything)] as sugar for
184     // #[derive_Anything].
185     (active, custom_derive, "1.0.0", Some(29644)),
186
187     // Allows the use of rustc_* attributes; RFC 572
188     (active, rustc_attrs, "1.0.0", Some(29642)),
189
190     // Allows the use of #[allow_internal_unstable]. This is an
191     // attribute on macro_rules! and can't use the attribute handling
192     // below (it has to be checked before expansion possibly makes
193     // macros disappear).
194     //
195     // rustc internal
196     (active, allow_internal_unstable, "1.0.0", None),
197
198     // #23121. Array patterns have some hazards yet.
199     (active, slice_patterns, "1.0.0", Some(23121)),
200
201     // Allows the definition of `const fn` functions.
202     (active, const_fn, "1.2.0", Some(24111)),
203
204     // Allows indexing into constant arrays.
205     (active, const_indexing, "1.4.0", Some(29947)),
206
207     // Allows using #[prelude_import] on glob `use` items.
208     //
209     // rustc internal
210     (active, prelude_import, "1.2.0", None),
211
212     // Allows default type parameters to influence type inference.
213     (active, default_type_parameter_fallback, "1.3.0", Some(27336)),
214
215     // Allows associated type defaults
216     (active, associated_type_defaults, "1.2.0", Some(29661)),
217
218     // allow `repr(simd)`, and importing the various simd intrinsics
219     (active, repr_simd, "1.4.0", Some(27731)),
220
221     // Allows cfg(target_feature = "...").
222     (active, cfg_target_feature, "1.4.0", Some(29717)),
223
224     // allow `extern "platform-intrinsic" { ... }`
225     (active, platform_intrinsics, "1.4.0", Some(27731)),
226
227     // allow `#[unwind]`
228     // rust runtime internal
229     (active, unwind_attributes, "1.4.0", None),
230
231     // allow the use of `#[naked]` on functions.
232     (active, naked_functions, "1.9.0", Some(32408)),
233
234     // allow `#[no_debug]`
235     (active, no_debug, "1.5.0", Some(29721)),
236
237     // allow `#[omit_gdb_pretty_printer_section]`
238     // rustc internal.
239     (active, omit_gdb_pretty_printer_section, "1.5.0", None),
240
241     // Allows cfg(target_vendor = "...").
242     (active, cfg_target_vendor, "1.5.0", Some(29718)),
243
244     // Allow attributes on expressions and non-item statements
245     (active, stmt_expr_attributes, "1.6.0", Some(15701)),
246
247     // allow using type ascription in expressions
248     (active, type_ascription, "1.6.0", Some(23416)),
249
250     // Allows cfg(target_thread_local)
251     (active, cfg_target_thread_local, "1.7.0", Some(29594)),
252
253     // rustc internal
254     (active, abi_vectorcall, "1.7.0", None),
255
256     // a...b and ...b
257     (active, inclusive_range_syntax, "1.7.0", Some(28237)),
258
259     // X..Y patterns
260     (active, exclusive_range_pattern, "1.11.0", Some(37854)),
261
262     // impl specialization (RFC 1210)
263     (active, specialization, "1.7.0", Some(31844)),
264
265     // Allow Drop types in statics/const functions (RFC 1440)
266     (active, drop_types_in_const, "1.9.0", Some(33156)),
267
268     // Allows cfg(target_has_atomic = "...").
269     (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
270
271     // Allows `impl Trait` in function return types.
272     (active, conservative_impl_trait, "1.12.0", Some(34511)),
273
274     // The `!` type
275     (active, never_type, "1.13.0", Some(35121)),
276
277     // Allows all literals in attribute lists and values of key-value pairs.
278     (active, attr_literals, "1.13.0", Some(34981)),
279
280     // Allows the sysV64 ABI to be specified on all platforms
281     // instead of just the platforms on which it is the C ABI
282     (active, abi_sysv64, "1.13.0", Some(36167)),
283
284     // Allows untagged unions `union U { ... }`
285     (active, untagged_unions, "1.13.0", Some(32836)),
286
287     // Used to identify the `compiler_builtins` crate
288     // rustc internal
289     (active, compiler_builtins, "1.13.0", None),
290
291     // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
292     (active, generic_param_attrs, "1.11.0", Some(34761)),
293
294     // Allows #[link(..., cfg(..))]
295     (active, link_cfg, "1.14.0", Some(37406)),
296
297     (active, use_extern_macros, "1.15.0", Some(35896)),
298
299     // Allows #[target_feature(...)]
300     (active, target_feature, "1.15.0", None),
301
302     // `extern "ptx-*" fn()`
303     (active, abi_ptx, "1.15.0", None),
304
305     // The `i128` type
306     (active, i128_type, "1.16.0", Some(35118)),
307
308     // The `unadjusted` ABI. Perma unstable.
309     (active, abi_unadjusted, "1.16.0", None),
310
311     // Procedural macros 2.0.
312     (active, proc_macro, "1.16.0", Some(38356)),
313
314     // Declarative macros 2.0 (`macro`).
315     (active, decl_macro, "1.17.0", Some(39412)),
316
317     // Allows #[link(kind="static-nobundle"...]
318     (active, static_nobundle, "1.16.0", Some(37403)),
319
320     // `extern "msp430-interrupt" fn()`
321     (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
322
323     // Used to identify crates that contain sanitizer runtimes
324     // rustc internal
325     (active, sanitizer_runtime, "1.17.0", None),
326
327     // Used to identify crates that contain the profiler runtime
328     // rustc internal
329     (active, profiler_runtime, "1.18.0", None),
330
331     // `extern "x86-interrupt" fn()`
332     (active, abi_x86_interrupt, "1.17.0", Some(40180)),
333
334
335     // Allows the `catch {...}` expression
336     (active, catch_expr, "1.17.0", Some(31436)),
337
338     // Allows `repr(align(u16))` struct attribute (RFC 1358)
339     (active, repr_align, "1.17.0", Some(33626)),
340
341     // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
342     (active, rvalue_static_promotion, "1.15.1", Some(38865)),
343
344     // Used to preserve symbols (see llvm.used)
345     (active, used, "1.18.0", Some(40289)),
346
347     // Allows module-level inline assembly by way of global_asm!()
348     (active, global_asm, "1.18.0", Some(35119)),
349
350     // Allows overlapping impls of marker traits
351     (active, overlapping_marker_traits, "1.18.0", Some(29864)),
352
353     // Allows use of the :vis macro fragment specifier
354     (active, macro_vis_matcher, "1.18.0", Some(41022)),
355
356     // rustc internal
357     (active, abi_thiscall, "1.19.0", None),
358
359     // Allows a test to fail without failing the whole suite
360     (active, allow_fail, "1.19.0", Some(42219)),
361
362     // Allows unsized tuple coercion.
363     (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
364
365     // global allocators and their internals
366     (active, global_allocator, "1.20.0", None),
367     (active, allocator_internals, "1.20.0", None),
368 );
369
370 declare_features! (
371     (removed, import_shadowing, "1.0.0", None),
372     (removed, managed_boxes, "1.0.0", None),
373     // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
374     (removed, negate_unsigned, "1.0.0", Some(29645)),
375     (removed, reflect, "1.0.0", Some(27749)),
376     // A way to temporarily opt out of opt in copy. This will *never* be accepted.
377     (removed, opt_out_copy, "1.0.0", None),
378     (removed, quad_precision_float, "1.0.0", None),
379     (removed, struct_inherit, "1.0.0", None),
380     (removed, test_removed_feature, "1.0.0", None),
381     (removed, visible_private_types, "1.0.0", None),
382     (removed, unsafe_no_drop_flag, "1.0.0", None),
383     // Allows using items which are missing stability attributes
384     // rustc internal
385     (removed, unmarked_api, "1.0.0", None),
386     (removed, pushpop_unsafe, "1.2.0", None),
387     (removed, allocator, "1.0.0", None),
388 );
389
390 declare_features! (
391     (stable_removed, no_stack_check, "1.0.0", None),
392 );
393
394 declare_features! (
395     (accepted, associated_types, "1.0.0", None),
396     // allow overloading augmented assignment operations like `a += b`
397     (accepted, augmented_assignments, "1.8.0", Some(28235)),
398     // allow empty structs and enum variants with braces
399     (accepted, braced_empty_structs, "1.8.0", Some(29720)),
400     (accepted, default_type_params, "1.0.0", None),
401     (accepted, globs, "1.0.0", None),
402     (accepted, if_let, "1.0.0", None),
403     // A temporary feature gate used to enable parser extensions needed
404     // to bootstrap fix for #5723.
405     (accepted, issue_5723_bootstrap, "1.0.0", None),
406     (accepted, macro_rules, "1.0.0", None),
407     // Allows using #![no_std]
408     (accepted, no_std, "1.6.0", None),
409     (accepted, slicing_syntax, "1.0.0", None),
410     (accepted, struct_variant, "1.0.0", None),
411     // These are used to test this portion of the compiler, they don't actually
412     // mean anything
413     (accepted, test_accepted_feature, "1.0.0", None),
414     (accepted, tuple_indexing, "1.0.0", None),
415     // Allows macros to appear in the type position.
416     (accepted, type_macros, "1.13.0", Some(27245)),
417     (accepted, while_let, "1.0.0", None),
418     // Allows `#[deprecated]` attribute
419     (accepted, deprecated, "1.9.0", Some(29935)),
420     // `expr?`
421     (accepted, question_mark, "1.13.0", Some(31436)),
422     // Allows `..` in tuple (struct) patterns
423     (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
424     (accepted, item_like_imports, "1.15.0", Some(35120)),
425     // Allows using `Self` and associated types in struct expressions and patterns.
426     (accepted, more_struct_aliases, "1.16.0", Some(37544)),
427     // elide `'static` lifetimes in `static`s and `const`s
428     (accepted, static_in_const, "1.17.0", Some(35897)),
429     // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
430     (accepted, field_init_shorthand, "1.17.0", Some(37340)),
431     // Allows the definition recursive static items.
432     (accepted, static_recursion, "1.17.0", Some(29719)),
433     // pub(restricted) visibilities (RFC 1422)
434     (accepted, pub_restricted, "1.18.0", Some(32409)),
435     // The #![windows_subsystem] attribute
436     (accepted, windows_subsystem, "1.18.0", Some(37499)),
437     // Allows `break {expr}` with a value inside `loop`s.
438     (accepted, loop_break_value, "1.19.0", Some(37339)),
439     // Permits numeric fields in struct expressions and patterns.
440     (accepted, relaxed_adts, "1.19.0", Some(35626)),
441     // Coerces non capturing closures to function pointers
442     (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
443     // Allows attributes on struct literal fields.
444     (accepted, struct_field_attributes, "1.20.0", Some(38814)),
445     // Allows the definition of associated constants in `trait` or `impl`
446     // blocks.
447     (accepted, associated_consts, "1.20.0", Some(29646)),
448 );
449
450 // If you change this, please modify src/doc/unstable-book as well. You must
451 // move that documentation into the relevant place in the other docs, and
452 // remove the chapter on the flag.
453
454 #[derive(PartialEq, Copy, Clone, Debug)]
455 pub enum AttributeType {
456     /// Normal, builtin attribute that is consumed
457     /// by the compiler before the unused_attribute check
458     Normal,
459
460     /// Builtin attribute that may not be consumed by the compiler
461     /// before the unused_attribute check. These attributes
462     /// will be ignored by the unused_attribute lint
463     Whitelisted,
464
465     /// Builtin attribute that is only allowed at the crate level
466     CrateLevel,
467 }
468
469 pub enum AttributeGate {
470     /// Is gated by a given feature gate, reason
471     /// and function to check if enabled
472     Gated(Stability, &'static str, &'static str, fn(&Features) -> bool),
473
474     /// Ungated attribute, can be used on all release channels
475     Ungated,
476 }
477
478 impl AttributeGate {
479     fn is_deprecated(&self) -> bool {
480         match *self {
481             Gated(Stability::Deprecated(_), ..) => true,
482             _ => false,
483         }
484     }
485 }
486
487 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
488 pub enum Stability {
489     Unstable,
490     // Argument is tracking issue link.
491     Deprecated(&'static str),
492 }
493
494 // fn() is not Debug
495 impl ::std::fmt::Debug for AttributeGate {
496     fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
497         match *self {
498             Gated(ref stab, name, expl, _) =>
499                 write!(fmt, "Gated({:?}, {}, {})", stab, name, expl),
500             Ungated => write!(fmt, "Ungated")
501         }
502     }
503 }
504
505 macro_rules! cfg_fn {
506     ($field: ident) => {{
507         fn f(features: &Features) -> bool {
508             features.$field
509         }
510         f as fn(&Features) -> bool
511     }}
512 }
513
514 pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> {
515     BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
516 }
517
518 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
519     BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name))
520 }
521
522 // Attributes that have a special meaning to rustc or rustdoc
523 pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
524     // Normal attributes
525
526     ("warn", Normal, Ungated),
527     ("allow", Normal, Ungated),
528     ("forbid", Normal, Ungated),
529     ("deny", Normal, Ungated),
530
531     ("macro_reexport", Normal, Ungated),
532     ("macro_use", Normal, Ungated),
533     ("macro_export", Normal, Ungated),
534     ("plugin_registrar", Normal, Ungated),
535
536     ("cfg", Normal, Ungated),
537     ("cfg_attr", Normal, Ungated),
538     ("main", Normal, Ungated),
539     ("start", Normal, Ungated),
540     ("test", Normal, Ungated),
541     ("bench", Normal, Ungated),
542     ("simd", Normal, Ungated),
543     ("repr", Normal, Ungated),
544     ("path", Normal, Ungated),
545     ("abi", Normal, Ungated),
546     ("automatically_derived", Normal, Ungated),
547     ("no_mangle", Normal, Ungated),
548     ("no_link", Normal, Ungated),
549     ("derive", Normal, Ungated),
550     ("should_panic", Normal, Ungated),
551     ("ignore", Normal, Ungated),
552     ("no_implicit_prelude", Normal, Ungated),
553     ("reexport_test_harness_main", Normal, Ungated),
554     ("link_args", Normal, Ungated),
555     ("macro_escape", Normal, Ungated),
556
557     // RFC #1445.
558     ("structural_match", Whitelisted, Gated(Stability::Unstable,
559                                             "structural_match",
560                                             "the semantics of constant patterns is \
561                                              not yet settled",
562                                             cfg_fn!(structural_match))),
563
564     ("plugin", CrateLevel, Gated(Stability::Unstable,
565                                  "plugin",
566                                  "compiler plugins are experimental \
567                                   and possibly buggy",
568                                  cfg_fn!(plugin))),
569
570     ("no_std", CrateLevel, Ungated),
571     ("no_core", CrateLevel, Gated(Stability::Unstable,
572                                   "no_core",
573                                   "no_core is experimental",
574                                   cfg_fn!(no_core))),
575     ("lang", Normal, Gated(Stability::Unstable,
576                            "lang_items",
577                            "language items are subject to change",
578                            cfg_fn!(lang_items))),
579     ("linkage", Whitelisted, Gated(Stability::Unstable,
580                                    "linkage",
581                                    "the `linkage` attribute is experimental \
582                                     and not portable across platforms",
583                                    cfg_fn!(linkage))),
584     ("thread_local", Whitelisted, Gated(Stability::Unstable,
585                                         "thread_local",
586                                         "`#[thread_local]` is an experimental feature, and does \
587                                          not currently handle destructors. There is no \
588                                          corresponding `#[task_local]` mapping to the task \
589                                          model",
590                                         cfg_fn!(thread_local))),
591
592     ("rustc_on_unimplemented", Normal, Gated(Stability::Unstable,
593                                              "on_unimplemented",
594                                              "the `#[rustc_on_unimplemented]` attribute \
595                                               is an experimental feature",
596                                              cfg_fn!(on_unimplemented))),
597     ("global_allocator", Normal, Gated(Stability::Unstable,
598                                        "global_allocator",
599                                        "the `#[global_allocator]` attribute is \
600                                         an experimental feature",
601                                        cfg_fn!(global_allocator))),
602     ("default_lib_allocator", Whitelisted, Gated(Stability::Unstable,
603                                             "allocator_internals",
604                                             "the `#[default_lib_allocator]` \
605                                              attribute is an experimental feature",
606                                             cfg_fn!(allocator_internals))),
607     ("needs_allocator", Normal, Gated(Stability::Unstable,
608                                       "allocator_internals",
609                                       "the `#[needs_allocator]` \
610                                        attribute is an experimental \
611                                        feature",
612                                       cfg_fn!(allocator_internals))),
613     ("panic_runtime", Whitelisted, Gated(Stability::Unstable,
614                                          "panic_runtime",
615                                          "the `#[panic_runtime]` attribute is \
616                                           an experimental feature",
617                                          cfg_fn!(panic_runtime))),
618     ("needs_panic_runtime", Whitelisted, Gated(Stability::Unstable,
619                                                "needs_panic_runtime",
620                                                "the `#[needs_panic_runtime]` \
621                                                 attribute is an experimental \
622                                                 feature",
623                                                cfg_fn!(needs_panic_runtime))),
624     ("rustc_variance", Normal, Gated(Stability::Unstable,
625                                      "rustc_attrs",
626                                      "the `#[rustc_variance]` attribute \
627                                       is just used for rustc unit tests \
628                                       and will never be stable",
629                                      cfg_fn!(rustc_attrs))),
630     ("rustc_error", Whitelisted, Gated(Stability::Unstable,
631                                        "rustc_attrs",
632                                        "the `#[rustc_error]` attribute \
633                                         is just used for rustc unit tests \
634                                         and will never be stable",
635                                        cfg_fn!(rustc_attrs))),
636     ("rustc_if_this_changed", Whitelisted, Gated(Stability::Unstable,
637                                                  "rustc_attrs",
638                                                  "the `#[rustc_if_this_changed]` attribute \
639                                                   is just used for rustc unit tests \
640                                                   and will never be stable",
641                                                  cfg_fn!(rustc_attrs))),
642     ("rustc_then_this_would_need", Whitelisted, Gated(Stability::Unstable,
643                                                       "rustc_attrs",
644                                                       "the `#[rustc_if_this_changed]` attribute \
645                                                        is just used for rustc unit tests \
646                                                        and will never be stable",
647                                                       cfg_fn!(rustc_attrs))),
648     ("rustc_dirty", Whitelisted, Gated(Stability::Unstable,
649                                        "rustc_attrs",
650                                        "the `#[rustc_dirty]` attribute \
651                                         is just used for rustc unit tests \
652                                         and will never be stable",
653                                        cfg_fn!(rustc_attrs))),
654     ("rustc_clean", Whitelisted, Gated(Stability::Unstable,
655                                        "rustc_attrs",
656                                        "the `#[rustc_clean]` attribute \
657                                         is just used for rustc unit tests \
658                                         and will never be stable",
659                                        cfg_fn!(rustc_attrs))),
660     ("rustc_metadata_dirty", Whitelisted, Gated(Stability::Unstable,
661                                                 "rustc_attrs",
662                                                 "the `#[rustc_metadata_dirty]` attribute \
663                                                  is just used for rustc unit tests \
664                                                  and will never be stable",
665                                                  cfg_fn!(rustc_attrs))),
666     ("rustc_metadata_clean", Whitelisted, Gated(Stability::Unstable,
667                                                 "rustc_attrs",
668                                                 "the `#[rustc_metadata_clean]` attribute \
669                                                  is just used for rustc unit tests \
670                                                  and will never be stable",
671                                                  cfg_fn!(rustc_attrs))),
672     ("rustc_partition_reused", Whitelisted, Gated(Stability::Unstable,
673                                                   "rustc_attrs",
674                                                   "this attribute \
675                                                    is just used for rustc unit tests \
676                                                    and will never be stable",
677                                                   cfg_fn!(rustc_attrs))),
678     ("rustc_partition_translated", Whitelisted, Gated(Stability::Unstable,
679                                                       "rustc_attrs",
680                                                       "this attribute \
681                                                        is just used for rustc unit tests \
682                                                        and will never be stable",
683                                                       cfg_fn!(rustc_attrs))),
684     ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
685                                              "rustc_attrs",
686                                              "internal rustc attributes will never be stable",
687                                              cfg_fn!(rustc_attrs))),
688     ("rustc_item_path", Whitelisted, Gated(Stability::Unstable,
689                                            "rustc_attrs",
690                                            "internal rustc attributes will never be stable",
691                                            cfg_fn!(rustc_attrs))),
692     ("rustc_mir", Whitelisted, Gated(Stability::Unstable,
693                                      "rustc_attrs",
694                                      "the `#[rustc_mir]` attribute \
695                                       is just used for rustc unit tests \
696                                       and will never be stable",
697                                      cfg_fn!(rustc_attrs))),
698     ("rustc_inherit_overflow_checks", Whitelisted, Gated(Stability::Unstable,
699                                                          "rustc_attrs",
700                                                          "the `#[rustc_inherit_overflow_checks]` \
701                                                           attribute is just used to control \
702                                                           overflow checking behavior of several \
703                                                           libcore functions that are inlined \
704                                                           across crates and will never be stable",
705                                                           cfg_fn!(rustc_attrs))),
706     ("compiler_builtins", Whitelisted, Gated(Stability::Unstable,
707                                              "compiler_builtins",
708                                              "the `#[compiler_builtins]` attribute is used to \
709                                               identify the `compiler_builtins` crate which \
710                                               contains compiler-rt intrinsics and will never be \
711                                               stable",
712                                           cfg_fn!(compiler_builtins))),
713     ("sanitizer_runtime", Whitelisted, Gated(Stability::Unstable,
714                                              "sanitizer_runtime",
715                                              "the `#[sanitizer_runtime]` attribute is used to \
716                                               identify crates that contain the runtime of a \
717                                               sanitizer and will never be stable",
718                                              cfg_fn!(sanitizer_runtime))),
719     ("profiler_runtime", Whitelisted, Gated(Stability::Unstable,
720                                              "profiler_runtime",
721                                              "the `#[profiler_runtime]` attribute is used to \
722                                               identify the `profiler_builtins` crate which \
723                                               contains the profiler runtime and will never be \
724                                               stable",
725                                              cfg_fn!(profiler_runtime))),
726
727     ("allow_internal_unstable", Normal, Gated(Stability::Unstable,
728                                               "allow_internal_unstable",
729                                               EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
730                                               cfg_fn!(allow_internal_unstable))),
731
732     ("fundamental", Whitelisted, Gated(Stability::Unstable,
733                                        "fundamental",
734                                        "the `#[fundamental]` attribute \
735                                         is an experimental feature",
736                                        cfg_fn!(fundamental))),
737
738     ("proc_macro_derive", Normal, Ungated),
739
740     ("rustc_copy_clone_marker", Whitelisted, Gated(Stability::Unstable,
741                                                    "rustc_attrs",
742                                                    "internal implementation detail",
743                                                    cfg_fn!(rustc_attrs))),
744
745     // FIXME: #14408 whitelist docs since rustdoc looks at them
746     ("doc", Whitelisted, Ungated),
747
748     // FIXME: #14406 these are processed in trans, which happens after the
749     // lint pass
750     ("cold", Whitelisted, Ungated),
751     ("naked", Whitelisted, Gated(Stability::Unstable,
752                                  "naked_functions",
753                                  "the `#[naked]` attribute \
754                                   is an experimental feature",
755                                  cfg_fn!(naked_functions))),
756     ("target_feature", Whitelisted, Gated(
757         Stability::Unstable, "target_feature",
758         "the `#[target_feature]` attribute is an experimental feature",
759         cfg_fn!(target_feature))),
760     ("export_name", Whitelisted, Ungated),
761     ("inline", Whitelisted, Ungated),
762     ("link", Whitelisted, Ungated),
763     ("link_name", Whitelisted, Ungated),
764     ("link_section", Whitelisted, Ungated),
765     ("no_builtins", Whitelisted, Ungated),
766     ("no_mangle", Whitelisted, Ungated),
767     ("no_debug", Whitelisted, Gated(
768         Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
769         "no_debug",
770         "the `#[no_debug]` attribute is an experimental feature",
771         cfg_fn!(no_debug))),
772     ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
773                                                        "omit_gdb_pretty_printer_section",
774                                                        "the `#[omit_gdb_pretty_printer_section]` \
775                                                         attribute is just used for the Rust test \
776                                                         suite",
777                                                        cfg_fn!(omit_gdb_pretty_printer_section))),
778     ("unsafe_destructor_blind_to_params",
779      Normal,
780      Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
781            "dropck_parametricity",
782            "unsafe_destructor_blind_to_params has been replaced by \
783             may_dangle and will be removed in the future",
784            cfg_fn!(dropck_parametricity))),
785     ("may_dangle",
786      Normal,
787      Gated(Stability::Unstable,
788            "dropck_eyepatch",
789            "may_dangle has unstable semantics and may be removed in the future",
790            cfg_fn!(dropck_eyepatch))),
791     ("unwind", Whitelisted, Gated(Stability::Unstable,
792                                   "unwind_attributes",
793                                   "#[unwind] is experimental",
794                                   cfg_fn!(unwind_attributes))),
795     ("used", Whitelisted, Gated(
796         Stability::Unstable, "used",
797         "the `#[used]` attribute is an experimental feature",
798         cfg_fn!(used))),
799
800     // used in resolve
801     ("prelude_import", Whitelisted, Gated(Stability::Unstable,
802                                           "prelude_import",
803                                           "`#[prelude_import]` is for use by rustc only",
804                                           cfg_fn!(prelude_import))),
805
806     // FIXME: #14407 these are only looked at on-demand so we can't
807     // guarantee they'll have already been checked
808     ("rustc_deprecated", Whitelisted, Ungated),
809     ("must_use", Whitelisted, Ungated),
810     ("stable", Whitelisted, Ungated),
811     ("unstable", Whitelisted, Ungated),
812     ("deprecated", Normal, Ungated),
813
814     ("rustc_paren_sugar", Normal, Gated(Stability::Unstable,
815                                         "unboxed_closures",
816                                         "unboxed_closures are still evolving",
817                                         cfg_fn!(unboxed_closures))),
818
819     ("windows_subsystem", Whitelisted, Ungated),
820
821     ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
822                                            "proc_macro",
823                                            "attribute proc macros are currently unstable",
824                                            cfg_fn!(proc_macro))),
825
826     ("proc_macro", Normal, Gated(Stability::Unstable,
827                                  "proc_macro",
828                                  "function-like proc macros are currently unstable",
829                                  cfg_fn!(proc_macro))),
830
831     ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
832                                              "rustc_derive_registrar",
833                                              "used internally by rustc",
834                                              cfg_fn!(rustc_attrs))),
835
836     ("allow_fail", Normal, Gated(Stability::Unstable,
837                                  "allow_fail",
838                                  "allow_fail attribute is currently unstable",
839                                  cfg_fn!(allow_fail))),
840
841     // Crate level attributes
842     ("crate_name", CrateLevel, Ungated),
843     ("crate_type", CrateLevel, Ungated),
844     ("crate_id", CrateLevel, Ungated),
845     ("feature", CrateLevel, Ungated),
846     ("no_start", CrateLevel, Ungated),
847     ("no_main", CrateLevel, Ungated),
848     ("no_builtins", CrateLevel, Ungated),
849     ("recursion_limit", CrateLevel, Ungated),
850     ("type_length_limit", CrateLevel, Ungated),
851 ];
852
853 // cfg(...)'s that are feature gated
854 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
855     // (name in cfg, feature, function to check if the feature is enabled)
856     ("target_feature", "cfg_target_feature", cfg_fn!(cfg_target_feature)),
857     ("target_vendor", "cfg_target_vendor", cfg_fn!(cfg_target_vendor)),
858     ("target_thread_local", "cfg_target_thread_local", cfg_fn!(cfg_target_thread_local)),
859     ("target_has_atomic", "cfg_target_has_atomic", cfg_fn!(cfg_target_has_atomic)),
860 ];
861
862 #[derive(Debug, Eq, PartialEq)]
863 pub struct GatedCfg {
864     span: Span,
865     index: usize,
866 }
867
868 impl GatedCfg {
869     pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
870         let name = cfg.name().as_str();
871         GATED_CFGS.iter()
872                   .position(|info| info.0 == name)
873                   .map(|idx| {
874                       GatedCfg {
875                           span: cfg.span,
876                           index: idx
877                       }
878                   })
879     }
880
881     pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) {
882         let (cfg, feature, has_feature) = GATED_CFGS[self.index];
883         if !has_feature(features) && !self.span.allows_unstable() {
884             let explain = format!("`cfg({})` is experimental and subject to change", cfg);
885             emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain);
886         }
887     }
888 }
889
890 struct Context<'a> {
891     features: &'a Features,
892     parse_sess: &'a ParseSess,
893     plugin_attributes: &'a [(String, AttributeType)],
894 }
895
896 macro_rules! gate_feature_fn {
897     ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
898         let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
899         let has_feature: bool = has_feature(&$cx.features);
900         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
901         if !has_feature && !span.allows_unstable() {
902             emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
903         }
904     }}
905 }
906
907 macro_rules! gate_feature {
908     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
909         gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
910     }
911 }
912
913 impl<'a> Context<'a> {
914     fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
915         debug!("check_attribute(attr = {:?})", attr);
916         let name = unwrap_or!(attr.name(), return).as_str();
917         for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
918             if name == n {
919                 if let Gated(_, name, desc, ref has_feature) = *gateage {
920                     gate_feature_fn!(self, has_feature, attr.span, name, desc);
921                 }
922                 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
923                 return;
924             }
925         }
926         for &(ref n, ref ty) in self.plugin_attributes {
927             if attr.path == &**n {
928                 // Plugins can't gate attributes, so we don't check for it
929                 // unlike the code above; we only use this loop to
930                 // short-circuit to avoid the checks below
931                 debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
932                 return;
933             }
934         }
935         if name.starts_with("rustc_") {
936             gate_feature!(self, rustc_attrs, attr.span,
937                           "unless otherwise specified, attributes \
938                            with the prefix `rustc_` \
939                            are reserved for internal compiler diagnostics");
940         } else if name.starts_with("derive_") {
941             gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
942         } else if !attr::is_known(attr) {
943             // Only run the custom attribute lint during regular
944             // feature gate checking. Macro gating runs
945             // before the plugin attributes are registered
946             // so we skip this then
947             if !is_macro {
948                 gate_feature!(self, custom_attribute, attr.span,
949                               &format!("The attribute `{}` is currently \
950                                         unknown to the compiler and \
951                                         may have meaning \
952                                         added to it in the future",
953                                        attr.path));
954             }
955         }
956     }
957 }
958
959 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
960     let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
961     cx.check_attribute(attr, true);
962 }
963
964 pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
965     ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
966 }
967
968 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
969     if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
970         let issue = info.2;
971         // FIXME (#28244): enforce that active features have issue numbers
972         // assert!(issue.is_some())
973         issue
974     } else {
975         // search in Accepted, Removed, or Stable Removed features
976         let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
977             .find(|t| t.0 == feature);
978         match found {
979             Some(&(_, _, issue)) => issue,
980             None => panic!("Feature `{}` is not declared anywhere", feature),
981         }
982     }
983 }
984
985 pub enum GateIssue {
986     Language,
987     Library(Option<u32>)
988 }
989
990 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
991                         explain: &str) {
992     feature_err(sess, feature, span, issue, explain).emit();
993 }
994
995 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
996                    explain: &str) -> DiagnosticBuilder<'a> {
997     let diag = &sess.span_diagnostic;
998
999     let issue = match issue {
1000         GateIssue::Language => find_lang_feature_issue(feature),
1001         GateIssue::Library(lib) => lib,
1002     };
1003
1004     let mut err = if let Some(n) = issue {
1005         diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
1006     } else {
1007         diag.struct_span_err(span, explain)
1008     };
1009
1010     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
1011     if sess.unstable_features.is_nightly_build() {
1012         err.help(&format!("add #![feature({})] to the \
1013                            crate attributes to enable",
1014                           feature));
1015     }
1016
1017     err
1018 }
1019
1020 const EXPLAIN_BOX_SYNTAX: &'static str =
1021     "box expression syntax is experimental; you can call `Box::new` instead.";
1022
1023 pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str =
1024     "attributes on non-item statements and expressions are experimental.";
1025
1026 pub const EXPLAIN_ASM: &'static str =
1027     "inline assembly is not stable enough for use and is subject to change";
1028
1029 pub const EXPLAIN_GLOBAL_ASM: &'static str =
1030     "`global_asm!` is not stable enough for use and is subject to change";
1031
1032 pub const EXPLAIN_LOG_SYNTAX: &'static str =
1033     "`log_syntax!` is not stable enough for use and is subject to change";
1034
1035 pub const EXPLAIN_CONCAT_IDENTS: &'static str =
1036     "`concat_idents` is not stable enough for use and is subject to change";
1037
1038 pub const EXPLAIN_COMPILE_ERROR: &'static str =
1039     "`compile_error` is not stable enough for use and is subject to change";
1040
1041 pub const EXPLAIN_TRACE_MACROS: &'static str =
1042     "`trace_macros` is not stable enough for use and is subject to change";
1043 pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
1044     "allow_internal_unstable side-steps feature gating and stability checks";
1045
1046 pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
1047     "`#[derive]` for custom traits is deprecated and will be removed in the future.";
1048
1049 pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str =
1050     "`#[derive]` for custom traits is deprecated and will be removed in the future. \
1051     Prefer using procedural macro custom derive.";
1052
1053 pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
1054     "attributes of the form `#[derive_*]` are reserved for the compiler";
1055
1056 pub const EXPLAIN_VIS_MATCHER: &'static str =
1057     ":vis fragment specifier is experimental and subject to change";
1058
1059 pub const EXPLAIN_PLACEMENT_IN: &'static str =
1060     "placement-in expression syntax is experimental and subject to change.";
1061
1062 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
1063     "Unsized tuple coercion is not stable enough for use and is subject to change";
1064
1065 struct PostExpansionVisitor<'a> {
1066     context: &'a Context<'a>,
1067 }
1068
1069 macro_rules! gate_feature_post {
1070     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
1071         let (cx, span) = ($cx, $span);
1072         if !span.allows_unstable() {
1073             gate_feature!(cx.context, $feature, span, $explain)
1074         }
1075     }}
1076 }
1077
1078 impl<'a> PostExpansionVisitor<'a> {
1079     fn check_abi(&self, abi: Abi, span: Span) {
1080         match abi {
1081             Abi::RustIntrinsic => {
1082                 gate_feature_post!(&self, intrinsics, span,
1083                                    "intrinsics are subject to change");
1084             },
1085             Abi::PlatformIntrinsic => {
1086                 gate_feature_post!(&self, platform_intrinsics, span,
1087                                    "platform intrinsics are experimental and possibly buggy");
1088             },
1089             Abi::Vectorcall => {
1090                 gate_feature_post!(&self, abi_vectorcall, span,
1091                                    "vectorcall is experimental and subject to change");
1092             },
1093             Abi::Thiscall => {
1094                 gate_feature_post!(&self, abi_thiscall, span,
1095                                    "thiscall is experimental and subject to change");
1096             },
1097             Abi::RustCall => {
1098                 gate_feature_post!(&self, unboxed_closures, span,
1099                                    "rust-call ABI is subject to change");
1100             },
1101             Abi::SysV64 => {
1102                 gate_feature_post!(&self, abi_sysv64, span,
1103                                    "sysv64 ABI is experimental and subject to change");
1104             },
1105             Abi::PtxKernel => {
1106                 gate_feature_post!(&self, abi_ptx, span,
1107                                    "PTX ABIs are experimental and subject to change");
1108             },
1109             Abi::Unadjusted => {
1110                 gate_feature_post!(&self, abi_unadjusted, span,
1111                                    "unadjusted ABI is an implementation detail and perma-unstable");
1112             },
1113             Abi::Msp430Interrupt => {
1114                 gate_feature_post!(&self, abi_msp430_interrupt, span,
1115                                    "msp430-interrupt ABI is experimental and subject to change");
1116             },
1117             Abi::X86Interrupt => {
1118                 gate_feature_post!(&self, abi_x86_interrupt, span,
1119                                    "x86-interrupt ABI is experimental and subject to change");
1120             },
1121             // Stable
1122             Abi::Cdecl |
1123             Abi::Stdcall |
1124             Abi::Fastcall |
1125             Abi::Aapcs |
1126             Abi::Win64 |
1127             Abi::Rust |
1128             Abi::C |
1129             Abi::System => {}
1130         }
1131     }
1132 }
1133
1134 fn contains_novel_literal(item: &ast::MetaItem) -> bool {
1135     use ast::MetaItemKind::*;
1136     use ast::NestedMetaItemKind::*;
1137
1138     match item.node {
1139         Word => false,
1140         NameValue(ref lit) => !lit.node.is_str(),
1141         List(ref list) => list.iter().any(|li| {
1142             match li.node {
1143                 MetaItem(ref mi) => contains_novel_literal(mi),
1144                 Literal(_) => true,
1145             }
1146         }),
1147     }
1148 }
1149
1150 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
1151     fn visit_attribute(&mut self, attr: &ast::Attribute) {
1152         if !attr.span.allows_unstable() {
1153             // check for gated attributes
1154             self.context.check_attribute(attr, false);
1155         }
1156
1157         if self.context.features.proc_macro && attr::is_known(attr) {
1158             return
1159         }
1160
1161         let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1162         if contains_novel_literal(&meta) {
1163             gate_feature_post!(&self, attr_literals, attr.span,
1164                                "non-string literals in attributes, or string \
1165                                literals in top-level positions, are experimental");
1166         }
1167     }
1168
1169     fn visit_name(&mut self, sp: Span, name: ast::Name) {
1170         if !name.as_str().is_ascii() {
1171             gate_feature_post!(&self, non_ascii_idents, sp,
1172                                "non-ascii idents are not fully supported.");
1173         }
1174     }
1175
1176     fn visit_item(&mut self, i: &'a ast::Item) {
1177         match i.node {
1178             ast::ItemKind::ExternCrate(_) => {
1179                 if attr::contains_name(&i.attrs[..], "macro_reexport") {
1180                     gate_feature_post!(&self, macro_reexport, i.span,
1181                                        "macros reexports are experimental \
1182                                         and possibly buggy");
1183                 }
1184             }
1185
1186             ast::ItemKind::ForeignMod(ref foreign_module) => {
1187                 if attr::contains_name(&i.attrs[..], "link_args") {
1188                     gate_feature_post!(&self, link_args, i.span,
1189                                       "the `link_args` attribute is not portable \
1190                                        across platforms, it is recommended to \
1191                                        use `#[link(name = \"foo\")]` instead")
1192                 }
1193                 self.check_abi(foreign_module.abi, i.span);
1194             }
1195
1196             ast::ItemKind::Fn(..) => {
1197                 if attr::contains_name(&i.attrs[..], "plugin_registrar") {
1198                     gate_feature_post!(&self, plugin_registrar, i.span,
1199                                        "compiler plugins are experimental and possibly buggy");
1200                 }
1201                 if attr::contains_name(&i.attrs[..], "start") {
1202                     gate_feature_post!(&self, start, i.span,
1203                                       "a #[start] function is an experimental \
1204                                        feature whose signature may change \
1205                                        over time");
1206                 }
1207                 if attr::contains_name(&i.attrs[..], "main") {
1208                     gate_feature_post!(&self, main, i.span,
1209                                        "declaration of a nonstandard #[main] \
1210                                         function may change over time, for now \
1211                                         a top-level `fn main()` is required");
1212                 }
1213             }
1214
1215             ast::ItemKind::Struct(..) => {
1216                 if attr::contains_name(&i.attrs[..], "simd") {
1217                     gate_feature_post!(&self, simd, i.span,
1218                                        "SIMD types are experimental and possibly buggy");
1219                     self.context.parse_sess.span_diagnostic.span_warn(i.span,
1220                                                                       "the `#[simd]` attribute \
1221                                                                        is deprecated, use \
1222                                                                        `#[repr(simd)]` instead");
1223                 }
1224                 for attr in &i.attrs {
1225                     if attr.path == "repr" {
1226                         for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
1227                             if item.check_name("simd") {
1228                                 gate_feature_post!(&self, repr_simd, i.span,
1229                                                    "SIMD types are experimental \
1230                                                     and possibly buggy");
1231
1232                             }
1233                             if item.check_name("align") {
1234                                 gate_feature_post!(&self, repr_align, i.span,
1235                                                    "the struct `#[repr(align(u16))]` attribute \
1236                                                     is experimental");
1237                             }
1238                         }
1239                     }
1240                 }
1241             }
1242
1243             ast::ItemKind::DefaultImpl(..) => {
1244                 gate_feature_post!(&self, optin_builtin_traits,
1245                                    i.span,
1246                                    "default trait implementations are experimental \
1247                                     and possibly buggy");
1248             }
1249
1250             ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
1251                 if polarity == ast::ImplPolarity::Negative {
1252                     gate_feature_post!(&self, optin_builtin_traits,
1253                                        i.span,
1254                                        "negative trait bounds are not yet fully implemented; \
1255                                         use marker types for now");
1256                 }
1257
1258                 if let ast::Defaultness::Default = defaultness {
1259                     gate_feature_post!(&self, specialization,
1260                                        i.span,
1261                                        "specialization is unstable");
1262                 }
1263             }
1264
1265             ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
1266                 let msg = "`macro` is experimental";
1267                 gate_feature_post!(&self, decl_macro, i.span, msg);
1268             }
1269
1270             _ => {}
1271         }
1272
1273         visit::walk_item(self, i);
1274     }
1275
1276     fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
1277         let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
1278             Some(val) => val.as_str().starts_with("llvm."),
1279             _ => false
1280         };
1281         if links_to_llvm {
1282             gate_feature_post!(&self, link_llvm_intrinsics, i.span,
1283                               "linking to LLVM intrinsics is experimental");
1284         }
1285
1286         visit::walk_foreign_item(self, i)
1287     }
1288
1289     fn visit_ty(&mut self, ty: &'a ast::Ty) {
1290         match ty.node {
1291             ast::TyKind::BareFn(ref bare_fn_ty) => {
1292                 self.check_abi(bare_fn_ty.abi, ty.span);
1293             }
1294             ast::TyKind::ImplTrait(..) => {
1295                 gate_feature_post!(&self, conservative_impl_trait, ty.span,
1296                                    "`impl Trait` is experimental");
1297             }
1298             ast::TyKind::Never => {
1299                 gate_feature_post!(&self, never_type, ty.span,
1300                                    "The `!` type is experimental");
1301             },
1302             _ => {}
1303         }
1304         visit::walk_ty(self, ty)
1305     }
1306
1307     fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) {
1308         if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
1309             if output_ty.node != ast::TyKind::Never {
1310                 self.visit_ty(output_ty)
1311             }
1312         }
1313     }
1314
1315     fn visit_expr(&mut self, e: &'a ast::Expr) {
1316         match e.node {
1317             ast::ExprKind::Box(_) => {
1318                 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
1319             }
1320             ast::ExprKind::Type(..) => {
1321                 gate_feature_post!(&self, type_ascription, e.span,
1322                                   "type ascription is experimental");
1323             }
1324             ast::ExprKind::Range(_, _, ast::RangeLimits::Closed) => {
1325                 gate_feature_post!(&self, inclusive_range_syntax,
1326                                   e.span,
1327                                   "inclusive range syntax is experimental");
1328             }
1329             ast::ExprKind::InPlace(..) => {
1330                 gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
1331             }
1332             ast::ExprKind::Lit(ref lit) => {
1333                 if let ast::LitKind::Int(_, ref ty) = lit.node {
1334                     match *ty {
1335                         ast::LitIntType::Signed(ast::IntTy::I128) |
1336                         ast::LitIntType::Unsigned(ast::UintTy::U128) => {
1337                             gate_feature_post!(&self, i128_type, e.span,
1338                                                "128-bit integers are not stable");
1339                         }
1340                         _ => {}
1341                     }
1342                 }
1343             }
1344             ast::ExprKind::Catch(_) => {
1345                 gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
1346             }
1347             _ => {}
1348         }
1349         visit::walk_expr(self, e);
1350     }
1351
1352     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
1353         match pattern.node {
1354             PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
1355                 gate_feature_post!(&self, advanced_slice_patterns,
1356                                   pattern.span,
1357                                   "multiple-element slice matches anywhere \
1358                                    but at the end of a slice (e.g. \
1359                                    `[0, ..xs, 0]`) are experimental")
1360             }
1361             PatKind::Slice(..) => {
1362                 gate_feature_post!(&self, slice_patterns,
1363                                   pattern.span,
1364                                   "slice pattern syntax is experimental");
1365             }
1366             PatKind::Box(..) => {
1367                 gate_feature_post!(&self, box_patterns,
1368                                   pattern.span,
1369                                   "box pattern syntax is experimental");
1370             }
1371             PatKind::Range(_, _, RangeEnd::Excluded) => {
1372                 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
1373                                    "exclusive range pattern syntax is experimental");
1374             }
1375             _ => {}
1376         }
1377         visit::walk_pat(self, pattern)
1378     }
1379
1380     fn visit_fn(&mut self,
1381                 fn_kind: FnKind<'a>,
1382                 fn_decl: &'a ast::FnDecl,
1383                 span: Span,
1384                 _node_id: NodeId) {
1385         // check for const fn declarations
1386         if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
1387             fn_kind {
1388             gate_feature_post!(&self, const_fn, span, "const fn is unstable");
1389         }
1390         // stability of const fn methods are covered in
1391         // visit_trait_item and visit_impl_item below; this is
1392         // because default methods don't pass through this
1393         // point.
1394
1395         match fn_kind {
1396             FnKind::ItemFn(_, _, _, _, abi, _, _) |
1397             FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
1398                 self.check_abi(abi, span);
1399             }
1400             _ => {}
1401         }
1402         visit::walk_fn(self, fn_kind, fn_decl, span);
1403     }
1404
1405     fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
1406         match ti.node {
1407             ast::TraitItemKind::Method(ref sig, ref block) => {
1408                 if block.is_none() {
1409                     self.check_abi(sig.abi, ti.span);
1410                 }
1411                 if sig.constness.node == ast::Constness::Const {
1412                     gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
1413                 }
1414             }
1415             ast::TraitItemKind::Type(_, Some(_)) => {
1416                 gate_feature_post!(&self, associated_type_defaults, ti.span,
1417                                   "associated type defaults are unstable");
1418             }
1419             _ => {}
1420         }
1421         visit::walk_trait_item(self, ti);
1422     }
1423
1424     fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
1425         if ii.defaultness == ast::Defaultness::Default {
1426             gate_feature_post!(&self, specialization,
1427                               ii.span,
1428                               "specialization is unstable");
1429         }
1430
1431         match ii.node {
1432             ast::ImplItemKind::Method(ref sig, _) => {
1433                 if sig.constness.node == ast::Constness::Const {
1434                     gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
1435                 }
1436             }
1437             _ => {}
1438         }
1439         visit::walk_impl_item(self, ii);
1440     }
1441
1442     fn visit_generics(&mut self, g: &'a ast::Generics) {
1443         for t in &g.ty_params {
1444             if !t.attrs.is_empty() {
1445                 gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
1446                                    "attributes on type parameter bindings are experimental");
1447             }
1448         }
1449         visit::walk_generics(self, g)
1450     }
1451
1452     fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
1453         if !lifetime_def.attrs.is_empty() {
1454             gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
1455                                "attributes on lifetime bindings are experimental");
1456         }
1457         visit::walk_lifetime_def(self, lifetime_def)
1458     }
1459 }
1460
1461 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
1462     let mut features = Features::new();
1463
1464     let mut feature_checker = MutexFeatureChecker::default();
1465
1466     for attr in krate_attrs {
1467         if !attr.check_name("feature") {
1468             continue
1469         }
1470
1471         match attr.meta_item_list() {
1472             None => {
1473                 span_err!(span_handler, attr.span, E0555,
1474                           "malformed feature attribute, expected #![feature(...)]");
1475             }
1476             Some(list) => {
1477                 for mi in list {
1478                     let name = if let Some(word) = mi.word() {
1479                         word.name()
1480                     } else {
1481                         span_err!(span_handler, mi.span, E0556,
1482                                   "malformed feature, expected just one word");
1483                         continue
1484                     };
1485
1486                     if let Some(&(_, _, _, set)) = ACTIVE_FEATURES.iter()
1487                         .find(|& &(n, _, _, _)| name == n) {
1488                         set(&mut features, mi.span);
1489                         feature_checker.collect(&features, mi.span);
1490                     }
1491                     else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
1492                             .find(|& &(n, _, _)| name == n)
1493                         .or_else(|| STABLE_REMOVED_FEATURES.iter()
1494                             .find(|& &(n, _, _)| name == n)) {
1495                         span_err!(span_handler, mi.span, E0557, "feature has been removed");
1496                     }
1497                     else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
1498                         .find(|& &(n, _, _)| name == n) {
1499                         features.declared_stable_lang_features.push((name, mi.span));
1500                     } else {
1501                         features.declared_lib_features.push((name, mi.span));
1502                     }
1503                 }
1504             }
1505         }
1506     }
1507
1508     feature_checker.check(span_handler);
1509
1510     features
1511 }
1512
1513 // A collector for mutually-exclusive features and their flag spans
1514 #[derive(Default)]
1515 struct MutexFeatureChecker {
1516     proc_macro: Option<Span>,
1517     custom_attribute: Option<Span>,
1518 }
1519
1520 impl MutexFeatureChecker {
1521     // If this method turns out to be a hotspot due to branching,
1522     // the branching can be eliminated by modifying `set!()` to set these spans
1523     // only for the features that need to be checked for mutual exclusion.
1524     fn collect(&mut self, features: &Features, span: Span) {
1525         if features.proc_macro {
1526             // If self.proc_macro is None, set to Some(span)
1527             self.proc_macro = self.proc_macro.or(Some(span));
1528         }
1529
1530         if features.custom_attribute {
1531             self.custom_attribute = self.custom_attribute.or(Some(span));
1532         }
1533     }
1534
1535     fn check(self, handler: &Handler) {
1536         if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
1537             handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
1538                                               `#![feature(custom_attribute)] at the same time")
1539                 .span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
1540                 .emit();
1541
1542             panic!(FatalError);
1543         }
1544     }
1545 }
1546
1547 pub fn check_crate(krate: &ast::Crate,
1548                    sess: &ParseSess,
1549                    features: &Features,
1550                    plugin_attributes: &[(String, AttributeType)],
1551                    unstable: UnstableFeatures) {
1552     maybe_stage_features(&sess.span_diagnostic, krate, unstable);
1553     let ctx = Context {
1554         features: features,
1555         parse_sess: sess,
1556         plugin_attributes: plugin_attributes,
1557     };
1558     visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1559 }
1560
1561 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
1562 pub enum UnstableFeatures {
1563     /// Hard errors for unstable features are active, as on
1564     /// beta/stable channels.
1565     Disallow,
1566     /// Allow features to be activated, as on nightly.
1567     Allow,
1568     /// Errors are bypassed for bootstrapping. This is required any time
1569     /// during the build that feature-related lints are set to warn or above
1570     /// because the build turns on warnings-as-errors and uses lots of unstable
1571     /// features. As a result, this is always required for building Rust itself.
1572     Cheat
1573 }
1574
1575 impl UnstableFeatures {
1576     pub fn from_environment() -> UnstableFeatures {
1577         // Whether this is a feature-staged build, i.e. on the beta or stable channel
1578         let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1579         // Whether we should enable unstable features for bootstrapping
1580         let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
1581         match (disable_unstable_features, bootstrap) {
1582             (_, true) => UnstableFeatures::Cheat,
1583             (true, _) => UnstableFeatures::Disallow,
1584             (false, _) => UnstableFeatures::Allow
1585         }
1586     }
1587
1588     pub fn is_nightly_build(&self) -> bool {
1589         match *self {
1590             UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
1591             _ => false,
1592         }
1593     }
1594 }
1595
1596 fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
1597                         unstable: UnstableFeatures) {
1598     let allow_features = match unstable {
1599         UnstableFeatures::Allow => true,
1600         UnstableFeatures::Disallow => false,
1601         UnstableFeatures::Cheat => true
1602     };
1603     if !allow_features {
1604         for attr in &krate.attrs {
1605             if attr.check_name("feature") {
1606                 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
1607                 span_err!(span_handler, attr.span, E0554,
1608                           "#[feature] may not be used on the {} release channel",
1609                           release_channel);
1610             }
1611         }
1612     }
1613 }