Skip to content

Commit 7c78090

Browse files
committed
get_features -> rustc_parse::config
1 parent c944e6a commit 7c78090

File tree

3 files changed

+182
-178
lines changed

3 files changed

+182
-178
lines changed

src/librustc_parse/config.rs

Lines changed: 177 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,20 @@
99
//! [#64197]: https://github.com/rust-lang/rust/issues/64197
1010
1111
use crate::{parse_in, validate_attr};
12-
use rustc_errors::Applicability;
13-
use rustc_feature::Features;
14-
use rustc_span::edition::Edition;
15-
use rustc_span::symbol::sym;
16-
use rustc_span::Span;
12+
use rustc_data_structures::fx::FxHashMap;
13+
use rustc_error_codes::*;
14+
use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
15+
use rustc_feature::{Feature, Features, State as FeatureState};
16+
use rustc_feature::{
17+
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
18+
};
19+
use rustc_span::edition::{Edition, ALL_EDITIONS};
20+
use rustc_span::symbol::{sym, Symbol};
21+
use rustc_span::{Span, DUMMY_SP};
1722
use syntax::ast::{self, AttrItem, Attribute, MetaItem};
1823
use syntax::attr;
1924
use syntax::attr::HasAttrs;
20-
use syntax::feature_gate::{feature_err, get_features};
25+
use syntax::feature_gate::feature_err;
2126
use syntax::mut_visit::*;
2227
use syntax::ptr::P;
2328
use syntax::sess::ParseSess;
@@ -31,6 +36,172 @@ pub struct StripUnconfigured<'a> {
3136
pub features: Option<&'a Features>,
3237
}
3338

39+
fn get_features(
40+
span_handler: &Handler,
41+
krate_attrs: &[ast::Attribute],
42+
crate_edition: Edition,
43+
allow_features: &Option<Vec<String>>,
44+
) -> Features {
45+
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
46+
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
47+
err.span_label(span, "feature has been removed");
48+
if let Some(reason) = reason {
49+
err.note(reason);
50+
}
51+
err.emit();
52+
}
53+
54+
fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
55+
ACTIVE_FEATURES.iter().filter(move |feature| {
56+
if let Some(feature_edition) = feature.edition {
57+
feature_edition <= edition
58+
} else {
59+
false
60+
}
61+
})
62+
}
63+
64+
let mut features = Features::default();
65+
let mut edition_enabled_features = FxHashMap::default();
66+
67+
for &edition in ALL_EDITIONS {
68+
if edition <= crate_edition {
69+
// The `crate_edition` implies its respective umbrella feature-gate
70+
// (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
71+
edition_enabled_features.insert(edition.feature_name(), edition);
72+
}
73+
}
74+
75+
for feature in active_features_up_to(crate_edition) {
76+
feature.set(&mut features, DUMMY_SP);
77+
edition_enabled_features.insert(feature.name, crate_edition);
78+
}
79+
80+
// Process the edition umbrella feature-gates first, to ensure
81+
// `edition_enabled_features` is completed before it's queried.
82+
for attr in krate_attrs {
83+
if !attr.check_name(sym::feature) {
84+
continue;
85+
}
86+
87+
let list = match attr.meta_item_list() {
88+
Some(list) => list,
89+
None => continue,
90+
};
91+
92+
for mi in list {
93+
if !mi.is_word() {
94+
continue;
95+
}
96+
97+
let name = mi.name_or_empty();
98+
99+
let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
100+
if let Some(edition) = edition {
101+
if edition <= crate_edition {
102+
continue;
103+
}
104+
105+
for feature in active_features_up_to(edition) {
106+
// FIXME(Manishearth) there is currently no way to set
107+
// lib features by edition
108+
feature.set(&mut features, DUMMY_SP);
109+
edition_enabled_features.insert(feature.name, edition);
110+
}
111+
}
112+
}
113+
}
114+
115+
for attr in krate_attrs {
116+
if !attr.check_name(sym::feature) {
117+
continue;
118+
}
119+
120+
let list = match attr.meta_item_list() {
121+
Some(list) => list,
122+
None => continue,
123+
};
124+
125+
let bad_input = |span| {
126+
struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
127+
};
128+
129+
for mi in list {
130+
let name = match mi.ident() {
131+
Some(ident) if mi.is_word() => ident.name,
132+
Some(ident) => {
133+
bad_input(mi.span())
134+
.span_suggestion(
135+
mi.span(),
136+
"expected just one word",
137+
format!("{}", ident.name),
138+
Applicability::MaybeIncorrect,
139+
)
140+
.emit();
141+
continue;
142+
}
143+
None => {
144+
bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
145+
continue;
146+
}
147+
};
148+
149+
if let Some(edition) = edition_enabled_features.get(&name) {
150+
let msg =
151+
&format!("the feature `{}` is included in the Rust {} edition", name, edition);
152+
span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
153+
continue;
154+
}
155+
156+
if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
157+
// Handled in the separate loop above.
158+
continue;
159+
}
160+
161+
let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
162+
let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
163+
if let Some(Feature { state, .. }) = removed.or(stable_removed) {
164+
if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
165+
state
166+
{
167+
feature_removed(span_handler, mi.span(), *reason);
168+
continue;
169+
}
170+
}
171+
172+
if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
173+
let since = Some(Symbol::intern(since));
174+
features.declared_lang_features.push((name, mi.span(), since));
175+
continue;
176+
}
177+
178+
if let Some(allowed) = allow_features.as_ref() {
179+
if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
180+
struct_span_err!(
181+
span_handler,
182+
mi.span(),
183+
E0725,
184+
"the feature `{}` is not in the list of allowed features",
185+
name
186+
)
187+
.emit();
188+
continue;
189+
}
190+
}
191+
192+
if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
193+
f.set(&mut features, mi.span());
194+
features.declared_lang_features.push((name, mi.span(), None));
195+
continue;
196+
}
197+
198+
features.declared_lib_features.push((name, mi.span()));
199+
}
200+
}
201+
202+
features
203+
}
204+
34205
// `cfg_attr`-process the crate's attributes and compute the crate's features.
35206
pub fn features(
36207
mut krate: ast::Crate,

src/libsyntax/feature_gate/check.rs

Lines changed: 4 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,13 @@ use crate::attr;
44
use crate::sess::{feature_err, leveled_feature_err, GateStrength, ParseSess};
55
use crate::visit::{self, FnKind, Visitor};
66

7-
use rustc_data_structures::fx::FxHashMap;
87
use rustc_error_codes::*;
9-
use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
8+
use rustc_errors::{struct_span_err, Handler};
109
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
11-
use rustc_feature::{Feature, Features, GateIssue, State as FeatureState, UnstableFeatures};
12-
use rustc_feature::{
13-
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
14-
};
15-
use rustc_span::edition::{Edition, ALL_EDITIONS};
10+
use rustc_feature::{Features, GateIssue, UnstableFeatures};
1611
use rustc_span::source_map::Spanned;
17-
use rustc_span::symbol::{sym, Symbol};
18-
use rustc_span::{Span, DUMMY_SP};
12+
use rustc_span::symbol::sym;
13+
use rustc_span::Span;
1914

2015
use log::debug;
2116

@@ -659,168 +654,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
659654
}
660655
}
661656

662-
pub fn get_features(
663-
span_handler: &Handler,
664-
krate_attrs: &[ast::Attribute],
665-
crate_edition: Edition,
666-
allow_features: &Option<Vec<String>>,
667-
) -> Features {
668-
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
669-
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
670-
err.span_label(span, "feature has been removed");
671-
if let Some(reason) = reason {
672-
err.note(reason);
673-
}
674-
err.emit();
675-
}
676-
677-
let mut features = Features::default();
678-
let mut edition_enabled_features = FxHashMap::default();
679-
680-
for &edition in ALL_EDITIONS {
681-
if edition <= crate_edition {
682-
// The `crate_edition` implies its respective umbrella feature-gate
683-
// (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
684-
edition_enabled_features.insert(edition.feature_name(), edition);
685-
}
686-
}
687-
688-
for feature in active_features_up_to(crate_edition) {
689-
feature.set(&mut features, DUMMY_SP);
690-
edition_enabled_features.insert(feature.name, crate_edition);
691-
}
692-
693-
// Process the edition umbrella feature-gates first, to ensure
694-
// `edition_enabled_features` is completed before it's queried.
695-
for attr in krate_attrs {
696-
if !attr.check_name(sym::feature) {
697-
continue;
698-
}
699-
700-
let list = match attr.meta_item_list() {
701-
Some(list) => list,
702-
None => continue,
703-
};
704-
705-
for mi in list {
706-
if !mi.is_word() {
707-
continue;
708-
}
709-
710-
let name = mi.name_or_empty();
711-
712-
let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
713-
if let Some(edition) = edition {
714-
if edition <= crate_edition {
715-
continue;
716-
}
717-
718-
for feature in active_features_up_to(edition) {
719-
// FIXME(Manishearth) there is currently no way to set
720-
// lib features by edition
721-
feature.set(&mut features, DUMMY_SP);
722-
edition_enabled_features.insert(feature.name, edition);
723-
}
724-
}
725-
}
726-
}
727-
728-
for attr in krate_attrs {
729-
if !attr.check_name(sym::feature) {
730-
continue;
731-
}
732-
733-
let list = match attr.meta_item_list() {
734-
Some(list) => list,
735-
None => continue,
736-
};
737-
738-
let bad_input = |span| {
739-
struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
740-
};
741-
742-
for mi in list {
743-
let name = match mi.ident() {
744-
Some(ident) if mi.is_word() => ident.name,
745-
Some(ident) => {
746-
bad_input(mi.span())
747-
.span_suggestion(
748-
mi.span(),
749-
"expected just one word",
750-
format!("{}", ident.name),
751-
Applicability::MaybeIncorrect,
752-
)
753-
.emit();
754-
continue;
755-
}
756-
None => {
757-
bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
758-
continue;
759-
}
760-
};
761-
762-
if let Some(edition) = edition_enabled_features.get(&name) {
763-
let msg =
764-
&format!("the feature `{}` is included in the Rust {} edition", name, edition);
765-
span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
766-
continue;
767-
}
768-
769-
if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
770-
// Handled in the separate loop above.
771-
continue;
772-
}
773-
774-
let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
775-
let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
776-
if let Some(Feature { state, .. }) = removed.or(stable_removed) {
777-
if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
778-
state
779-
{
780-
feature_removed(span_handler, mi.span(), *reason);
781-
continue;
782-
}
783-
}
784-
785-
if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
786-
let since = Some(Symbol::intern(since));
787-
features.declared_lang_features.push((name, mi.span(), since));
788-
continue;
789-
}
790-
791-
if let Some(allowed) = allow_features.as_ref() {
792-
if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
793-
struct_span_err!(
794-
span_handler,
795-
mi.span(),
796-
E0725,
797-
"the feature `{}` is not in the list of allowed features",
798-
name
799-
)
800-
.emit();
801-
continue;
802-
}
803-
}
804-
805-
if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
806-
f.set(&mut features, mi.span());
807-
features.declared_lang_features.push((name, mi.span(), None));
808-
continue;
809-
}
810-
811-
features.declared_lib_features.push((name, mi.span()));
812-
}
813-
}
814-
815-
features
816-
}
817-
818-
fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
819-
ACTIVE_FEATURES.iter().filter(move |feature| {
820-
if let Some(feature_edition) = feature.edition { feature_edition <= edition } else { false }
821-
})
822-
}
823-
824657
pub fn check_crate(
825658
krate: &ast::Crate,
826659
parse_sess: &ParseSess,

0 commit comments

Comments
 (0)