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