Skip to content

Commit 6ffc834

Browse files
author
Pascal Hertleif
committed
Introduce and use Feature type for feature gates
This replaces the ad-hoc tuples used in the different feature gate files and unifies their content into a common type, leading to more readable matches and other good stuff that comes from having named fields. It also contains the description of each feature as extracted from the doc comment.
1 parent c9619a4 commit 6ffc834

File tree

5 files changed

+124
-43
lines changed

5 files changed

+124
-43
lines changed

src/libsyntax/feature_gate/accepted.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
//! List of the accepted feature gates.
22
3-
use crate::symbol::{Symbol, sym};
3+
use crate::symbol::sym;
4+
use super::{State, Feature};
45

56
macro_rules! declare_features {
67
($(
78
$(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr, None),
89
)+) => {
910
/// Those language feature has since been Accepted (it was once Active)
10-
pub const ACCEPTED_FEATURES: &[(Symbol, &str, Option<u32>, Option<&str>)] = &[
11-
$((sym::$feature, $ver, $issue, None)),+
11+
pub const ACCEPTED_FEATURES: &[Feature] = &[
12+
$(
13+
Feature {
14+
state: State::Accepted,
15+
name: sym::$feature,
16+
since: $ver,
17+
issue: $issue,
18+
edition: None,
19+
description: concat!($($doc,)*),
20+
}
21+
),+
1222
];
1323
}
1424
}

src/libsyntax/feature_gate/active.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ macro_rules! declare_features {
6565
};
6666
}
6767

68+
impl Feature {
69+
/// Set this feature in `Features`. Panics if called on a non-active feature.
70+
pub fn set(&self, features: &mut Features, span: Span) {
71+
match self.state {
72+
State::Active { set } => set(features, span),
73+
_ => panic!("Called `set` on feature `{}` which is not `active`", self.name)
74+
}
75+
}
76+
}
77+
6878
// If you change this, please modify `src/doc/unstable-book` as well.
6979
//
7080
// Don't ever remove anything from this list; move them to `removed.rs`.

src/libsyntax/feature_gate/check.rs

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::active::{ACTIVE_FEATURES, Features};
1+
use super::{active::{ACTIVE_FEATURES, Features}, Feature, State as FeatureState};
22
use super::accepted::ACCEPTED_FEATURES;
33
use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
44
use super::builtin_attrs::{AttributeGate, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
@@ -127,17 +127,16 @@ pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features:
127127
}
128128

129129
fn find_lang_feature_issue(feature: Symbol) -> Option<u32> {
130-
if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
131-
let issue = info.2;
130+
if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) {
132131
// FIXME (#28244): enforce that active features have issue numbers
133-
// assert!(issue.is_some())
134-
issue
132+
// assert!(info.issue.is_some())
133+
info.issue
135134
} else {
136135
// search in Accepted, Removed, or Stable Removed features
137136
let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
138-
.find(|t| t.0 == feature);
137+
.find(|t| t.name == feature);
139138
match found {
140-
Some(&(_, _, issue, _)) => issue,
139+
Some(&Feature { issue, .. }) => issue,
141140
None => panic!("Feature `{}` is not declared anywhere", feature),
142141
}
143142
}
@@ -733,14 +732,11 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
733732
}
734733
}
735734

736-
for &(name, .., f_edition, set) in ACTIVE_FEATURES {
737-
if let Some(f_edition) = f_edition {
738-
if f_edition <= crate_edition {
739-
set(&mut features, DUMMY_SP);
740-
edition_enabled_features.insert(name, crate_edition);
741-
}
742-
}
743-
}
735+
active_features_up_to(crate_edition)
736+
.for_each(|f| {
737+
f.set(&mut features, DUMMY_SP);
738+
edition_enabled_features.insert(f.name, crate_edition);
739+
});
744740

745741
// Process the edition umbrella feature-gates first, to ensure
746742
// `edition_enabled_features` is completed before it's queried.
@@ -761,21 +757,19 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
761757

762758
let name = mi.name_or_empty();
763759

764-
if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) {
765-
if *edition <= crate_edition {
760+
if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied() {
761+
if edition <= crate_edition {
766762
continue;
767763
}
768764

769-
for &(name, .., f_edition, set) in ACTIVE_FEATURES {
770-
if let Some(f_edition) = f_edition {
771-
if f_edition <= *edition {
772-
// FIXME(Manishearth) there is currently no way to set
773-
// lib features by edition
774-
set(&mut features, DUMMY_SP);
775-
edition_enabled_features.insert(name, *edition);
776-
}
777-
}
778-
}
765+
active_features_up_to(edition)
766+
.for_each(|f| {
767+
// FIXME(Manishearth) there is currently no way to set
768+
// lib features by edition
769+
770+
f.set(&mut features, DUMMY_SP);
771+
edition_enabled_features.insert(name, edition);
772+
});
779773
}
780774
}
781775
}
@@ -829,14 +823,18 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
829823
continue;
830824
}
831825

832-
let removed = REMOVED_FEATURES.iter().find(|f| name == f.0);
833-
let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0);
834-
if let Some((.., reason)) = removed.or(stable_removed) {
835-
feature_removed(span_handler, mi.span(), *reason);
836-
continue;
826+
let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
827+
let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
828+
if let Some(Feature { state, .. }) = removed.or(stable_removed) {
829+
if let FeatureState::Removed { reason }
830+
| FeatureState::Stabilized { reason } = state
831+
{
832+
feature_removed(span_handler, mi.span(), *reason);
833+
continue;
834+
}
837835
}
838836

839-
if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) {
837+
if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
840838
let since = Some(Symbol::intern(since));
841839
features.declared_lang_features.push((name, mi.span(), since));
842840
continue;
@@ -851,8 +849,8 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
851849
}
852850
}
853851

854-
if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
855-
set(&mut features, mi.span());
852+
if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
853+
f.set(&mut features, mi.span());
856854
features.declared_lang_features.push((name, mi.span(), None));
857855
continue;
858856
}
@@ -864,6 +862,17 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
864862
features
865863
}
866864

865+
fn active_features_up_to(edition: Edition) -> impl Iterator<Item=&'static Feature> {
866+
ACTIVE_FEATURES.iter()
867+
.filter(move |feature| {
868+
if let Some(feature_edition) = feature.edition {
869+
feature_edition <= edition
870+
} else {
871+
false
872+
}
873+
})
874+
}
875+
867876
pub fn check_crate(krate: &ast::Crate,
868877
sess: &ParseSess,
869878
features: &Features,

src/libsyntax/feature_gate/mod.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,39 @@ mod active;
1818
mod builtin_attrs;
1919
mod check;
2020

21+
use std::fmt;
22+
use crate::{edition::Edition, symbol::Symbol};
23+
use syntax_pos::Span;
24+
25+
#[derive(Clone, Copy)]
26+
pub enum State {
27+
Accepted,
28+
Active { set: fn(&mut Features, Span) },
29+
Removed { reason: Option<&'static str> },
30+
Stabilized { reason: Option<&'static str> },
31+
}
32+
33+
impl fmt::Debug for State {
34+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35+
match self {
36+
State::Accepted { .. } => write!(f, "accepted"),
37+
State::Active { .. } => write!(f, "active"),
38+
State::Removed { .. } => write!(f, "removed"),
39+
State::Stabilized { .. } => write!(f, "stabilized"),
40+
}
41+
}
42+
}
43+
44+
#[derive(Debug, Clone)]
45+
pub struct Feature {
46+
state: State,
47+
name: Symbol,
48+
since: &'static str,
49+
issue: Option<u32>,
50+
edition: Option<Edition>,
51+
description: &'static str,
52+
}
53+
2154
pub use active::{Features, INCOMPLETE_FEATURES};
2255
pub use builtin_attrs::{
2356
AttributeGate, AttributeType, GatedCfg,

src/libsyntax/feature_gate/removed.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
11
//! List of the removed feature gates.
22
3-
use crate::symbol::{Symbol, sym};
3+
use crate::symbol::sym;
4+
use super::{State, Feature};
45

56
macro_rules! declare_features {
67
($(
78
$(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, None, $reason:expr),
89
)+) => {
910
/// Represents unstable features which have since been removed (it was once Active)
10-
pub const REMOVED_FEATURES: &[(Symbol, &str, Option<u32>, Option<&str>)] = &[
11-
$((sym::$feature, $ver, $issue, $reason)),+
11+
pub const REMOVED_FEATURES: &[Feature] = &[
12+
$(
13+
Feature {
14+
state: State::Removed { reason: $reason },
15+
name: sym::$feature,
16+
since: $ver,
17+
issue: $issue,
18+
edition: None,
19+
description: concat!($($doc,)*),
20+
}
21+
),+
1222
];
1323
};
1424

1525
($(
1626
$(#[doc = $doc:tt])* (stable_removed, $feature:ident, $ver:expr, $issue:expr, None),
1727
)+) => {
1828
/// Represents stable features which have since been removed (it was once Accepted)
19-
pub const STABLE_REMOVED_FEATURES: &[(Symbol, &str, Option<u32>, Option<&str>)] = &[
20-
$((sym::$feature, $ver, $issue, None)),+
29+
pub const STABLE_REMOVED_FEATURES: &[Feature] = &[
30+
$(
31+
Feature {
32+
state: State::Stabilized { reason: None },
33+
name: sym::$feature,
34+
since: $ver,
35+
issue: $issue,
36+
edition: None,
37+
description: concat!($($doc,)*),
38+
}
39+
),+
2140
];
2241
};
2342
}

0 commit comments

Comments
 (0)