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