Skip to content

Commit c9d9616

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 c9d9616

File tree

5 files changed

+98
-23
lines changed

5 files changed

+98
-23
lines changed

src/libsyntax/feature_gate/accepted.rs

+13-3
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

+10
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

+18-15
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
}
@@ -829,14 +828,18 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
829828
continue;
830829
}
831830

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;
831+
let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
832+
let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
833+
if let Some(Feature { state, .. }) = removed.or(stable_removed) {
834+
if let FeatureState::Removed { reason }
835+
| FeatureState::Stabilized { reason } = state
836+
{
837+
feature_removed(span_handler, mi.span(), *reason);
838+
continue;
839+
}
837840
}
838841

839-
if let Some((_, since, ..)) = ACCEPTED_FEATURES.iter().find(|f| name == f.0) {
842+
if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
840843
let since = Some(Symbol::intern(since));
841844
features.declared_lang_features.push((name, mi.span(), since));
842845
continue;
@@ -851,8 +854,8 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
851854
}
852855
}
853856

854-
if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
855-
set(&mut features, mi.span());
857+
if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
858+
f.set(&mut features, mi.span());
856859
features.declared_lang_features.push((name, mi.span(), None));
857860
continue;
858861
}

src/libsyntax/feature_gate/mod.rs

+33
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

+24-5
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)