]> git.lizzy.rs Git - rust.git/blobdiff - src/libsyntax/feature_gate.rs
Auto merge of #51990 - oli-obk:unstable_union, r=nikomatsakis
[rust.git] / src / libsyntax / feature_gate.rs
index 7797e947ed779745849ab262624a49178e64134f..6d71d276390c41308f2df8ceac80770963595301 100644 (file)
@@ -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 @@ pub struct 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 @@ pub fn use_extern_macros(&self) -> bool {
     (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),
@@ -216,6 +216,18 @@ pub fn use_extern_macros(&self) -> bool {
     // Allows let bindings and destructuring in `const fn` functions and constants.
     (active, const_let, "1.22.1", Some(48821), None),
 
+    // Allows accessing fields of unions inside const fn
+    (active, const_fn_union, "1.27.0", Some(51909), None),
+
+    // Allows casting raw pointers to `usize` during const eval
+    (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),
+
+    // Allows dereferencing raw pointers during const eval
+    (active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
+
+    // Allows comparing raw pointers during const eval
+    (active, const_compare_raw_pointers, "1.27.0", Some(53020), None),
+
     // Allows using #[prelude_import] on glob `use` items.
     //
     // rustc internal
@@ -322,9 +334,8 @@ pub fn use_extern_macros(&self) -> bool {
     // `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)),
+    (active, catch_expr, "1.17.0", Some(31436), None),
 
     // Used to preserve symbols (see llvm.used)
     (active, used, "1.18.0", Some(40289), None),
@@ -1224,10 +1235,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;
@@ -1910,10 +1917,13 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
 
     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);
             }
         }
     }
@@ -1941,35 +1951,18 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
                 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);
                         }
                     }
                 }
@@ -1977,6 +1970,37 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
                 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));
         }
     }