Skip to content

Commit 365b5ea

Browse files
committed
use feature parser throughout the compiler
1 parent 4b9f5e4 commit 365b5ea

File tree

19 files changed

+192
-221
lines changed

19 files changed

+192
-221
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3402,6 +3402,7 @@ dependencies = [
34023402
"rustc_errors",
34033403
"rustc_feature",
34043404
"rustc_fluent_macro",
3405+
"rustc_hir",
34053406
"rustc_macros",
34063407
"rustc_session",
34073408
"rustc_span",

compiler/rustc_ast_passes/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
1414
rustc_errors = { path = "../rustc_errors" }
1515
rustc_feature = { path = "../rustc_feature" }
1616
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
17+
rustc_hir = { path = "../rustc_hir" }
1718
rustc_macros = { path = "../rustc_macros" }
1819
rustc_session = { path = "../rustc_session" }
1920
rustc_span = { path = "../rustc_span" }

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
use rustc_ast as ast;
22
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
33
use rustc_ast::{NodeId, PatKind, attr, token};
4+
use rustc_attr_parsing::AttributeParser;
45
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features};
6+
use rustc_hir::Attribute;
7+
use rustc_hir::attrs::AttributeKind;
58
use rustc_session::Session;
69
use rustc_session::parse::{feature_err, feature_warn};
710
use rustc_span::source_map::Spanned;
8-
use rustc_span::{Span, Symbol, sym};
11+
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
912
use thin_vec::ThinVec;
1013

1114
use crate::errors;
@@ -587,17 +590,27 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
587590
return;
588591
}
589592
let mut errored = false;
590-
for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
593+
594+
if let Some(Attribute::Parsed(AttributeKind::Feature(feature_idents, first_span))) =
595+
AttributeParser::parse_limited(
596+
sess,
597+
&krate.attrs,
598+
sym::feature,
599+
DUMMY_SP,
600+
krate.id,
601+
Some(&features),
602+
)
603+
{
591604
// `feature(...)` used on non-nightly. This is definitely an error.
592605
let mut err = errors::FeatureOnNonNightly {
593-
span: attr.span,
606+
span: first_span,
594607
channel: option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"),
595608
stable_features: vec![],
596609
sugg: None,
597610
};
598611

599612
let mut all_stable = true;
600-
for ident in attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident()) {
613+
for ident in feature_idents {
601614
let name = ident.name;
602615
let stable_since = features
603616
.enabled_lang_features()
@@ -612,7 +625,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
612625
}
613626
}
614627
if all_stable {
615-
err.sugg = Some(attr.span);
628+
err.sugg = Some(first_span);
616629
}
617630
sess.dcx().emit_err(err);
618631
errored = true;

compiler/rustc_attr_parsing/src/attributes/crate_level.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,7 @@ impl<S: Stage> CombineAttributeParser<S> for FeatureParser {
190190
const PATH: &[Symbol] = &[sym::feature];
191191
type Item = Ident;
192192
const CONVERT: ConvertFn<Self::Item> = AttributeKind::Feature;
193-
194-
// FIXME: recursion limit is allowed on all targets and ignored,
195-
// even though it should only be valid on crates of course
196-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
193+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
197194
const TEMPLATE: AttributeTemplate = template!(List: &["feature1, feature2, ..."]);
198195

199196
fn extend<'c>(

compiler/rustc_error_codes/src/error_codes/E0556.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
The `feature` attribute was badly formed.
24

35
Erroneous code example:
46

5-
```compile_fail,E0556
7+
```compile_fail
68
#![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] // error!
79
#![feature] // error!
810
#![feature = "foo"] // error!

compiler/rustc_error_codes/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ E0550: 0550,
338338
E0551: 0551,
339339
E0552: 0552,
340340
E0554: 0554,
341-
E0556: 0556,
341+
E0556: 0556, // REMOVED: merged with other attribute error codes
342342
E0557: 0557,
343343
E0559: 0559,
344344
E0560: 0560,

compiler/rustc_expand/src/config.rs

Lines changed: 33 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use rustc_ast::tokenstream::{
77
AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree,
88
};
99
use rustc_ast::{
10-
self as ast, AttrKind, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner,
11-
NodeId, NormalAttr,
10+
self as ast, AttrKind, AttrStyle, Attribute, DUMMY_NODE_ID, HasAttrs, HasTokens, MetaItem,
11+
MetaItemInner, NodeId, NormalAttr,
1212
};
1313
use rustc_attr_parsing as attr;
1414
use rustc_attr_parsing::validate_attr::deny_builtin_meta_unsafety;
@@ -21,16 +21,16 @@ use rustc_feature::{
2121
ACCEPTED_LANG_FEATURES, AttributeSafety, EnabledLangFeature, EnabledLibFeature, Features,
2222
REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES,
2323
};
24+
use rustc_hir::attrs::AttributeKind;
25+
use rustc_hir::{self as hir};
2426
use rustc_session::Session;
2527
use rustc_session::parse::feature_err;
26-
use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym};
27-
use thin_vec::ThinVec;
28+
use rustc_span::{DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym};
2829
use tracing::instrument;
2930

3031
use crate::errors::{
3132
CrateNameInCfgAttr, CrateTypeInCfgAttr, FeatureNotAllowed, FeatureRemoved,
32-
FeatureRemovedReason, InvalidCfg, MalformedFeatureAttribute, MalformedFeatureAttributeHelp,
33-
RemoveExprNotSupported,
33+
FeatureRemovedReason, InvalidCfg, RemoveExprNotSupported,
3434
};
3535

3636
/// A folder that strips out items that do not belong in the current configuration.
@@ -45,44 +45,21 @@ pub struct StripUnconfigured<'a> {
4545
}
4646

4747
pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -> Features {
48-
fn feature_list(attr: &Attribute) -> ThinVec<ast::MetaItemInner> {
49-
if attr.has_name(sym::feature)
50-
&& let Some(list) = attr.meta_item_list()
51-
{
52-
list
53-
} else {
54-
ThinVec::new()
55-
}
56-
}
57-
5848
let mut features = Features::default();
5949

60-
// Process all features enabled in the code.
61-
for attr in krate_attrs {
62-
for mi in feature_list(attr) {
63-
let name = match mi.ident() {
64-
Some(ident) if mi.is_word() => ident.name,
65-
Some(ident) => {
66-
sess.dcx().emit_err(MalformedFeatureAttribute {
67-
span: mi.span(),
68-
help: MalformedFeatureAttributeHelp::Suggestion {
69-
span: mi.span(),
70-
suggestion: ident.name,
71-
},
72-
});
73-
continue;
74-
}
75-
None => {
76-
sess.dcx().emit_err(MalformedFeatureAttribute {
77-
span: mi.span(),
78-
help: MalformedFeatureAttributeHelp::Label { span: mi.span() },
79-
});
80-
continue;
81-
}
82-
};
83-
50+
if let Some(hir::Attribute::Parsed(AttributeKind::Feature(feature_idents, _))) =
51+
AttributeParser::parse_limited(
52+
sess,
53+
krate_attrs,
54+
sym::feature,
55+
DUMMY_SP,
56+
DUMMY_NODE_ID,
57+
Some(&features),
58+
)
59+
{
60+
for name in feature_idents {
8461
// If the enabled feature has been removed, issue an error.
85-
if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| name == f.feature.name) {
62+
if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| name.name == f.feature.name) {
8663
let pull_note = if let Some(pull) = f.pull {
8764
format!(
8865
"; see <https://github.com/rust-lang/rust/pull/{}> for more information",
@@ -92,7 +69,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
9269
"".to_owned()
9370
};
9471
sess.dcx().emit_err(FeatureRemoved {
95-
span: mi.span(),
72+
span: name.span,
9673
reason: f.reason.map(|reason| FeatureRemovedReason { reason }),
9774
removed_rustc_version: f.feature.since,
9875
pull_note,
@@ -101,10 +78,10 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
10178
}
10279

10380
// If the enabled feature is stable, record it.
104-
if let Some(f) = ACCEPTED_LANG_FEATURES.iter().find(|f| name == f.name) {
81+
if let Some(f) = ACCEPTED_LANG_FEATURES.iter().find(|f| name.name == f.name) {
10582
features.set_enabled_lang_feature(EnabledLangFeature {
106-
gate_name: name,
107-
attr_sp: mi.span(),
83+
gate_name: name.name,
84+
attr_sp: name.span,
10885
stable_since: Some(Symbol::intern(f.since)),
10986
});
11087
continue;
@@ -114,38 +91,40 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
11491
// unstable and not also listed as one of the allowed features,
11592
// issue an error.
11693
if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
117-
if allowed.iter().all(|f| name.as_str() != f) {
118-
sess.dcx().emit_err(FeatureNotAllowed { span: mi.span(), name });
94+
if allowed.iter().all(|f| name.name.as_str() != f) {
95+
sess.dcx().emit_err(FeatureNotAllowed { span: name.span, name: name.name });
11996
continue;
12097
}
12198
}
12299

123100
// If the enabled feature is unstable, record it.
124-
if UNSTABLE_LANG_FEATURES.iter().find(|f| name == f.name).is_some() {
101+
if UNSTABLE_LANG_FEATURES.iter().find(|f| name.name == f.name).is_some() {
125102
// When the ICE comes a standard library crate, there's a chance that the person
126103
// hitting the ICE may be using -Zbuild-std or similar with an untested target.
127104
// The bug is probably in the standard library and not the compiler in that case,
128105
// but that doesn't really matter - we want a bug report.
129-
if features.internal(name) && !STDLIB_STABLE_CRATES.contains(&crate_name) {
106+
if features.internal(name.name) && !STDLIB_STABLE_CRATES.contains(&crate_name) {
130107
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
131108
}
132109

133110
features.set_enabled_lang_feature(EnabledLangFeature {
134-
gate_name: name,
135-
attr_sp: mi.span(),
111+
gate_name: name.name,
112+
attr_sp: name.span,
136113
stable_since: None,
137114
});
138115
continue;
139116
}
140117

141118
// Otherwise, the feature is unknown. Enable it as a lib feature.
142119
// It will be checked later whether the feature really exists.
143-
features
144-
.set_enabled_lib_feature(EnabledLibFeature { gate_name: name, attr_sp: mi.span() });
120+
features.set_enabled_lib_feature(EnabledLibFeature {
121+
gate_name: name.name,
122+
attr_sp: name.span,
123+
});
145124

146125
// Similar to above, detect internal lib features to suppress
147126
// the ICE message that asks for a report.
148-
if features.internal(name) && !STDLIB_STABLE_CRATES.contains(&crate_name) {
127+
if features.internal(name.name) && !STDLIB_STABLE_CRATES.contains(&crate_name) {
149128
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
150129
}
151130
}

compiler/rustc_expand/src/errors.rs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -143,30 +143,6 @@ pub(crate) struct RecursionLimitReached {
143143
pub crate_name: Symbol,
144144
}
145145

146-
#[derive(Diagnostic)]
147-
#[diag(expand_malformed_feature_attribute, code = E0556)]
148-
pub(crate) struct MalformedFeatureAttribute {
149-
#[primary_span]
150-
pub span: Span,
151-
#[subdiagnostic]
152-
pub help: MalformedFeatureAttributeHelp,
153-
}
154-
155-
#[derive(Subdiagnostic)]
156-
pub(crate) enum MalformedFeatureAttributeHelp {
157-
#[label(expand_expected)]
158-
Label {
159-
#[primary_span]
160-
span: Span,
161-
},
162-
#[suggestion(expand_expected, code = "{suggestion}", applicability = "maybe-incorrect")]
163-
Suggestion {
164-
#[primary_span]
165-
span: Span,
166-
suggestion: Symbol,
167-
},
168-
}
169-
170146
#[derive(Diagnostic)]
171147
#[diag(expand_remove_expr_not_supported)]
172148
pub(crate) struct RemoveExprNotSupported {

compiler/rustc_lint/src/builtin.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,12 +1133,10 @@ declare_lint_pass!(
11331133
);
11341134

11351135
impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
1136-
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &hir::Attribute) {
1137-
if attr.has_name(sym::feature)
1138-
&& let Some(items) = attr.meta_item_list()
1139-
{
1140-
for item in items {
1141-
cx.emit_span_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
1136+
fn check_attributes(&mut self, cx: &LateContext<'_>, attrs: &[hir::Attribute]) {
1137+
if let Some(features) = find_attr!(attrs, AttributeKind::Feature(features, _) => features) {
1138+
for feature in features {
1139+
cx.emit_span_lint(UNSTABLE_FEATURES, feature.span, BuiltinUnstableFeatures);
11421140
}
11431141
}
11441142
}

tests/pretty/hir-delegation.pp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//@ pp-exact:hir-delegation.pp
44

55
#![allow(incomplete_features)]
6-
#![feature(fn_delegation)]
6+
#![attr = Feature([fn_delegation#0])]
77
#[attr = MacroUse {arguments: UseAll}]
88
extern crate std;
99
#[prelude_import]

0 commit comments

Comments
 (0)