Skip to content

Commit 45e50e2

Browse files
authored
Rollup merge of rust-lang#64462 - petrochenkov:remattr, r=Centril
feature_gate: Remove dead code from attribute checking rust-lang#63468 is merged, so all attributes go through name resolution now, so we can remove code that previously performed some checks for attributes not going through resolution.
2 parents 5f9b9b2 + cb771fd commit 45e50e2

13 files changed

+63
-161
lines changed

src/librustc_interface/passes.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ use syntax::mut_visit::MutVisitor;
4141
use syntax::parse::{self, PResult};
4242
use syntax::util::node_count::NodeCounter;
4343
use syntax::symbol::Symbol;
44-
use syntax::feature_gate::AttributeType;
4544
use syntax_pos::FileName;
4645
use syntax_ext;
4746

@@ -219,7 +218,6 @@ impl BoxedResolver {
219218

220219
pub struct PluginInfo {
221220
syntax_exts: Vec<NamedSyntaxExtension>,
222-
attributes: Vec<(Symbol, AttributeType)>,
223221
}
224222

225223
pub fn register_plugins<'a>(
@@ -312,12 +310,9 @@ pub fn register_plugins<'a>(
312310
}
313311

314312
*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
315-
*sess.plugin_attributes.borrow_mut() = attributes.clone();
313+
*sess.plugin_attributes.borrow_mut() = attributes;
316314

317-
Ok((krate, PluginInfo {
318-
syntax_exts,
319-
attributes,
320-
}))
315+
Ok((krate, PluginInfo { syntax_exts }))
321316
}
322317

323318
fn configure_and_expand_inner<'a>(
@@ -329,7 +324,6 @@ fn configure_and_expand_inner<'a>(
329324
crate_loader: &'a mut CrateLoader<'a>,
330325
plugin_info: PluginInfo,
331326
) -> Result<(ast::Crate, Resolver<'a>)> {
332-
let attributes = plugin_info.attributes;
333327
time(sess, "pre ast expansion lint checks", || {
334328
lint::check_ast_crate(
335329
sess,
@@ -522,7 +516,6 @@ fn configure_and_expand_inner<'a>(
522516
&krate,
523517
&sess.parse_sess,
524518
&sess.features_untracked(),
525-
&attributes,
526519
sess.opts.unstable_features,
527520
);
528521
});

src/libsyntax/ext/expand.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use syntax_pos::{Span, DUMMY_SP, FileName};
2626
use rustc_data_structures::fx::FxHashMap;
2727
use rustc_data_structures::sync::Lrc;
2828
use std::io::ErrorKind;
29-
use std::{iter, mem};
29+
use std::{iter, mem, slice};
3030
use std::ops::DerefMut;
3131
use std::rc::Rc;
3232
use std::path::PathBuf;
@@ -1019,7 +1019,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10191019
fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
10201020
let features = self.cx.ecfg.features.unwrap();
10211021
for attr in attrs.iter() {
1022-
self.check_attribute_inner(attr, features);
1022+
feature_gate::check_attribute(attr, self.cx.parse_sess, features);
10231023

10241024
// macros are expanded before any lint passes so this warning has to be hardcoded
10251025
if attr.path == sym::derive {
@@ -1029,15 +1029,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10291029
}
10301030
}
10311031
}
1032-
1033-
fn check_attribute(&mut self, at: &ast::Attribute) {
1034-
let features = self.cx.ecfg.features.unwrap();
1035-
self.check_attribute_inner(at, features);
1036-
}
1037-
1038-
fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) {
1039-
feature_gate::check_attribute(at, self.cx.parse_sess, features);
1040-
}
10411032
}
10421033

10431034
impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
@@ -1445,7 +1436,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14451436

14461437
if let Some(file) = it.value_str() {
14471438
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
1448-
self.check_attribute(&at);
1439+
self.check_attributes(slice::from_ref(at));
14491440
if self.cx.parse_sess.span_diagnostic.err_count() > err_count {
14501441
// avoid loading the file if they haven't enabled the feature
14511442
return noop_visit_attribute(at, self);

src/libsyntax/feature_gate/builtin_attrs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub enum AttributeType {
7979
CrateLevel,
8080
}
8181

82+
#[derive(Clone, Copy)]
8283
pub enum AttributeGate {
8384
/// Is gated by a given feature gate, reason
8485
/// and function to check if enabled

src/libsyntax/feature_gate/check.rs

+47-131
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
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};
4-
use super::builtin_attrs::{AttributeGate, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
4+
use super::builtin_attrs::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
55

66
use crate::ast::{
77
self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind,
@@ -32,16 +32,10 @@ pub enum Stability {
3232
Deprecated(&'static str, Option<&'static str>),
3333
}
3434

35-
struct Context<'a> {
36-
features: &'a Features,
37-
parse_sess: &'a ParseSess,
38-
plugin_attributes: &'a [(Symbol, AttributeType)],
39-
}
40-
4135
macro_rules! gate_feature_fn {
4236
($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
4337
let (cx, has_feature, span,
44-
name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
38+
name, explain, level) = (&*$cx, $has_feature, $span, $name, $explain, $level);
4539
let has_feature: bool = has_feature(&$cx.features);
4640
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
4741
if !has_feature && !span.allows_unstable($name) {
@@ -62,68 +56,8 @@ macro_rules! gate_feature {
6256
};
6357
}
6458

65-
impl<'a> Context<'a> {
66-
fn check_attribute(
67-
&self,
68-
attr: &ast::Attribute,
69-
attr_info: Option<&BuiltinAttribute>,
70-
is_macro: bool
71-
) {
72-
debug!("check_attribute(attr = {:?})", attr);
73-
if let Some(&(name, ty, _template, ref gateage)) = attr_info {
74-
if let AttributeGate::Gated(_, name, desc, ref has_feature) = *gateage {
75-
if !attr.span.allows_unstable(name) {
76-
gate_feature_fn!(
77-
self, has_feature, attr.span, name, desc, GateStrength::Hard
78-
);
79-
}
80-
} else if name == sym::doc {
81-
if let Some(content) = attr.meta_item_list() {
82-
if content.iter().any(|c| c.check_name(sym::include)) {
83-
gate_feature!(self, external_doc, attr.span,
84-
"`#[doc(include = \"...\")]` is experimental"
85-
);
86-
}
87-
}
88-
}
89-
debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
90-
return;
91-
} else {
92-
for segment in &attr.path.segments {
93-
if segment.ident.as_str().starts_with("rustc") {
94-
let msg = "attributes starting with `rustc` are \
95-
reserved for use by the `rustc` compiler";
96-
gate_feature!(self, rustc_attrs, segment.ident.span, msg);
97-
}
98-
}
99-
}
100-
for &(n, ty) in self.plugin_attributes {
101-
if attr.path == n {
102-
// Plugins can't gate attributes, so we don't check for it
103-
// unlike the code above; we only use this loop to
104-
// short-circuit to avoid the checks below.
105-
debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty);
106-
return;
107-
}
108-
}
109-
if !is_macro && !attr::is_known(attr) {
110-
// Only run the custom attribute lint during regular feature gate
111-
// checking. Macro gating runs before the plugin attributes are
112-
// registered, so we skip this in that case.
113-
let msg = format!("the attribute `{}` is currently unknown to the compiler and \
114-
may have meaning added to it in the future", attr.path);
115-
gate_feature!(self, custom_attribute, attr.span, &msg);
116-
}
117-
}
118-
}
119-
120-
pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
121-
let cx = Context { features, parse_sess, plugin_attributes: &[] };
122-
cx.check_attribute(
123-
attr,
124-
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name).map(|a| *a)),
125-
true
126-
);
59+
crate fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
60+
PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
12761
}
12862

12963
fn find_lang_feature_issue(feature: Symbol) -> Option<u32> {
@@ -238,21 +172,21 @@ pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str =
238172
"unsized tuple coercion is not stable enough for use and is subject to change";
239173

240174
struct PostExpansionVisitor<'a> {
241-
context: &'a Context<'a>,
242-
builtin_attributes: &'static FxHashMap<Symbol, &'static BuiltinAttribute>,
175+
parse_sess: &'a ParseSess,
176+
features: &'a Features,
243177
}
244178

245179
macro_rules! gate_feature_post {
246180
($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{
247181
let (cx, span) = ($cx, $span);
248182
if !span.allows_unstable(sym::$feature) {
249-
gate_feature!(cx.context, $feature, span, $explain)
183+
gate_feature!(cx, $feature, span, $explain)
250184
}
251185
}};
252186
($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
253187
let (cx, span) = ($cx, $span);
254188
if !span.allows_unstable(sym::$feature) {
255-
gate_feature!(cx.context, $feature, span, $explain, $level)
189+
gate_feature!(cx, $feature, span, $explain, $level)
256190
}
257191
}}
258192
}
@@ -316,58 +250,52 @@ impl<'a> PostExpansionVisitor<'a> {
316250

317251
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
318252
fn visit_attribute(&mut self, attr: &ast::Attribute) {
319-
let attr_info = attr.ident().and_then(|ident| {
320-
self.builtin_attributes.get(&ident.name).map(|a| *a)
321-
});
322-
323-
// Check for gated attributes.
324-
self.context.check_attribute(attr, attr_info, false);
325-
326-
if attr.check_name(sym::doc) {
327-
if let Some(content) = attr.meta_item_list() {
328-
if content.len() == 1 && content[0].check_name(sym::cfg) {
329-
gate_feature_post!(&self, doc_cfg, attr.span,
330-
"`#[doc(cfg(...))]` is experimental"
331-
);
332-
} else if content.iter().any(|c| c.check_name(sym::masked)) {
333-
gate_feature_post!(&self, doc_masked, attr.span,
334-
"`#[doc(masked)]` is experimental"
335-
);
336-
} else if content.iter().any(|c| c.check_name(sym::spotlight)) {
337-
gate_feature_post!(&self, doc_spotlight, attr.span,
338-
"`#[doc(spotlight)]` is experimental"
339-
);
340-
} else if content.iter().any(|c| c.check_name(sym::alias)) {
341-
gate_feature_post!(&self, doc_alias, attr.span,
342-
"`#[doc(alias = \"...\")]` is experimental"
343-
);
344-
} else if content.iter().any(|c| c.check_name(sym::keyword)) {
345-
gate_feature_post!(&self, doc_keyword, attr.span,
346-
"`#[doc(keyword = \"...\")]` is experimental"
347-
);
348-
}
349-
}
253+
let attr_info =
254+
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);
255+
// Check feature gates for built-in attributes.
256+
if let Some((.., AttributeGate::Gated(_, name, descr, has_feature))) = attr_info {
257+
gate_feature_fn!(self, has_feature, attr.span, name, descr, GateStrength::Hard);
350258
}
351-
259+
// Check input tokens for built-in and key-value attributes.
352260
match attr_info {
353261
// `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
354-
Some(&(name, _, template, _)) if name != sym::rustc_dummy =>
355-
check_builtin_attribute(self.context.parse_sess, attr, name, template),
262+
Some((name, _, template, _)) if name != sym::rustc_dummy =>
263+
check_builtin_attribute(self.parse_sess, attr, name, template),
356264
_ => if let Some(TokenTree::Token(token)) = attr.tokens.trees().next() {
357265
if token == token::Eq {
358266
// All key-value attributes are restricted to meta-item syntax.
359-
attr.parse_meta(self.context.parse_sess).map_err(|mut err| err.emit()).ok();
267+
attr.parse_meta(self.parse_sess).map_err(|mut err| err.emit()).ok();
360268
}
361269
}
362270
}
271+
// Check unstable flavors of the `#[doc]` attribute.
272+
if attr.check_name(sym::doc) {
273+
for nested_meta in attr.meta_item_list().unwrap_or_default() {
274+
macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
275+
$(if nested_meta.check_name(sym::$name) {
276+
let msg = concat!("`#[doc(", stringify!($name), ")]` is experimental");
277+
gate_feature!(self, $feature, attr.span, msg);
278+
})*
279+
}}
280+
281+
gate_doc!(
282+
include => external_doc
283+
cfg => doc_cfg
284+
masked => doc_masked
285+
spotlight => doc_spotlight
286+
alias => doc_alias
287+
keyword => doc_keyword
288+
);
289+
}
290+
}
363291
}
364292

365293
fn visit_name(&mut self, sp: Span, name: ast::Name) {
366294
if !name.as_str().is_ascii() {
367295
gate_feature_post!(
368296
&self,
369297
non_ascii_idents,
370-
self.context.parse_sess.source_map().def_span(sp),
298+
self.parse_sess.source_map().def_span(sp),
371299
"non-ascii idents are not fully supported"
372300
);
373301
}
@@ -423,12 +351,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
423351
}
424352
}
425353

426-
let has_feature = self.context.features.arbitrary_enum_discriminant;
354+
let has_feature = self.features.arbitrary_enum_discriminant;
427355
if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
428-
Parser::maybe_report_invalid_custom_discriminants(
429-
self.context.parse_sess,
430-
&variants,
431-
);
356+
Parser::maybe_report_invalid_custom_discriminants(self.parse_sess, &variants);
432357
}
433358
}
434359

@@ -538,7 +463,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
538463
ast::ExprKind::Type(..) => {
539464
// To avoid noise about type ascription in common syntax errors, only emit if it
540465
// is the *only* error.
541-
if self.context.parse_sess.span_diagnostic.err_count() == 0 {
466+
if self.parse_sess.span_diagnostic.err_count() == 0 {
542467
gate_feature_post!(&self, type_ascription, e.span,
543468
"type ascription is experimental");
544469
}
@@ -872,22 +797,17 @@ fn active_features_up_to(edition: Edition) -> impl Iterator<Item=&'static Featur
872797
}
873798

874799
pub fn check_crate(krate: &ast::Crate,
875-
sess: &ParseSess,
800+
parse_sess: &ParseSess,
876801
features: &Features,
877-
plugin_attributes: &[(Symbol, AttributeType)],
878802
unstable: UnstableFeatures) {
879-
maybe_stage_features(&sess.span_diagnostic, krate, unstable);
880-
let ctx = Context {
881-
features,
882-
parse_sess: sess,
883-
plugin_attributes,
884-
};
803+
maybe_stage_features(&parse_sess.span_diagnostic, krate, unstable);
804+
let mut visitor = PostExpansionVisitor { parse_sess, features };
885805

886806
macro_rules! gate_all {
887807
($gate:ident, $msg:literal) => { gate_all!($gate, $gate, $msg); };
888808
($spans:ident, $gate:ident, $msg:literal) => {
889-
for span in &*sess.gated_spans.$spans.borrow() {
890-
gate_feature!(&ctx, $gate, *span, $msg);
809+
for span in &*parse_sess.gated_spans.$spans.borrow() {
810+
gate_feature!(&visitor, $gate, *span, $msg);
891811
}
892812
}
893813
}
@@ -898,11 +818,7 @@ pub fn check_crate(krate: &ast::Crate,
898818
gate_all!(yields, generators, "yield syntax is experimental");
899819
gate_all!(or_patterns, "or-patterns syntax is experimental");
900820

901-
let visitor = &mut PostExpansionVisitor {
902-
context: &ctx,
903-
builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP,
904-
};
905-
visit::walk_crate(visitor, krate);
821+
visit::walk_crate(&mut visitor, krate);
906822
}
907823

908824
#[derive(Clone, Copy, Hash)]

src/libsyntax/feature_gate/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ pub use builtin_attrs::{
5858
deprecated_attributes, is_builtin_attr, is_builtin_attr_name,
5959
};
6060
pub use check::{
61-
check_attribute, check_crate, get_features, feature_err, emit_feature_err,
61+
check_crate, get_features, feature_err, emit_feature_err,
6262
Stability, GateIssue, UnstableFeatures,
6363
EXPLAIN_STMT_ATTR_SYNTAX, EXPLAIN_UNSIZED_TUPLE_COERCION,
6464
};
65+
crate use check::check_attribute;
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[doc(alias = "foo")] //~ ERROR: `#[doc(alias = "...")]` is experimental
1+
#[doc(alias = "foo")] //~ ERROR: `#[doc(alias)]` is experimental
22
pub struct Foo;
33

44
fn main() {}

src/test/ui/feature-gates/feature-gate-doc_alias.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0658]: `#[doc(alias = "...")]` is experimental
1+
error[E0658]: `#[doc(alias)]` is experimental
22
--> $DIR/feature-gate-doc_alias.rs:1:1
33
|
44
LL | #[doc(alias = "foo")]

0 commit comments

Comments
 (0)