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),+
}
{
$(f(stringify!($feature), self.$feature);)+
}
+
+ pub fn use_extern_macros(&self) -> bool {
+ // The `decl_macro` and `tool_attributes` features imply `use_extern_macros`.
+ self.use_extern_macros || self.decl_macro || self.tool_attributes
+ }
}
};
(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),
(active, crate_in_paths, "1.23.0", Some(45477), Some(Edition::Edition2018)),
// In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`)
- (active, in_band_lifetimes, "1.23.0", Some(44524), Some(Edition::Edition2018)),
+ (active, in_band_lifetimes, "1.23.0", Some(44524), None),
// generic associated types (RFC 1598)
(active, generic_associated_types, "1.23.0", Some(44265), None),
// Infer outlives requirements; RFC 2093
(active, infer_outlives_requirements, "1.26.0", Some(44493), None),
- // Infer outlives requirements; RFC 2093
+ // Infer static outlives requirements; RFC 2093
(active, infer_static_outlives_requirements, "1.26.0", Some(44493), None),
// Multiple patterns with `|` in `if let` and `while let`
(active, alloc_error_handler, "1.29.0", Some(51540), None),
(active, abi_amdgpu_kernel, "1.29.0", Some(51575), None),
+
+ // impl<I:Iterator> Iterator for &mut Iterator
+ // impl Debug for Foo<'_>
+ (active, impl_header_lifetime_elision, "1.30.0", Some(15872), Some(Edition::Edition2018)),
);
declare_features! (
BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
}
+pub fn is_builtin_attr_name(name: ast::Name) -> bool {
+ BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| name == builtin_name)
+}
+
pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name)) ||
attr.name().as_str().starts_with("rustc_")
// before the plugin attributes are registered
// so we skip this then
if !is_macro {
- if attr.is_scoped() {
- gate_feature!(self, tool_attributes, attr.span,
- &format!("scoped attribute `{}` is experimental", attr.path));
- if attr::is_known_tool(attr) {
- attr::mark_used(attr);
- } else {
- span_err!(
- self.parse_sess.span_diagnostic,
- attr.span,
- E0694,
- "an unknown tool name found in scoped attribute: `{}`.",
- attr.path
- );
- }
- } else {
- gate_feature!(self, custom_attribute, attr.span,
- &format!("The attribute `{}` is currently \
- unknown to the compiler and \
- may have meaning \
- added to it in the future",
- attr.path));
- }
+ let msg = format!("The attribute `{}` is currently unknown to the compiler and \
+ may have meaning added to it in the future", attr.path);
+ gate_feature!(self, custom_attribute, attr.span, &msg);
}
}
}
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;
}
}
- if self.context.features.use_extern_macros && attr::is_known(attr) {
+ if self.context.features.use_extern_macros() && attr::is_known(attr) {
return
}
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));
}
}
// the branching can be eliminated by modifying `set!()` to set these spans
// only for the features that need to be checked for mutual exclusion.
fn collect(&mut self, features: &Features, span: Span) {
- if features.use_extern_macros {
+ if features.use_extern_macros() {
// If self.use_extern_macros is None, set to Some(span)
self.use_extern_macros = self.use_extern_macros.or(Some(span));
}