about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-08-06 16:58:27 +0000
committerbors <bors@rust-lang.org>2018-08-06 16:58:27 +0000
commitb2397437530eecef72a1524a7e0a4b42034fa360 (patch)
tree429466887a0f431e3586e4985775d268dd2374f1 /src/libsyntax
parent4b8089daf8046d7999310d44e5c68ccff4ab255a (diff)
parent4687476470d383fefe62ac9cde4e6f9015ba550f (diff)
downloadrust-b2397437530eecef72a1524a7e0a4b42034fa360.tar.gz
rust-b2397437530eecef72a1524a7e0a4b42034fa360.zip
Auto merge of #52644 - varkor:lib-feature-gate-2, r=withoutboats
Add errors for unknown, stable and duplicate feature attributes

- Adds an error for unknown (lang and lib) features.
- Extends the lint for unnecessary feature attributes for stable features to libs features (this already exists for lang features).
- Adds an error for duplicate (lang and lib) features.

```rust
#![feature(fake_feature)] //~ ERROR unknown feature `fake_feature`

#![feature(i128_type)] //~ WARNING the feature `i128_type` has been stable since 1.26.0

#![feature(non_exhaustive)]
#![feature(non_exhaustive)] //~ ERROR duplicate `non_exhaustive` feature attribute
```

Fixes #52053, fixes #53032 and address some of the problems noted in #44232 (though not unused features).

There are a few outstanding problems, that I haven't narrowed down yet:
- [x] Stability attributes on macros do not seem to be taken into account.
- [x] Stability attributes behind `cfg` attributes are not taken into account.
- [x] There are failing incremental tests.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/diagnostic_list.rs14
-rw-r--r--src/libsyntax/feature_gate.rs72
-rw-r--r--src/libsyntax/lib.rs1
3 files changed, 56 insertions, 31 deletions
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index 8534969c623..15abad555f4 100644
--- a/src/libsyntax/diagnostic_list.rs
+++ b/src/libsyntax/diagnostic_list.rs
@@ -374,6 +374,20 @@ and likely to change in the future.
 
 "##,
 
+E0705: r##"
+A `#![feature]` attribute was declared for a feature that is stable in
+the current edition.
+
+Erroneous code example:
+
+```ignore (limited to a warning during 2018 edition development)
+#![feature(rust_2018_preview)]
+#![feature(raw_identifiers)] // error: the feature `raw_identifiers` is
+                             // included in the Rust 2018 edition
+```
+
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 77e3faa5b1f..193e560893f 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -25,6 +25,7 @@
 use self::AttributeType::*;
 use self::AttributeGate::*;
 
+use rustc_data_structures::fx::FxHashMap;
 use rustc_target::spec::abi::Abi;
 use ast::{self, NodeId, PatKind, RangeEnd};
 use attr;
@@ -59,8 +60,8 @@ macro_rules! declare_features {
         /// A set of features to be used by later passes.
         #[derive(Clone)]
         pub struct Features {
-            /// `#![feature]` attrs for stable language features, for error reporting
-            pub declared_stable_lang_features: Vec<(Symbol, Span)>,
+            /// `#![feature]` attrs for language features, for error reporting
+            pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
             /// `#![feature]` attrs for non-language (library) features
             pub declared_lib_features: Vec<(Symbol, Span)>,
             $(pub $feature: bool),+
@@ -69,7 +70,7 @@ macro_rules! declare_features {
         impl Features {
             pub fn new() -> Features {
                 Features {
-                    declared_stable_lang_features: Vec::new(),
+                    declared_lang_features: Vec::new(),
                     declared_lib_features: Vec::new(),
                     $($feature: false),+
                 }
@@ -140,7 +141,6 @@ declare_features! (
     (active, linkage, "1.0.0", Some(29603), None),
     (active, quote, "1.0.0", Some(29601), None),
 
-
     // rustc internal
     (active, rustc_diagnostic_macros, "1.0.0", None, None),
     (active, rustc_const_unstable, "1.0.0", None, None),
@@ -322,7 +322,6 @@ declare_features! (
     // `extern "x86-interrupt" fn()`
     (active, abi_x86_interrupt, "1.17.0", Some(40180), None),
 
-
     // Allows the `catch {...}` expression
     (active, catch_expr, "1.17.0", Some(31436), Some(Edition::Edition2018)),
 
@@ -1220,10 +1219,6 @@ pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features:
     cx.check_attribute(attr, true);
 }
 
-pub fn find_lang_feature_accepted_version(feature: &str) -> Option<&'static str> {
-    ACCEPTED_FEATURES.iter().find(|t| t.0 == feature).map(|t| t.1)
-}
-
 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
     if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
         let issue = info.2;
@@ -1906,10 +1901,13 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
 
     let mut feature_checker = FeatureChecker::default();
 
-    for &(.., f_edition, set) in ACTIVE_FEATURES.iter() {
+    let mut edition_enabled_features = FxHashMap();
+
+    for &(name, .., f_edition, set) in ACTIVE_FEATURES.iter() {
         if let Some(f_edition) = f_edition {
             if f_edition <= crate_edition {
                 set(&mut features, DUMMY_SP);
+                edition_enabled_features.insert(Symbol::intern(name), crate_edition);
             }
         }
     }
@@ -1937,35 +1935,18 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
                 continue
             };
 
-            if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
-                set(&mut features, mi.span);
-                feature_checker.collect(&features, mi.span);
-                continue
-            }
-
-            let removed = REMOVED_FEATURES.iter().find(|f| name == f.0);
-            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0);
-            if let Some((.., reason)) = removed.or(stable_removed) {
-                feature_removed(span_handler, mi.span, *reason);
-                continue
-            }
-
-            if ACCEPTED_FEATURES.iter().any(|f| name == f.0) {
-                features.declared_stable_lang_features.push((name, mi.span));
-                continue
-            }
-
             if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) {
                 if *edition <= crate_edition {
                     continue
                 }
 
-                for &(.., f_edition, set) in ACTIVE_FEATURES.iter() {
+                for &(name, .., f_edition, set) in ACTIVE_FEATURES.iter() {
                     if let Some(f_edition) = f_edition {
-                        if *edition >= f_edition {
+                        if f_edition <= *edition {
                             // FIXME(Manishearth) there is currently no way to set
                             // lib features by edition
                             set(&mut features, DUMMY_SP);
+                            edition_enabled_features.insert(Symbol::intern(name), *edition);
                         }
                     }
                 }
@@ -1973,6 +1954,37 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
                 continue
             }
 
+            if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
+                if let Some(edition) = edition_enabled_features.get(&name) {
+                    struct_span_warn!(
+                        span_handler,
+                        mi.span,
+                        E0705,
+                        "the feature `{}` is included in the Rust {} edition",
+                        name,
+                        edition,
+                    ).emit();
+                } else {
+                    set(&mut features, mi.span);
+                    feature_checker.collect(&features, mi.span);
+                    features.declared_lang_features.push((name, mi.span, None));
+                }
+                continue
+            }
+
+            let removed = REMOVED_FEATURES.iter().find(|f| name == f.0);
+            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0);
+            if let Some((.., reason)) = removed.or(stable_removed) {
+                feature_removed(span_handler, mi.span, *reason);
+                continue
+            }
+
+            if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) {
+                let since = Some(Symbol::intern(since));
+                features.declared_lang_features.push((name, mi.span, since));
+                continue
+            }
+
             features.declared_lib_features.push((name, mi.span));
         }
     }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 0c105865e0c..c8e60620248 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -19,7 +19,6 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
 
-#![feature(const_atomic_usize_new)]
 #![feature(crate_visibility_modifier)]
 #![feature(macro_at_most_once_rep)]
 #![feature(rustc_attrs)]