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