diff options
| author | bors <bors@rust-lang.org> | 2018-08-06 16:58:27 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-08-06 16:58:27 +0000 |
| commit | b2397437530eecef72a1524a7e0a4b42034fa360 (patch) | |
| tree | 429466887a0f431e3586e4985775d268dd2374f1 /src/libsyntax | |
| parent | 4b8089daf8046d7999310d44e5c68ccff4ab255a (diff) | |
| parent | 4687476470d383fefe62ac9cde4e6f9015ba550f (diff) | |
| download | rust-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.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 72 | ||||
| -rw-r--r-- | src/libsyntax/lib.rs | 1 |
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)] |
