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