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;
/// 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),+
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),+
}
(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),
// 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
// `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),
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;
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);
}
}
}
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);
}
}
}
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));
}
}