Skip to content

Commit ca941b9

Browse files
committed
Introduce new-style attribute parsers for several attributes
1 parent 781ba15 commit ca941b9

File tree

46 files changed

+1317
-1151
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1317
-1151
lines changed

Cargo.lock

+5
Original file line numberDiff line numberDiff line change
@@ -3478,6 +3478,7 @@ dependencies = [
34783478
"rustc_expand",
34793479
"rustc_feature",
34803480
"rustc_fluent_macro",
3481+
"rustc_hir",
34813482
"rustc_index",
34823483
"rustc_lexer",
34833484
"rustc_lint_defs",
@@ -3729,6 +3730,7 @@ dependencies = [
37293730
"rustc_abi",
37303731
"rustc_ast",
37313732
"rustc_ast_pretty",
3733+
"rustc_attr_data_structures",
37323734
"rustc_data_structures",
37333735
"rustc_error_codes",
37343736
"rustc_error_messages",
@@ -3762,6 +3764,7 @@ dependencies = [
37623764
"rustc_errors",
37633765
"rustc_feature",
37643766
"rustc_fluent_macro",
3767+
"rustc_hir",
37653768
"rustc_lexer",
37663769
"rustc_lint_defs",
37673770
"rustc_macros",
@@ -4440,6 +4443,7 @@ version = "0.0.0"
44404443
dependencies = [
44414444
"bitflags",
44424445
"rustc_abi",
4446+
"rustc_ast",
44434447
"rustc_data_structures",
44444448
"rustc_hir",
44454449
"rustc_middle",
@@ -4533,6 +4537,7 @@ dependencies = [
45334537
"punycode",
45344538
"rustc-demangle",
45354539
"rustc_abi",
4540+
"rustc_ast",
45364541
"rustc_data_structures",
45374542
"rustc_errors",
45384543
"rustc_hir",

compiler/rustc_ast_passes/messages.ftl

-2
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,6 @@ ast_passes_precise_capturing_duplicated = duplicate `use<...>` precise capturing
207207
208208
ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax not allowed in {$loc}
209209
210-
ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library
211-
212210
ast_passes_static_without_body =
213211
free static item without body
214212
.suggestion = provide a definition for the static

compiler/rustc_ast_passes/src/errors.rs

-7
Original file line numberDiff line numberDiff line change
@@ -732,13 +732,6 @@ pub(crate) struct AssociatedSuggestion2 {
732732
pub potential_assoc: Ident,
733733
}
734734

735-
#[derive(Diagnostic)]
736-
#[diag(ast_passes_stability_outside_std, code = E0734)]
737-
pub(crate) struct StabilityOutsideStd {
738-
#[primary_span]
739-
pub span: Span,
740-
}
741-
742735
#[derive(Diagnostic)]
743736
#[diag(ast_passes_feature_on_non_nightly, code = E0554)]
744737
pub(crate) struct FeatureOnNonNightly {

compiler/rustc_ast_passes/src/feature_gate.rs

-12
Original file line numberDiff line numberDiff line change
@@ -208,18 +208,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
208208
);
209209
}
210210
}
211-
212-
// Emit errors for non-staged-api crates.
213-
if !self.features.staged_api() {
214-
if attr.has_name(sym::unstable)
215-
|| attr.has_name(sym::stable)
216-
|| attr.has_name(sym::rustc_const_unstable)
217-
|| attr.has_name(sym::rustc_const_stable)
218-
|| attr.has_name(sym::rustc_default_body_unstable)
219-
{
220-
self.sess.dcx().emit_err(errors::StabilityOutsideStd { span: attr.span });
221-
}
222-
}
223211
}
224212

225213
fn visit_item(&mut self, i: &'a ast::Item) {

compiler/rustc_attr_data_structures/src/attributes.rs

+40-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ use rustc_abi::Align;
22
use rustc_ast::token::CommentKind;
33
use rustc_ast::{self as ast, AttrStyle};
44
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
5+
use rustc_span::hygiene::Transparency;
56
use rustc_span::{Span, Symbol};
7+
use thin_vec::ThinVec;
68

7-
use crate::RustcVersion;
9+
use crate::{DefaultBodyStability, PartialConstStability, RustcVersion, Stability};
810

911
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
1012
pub enum InlineAttr {
@@ -141,6 +143,42 @@ impl Deprecation {
141143
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
142144
pub enum AttributeKind {
143145
// tidy-alphabetical-start
144-
DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
146+
AllowConstFnUnstable(ThinVec<Symbol>),
147+
AllowInternalUnsafe,
148+
AllowInternalUnstable(ThinVec<Symbol>),
149+
BodyStability {
150+
stability: DefaultBodyStability,
151+
/// Span of the `#[rustc_default_body_unstable(...)]` attribute
152+
span: Span,
153+
},
154+
Confusables {
155+
symbols: ThinVec<Symbol>,
156+
// FIXME(jdonszelmann): remove when target validation code is moved
157+
first_span: Span,
158+
},
159+
ConstStability {
160+
stability: PartialConstStability,
161+
/// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
162+
span: Span,
163+
},
164+
ConstStabilityIndirect,
165+
Deprecation {
166+
deprecation: Deprecation,
167+
span: Span,
168+
},
169+
Diagnostic(DiagnosticAttribute),
170+
DocComment {
171+
style: AttrStyle,
172+
kind: CommentKind,
173+
span: Span,
174+
comment: Symbol,
175+
},
176+
MacroTransparency(Transparency),
177+
Repr(ThinVec<ReprAttr>),
178+
Stability {
179+
stability: Stability,
180+
/// Span of the `#[stable(...)]` or `#[unstable(...)]` attribute
181+
span: Span,
182+
},
145183
// tidy-alphabetical-end
146184
}

compiler/rustc_attr_parsing/messages.ftl

+11-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ attr_parsing_deprecated_item_suggestion =
66
.help = add `#![feature(deprecated_suggestion)]` to the crate root
77
.note = see #94785 for more details
88
9+
attr_parsing_empty_confusables =
10+
expected at least one confusable name
911
attr_parsing_expected_one_cfg_pattern =
1012
expected 1 cfg-pattern
1113
@@ -21,8 +23,8 @@ attr_parsing_expects_feature_list =
2123
attr_parsing_expects_features =
2224
`{$name}` expects feature names
2325
24-
attr_parsing_incorrect_meta_item =
25-
incorrect meta item
26+
attr_parsing_incorrect_meta_item = expected a quoted string literal
27+
attr_parsing_incorrect_meta_item_suggestion = consider surrounding this with quotes
2628
2729
attr_parsing_incorrect_repr_format_align_one_arg =
2830
incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
@@ -93,15 +95,14 @@ attr_parsing_repr_ident =
9395
attr_parsing_rustc_allowed_unstable_pairing =
9496
`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
9597
96-
attr_parsing_rustc_const_stable_indirect_pairing =
97-
`const_stable_indirect` attribute does not make sense on `rustc_const_stable` function, its behavior is already implied
98-
9998
attr_parsing_rustc_promotable_pairing =
10099
`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
101100
102101
attr_parsing_soft_no_args =
103102
`soft` should not have any arguments
104103
104+
attr_parsing_stability_outside_std = stability attributes may not be used outside of the standard library
105+
105106
attr_parsing_unknown_meta_item =
106107
unknown meta item '{$item}'
107108
.label = expected one of {$expected}
@@ -128,3 +129,8 @@ attr_parsing_unsupported_literal_generic =
128129
unsupported literal
129130
attr_parsing_unsupported_literal_suggestion =
130131
consider removing the prefix
132+
133+
attr_parsing_unused_multiple =
134+
multiple `{$name}` attributes
135+
.suggestion = remove this attribute
136+
.note = attribute also specified here
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,65 @@
1-
use rustc_ast::attr::{AttributeExt, filter_by_name};
2-
use rustc_session::Session;
1+
use rustc_attr_data_structures::AttributeKind;
32
use rustc_span::{Symbol, sym};
43

4+
use super::{CombineAttributeParser, ConvertFn};
5+
use crate::context::AcceptContext;
6+
use crate::parser::ArgParser;
57
use crate::session_diagnostics;
68

7-
pub fn allow_internal_unstable<'a>(
8-
sess: &'a Session,
9-
attrs: &'a [impl AttributeExt],
10-
) -> impl Iterator<Item = Symbol> + 'a {
11-
allow_unstable(sess, attrs, sym::allow_internal_unstable)
9+
pub(crate) struct AllowInternalUnstableParser;
10+
impl CombineAttributeParser for AllowInternalUnstableParser {
11+
const PATH: &'static [rustc_span::Symbol] = &[sym::allow_internal_unstable];
12+
type Item = Symbol;
13+
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowInternalUnstable;
14+
15+
fn extend<'a>(
16+
cx: &'a AcceptContext<'a>,
17+
args: &'a ArgParser<'a>,
18+
) -> impl IntoIterator<Item = Self::Item> + 'a {
19+
parse_unstable(cx, args, Self::PATH[0])
20+
}
1221
}
1322

14-
pub fn rustc_allow_const_fn_unstable<'a>(
15-
sess: &'a Session,
16-
attrs: &'a [impl AttributeExt],
17-
) -> impl Iterator<Item = Symbol> + 'a {
18-
allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)
23+
pub(crate) struct AllowConstFnUnstableParser;
24+
impl CombineAttributeParser for AllowConstFnUnstableParser {
25+
const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_allow_const_fn_unstable];
26+
type Item = Symbol;
27+
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowConstFnUnstable;
28+
29+
fn extend<'a>(
30+
cx: &'a AcceptContext<'a>,
31+
args: &'a ArgParser<'a>,
32+
) -> impl IntoIterator<Item = Self::Item> + 'a {
33+
parse_unstable(cx, args, Self::PATH[0])
34+
}
1935
}
2036

21-
fn allow_unstable<'a>(
22-
sess: &'a Session,
23-
attrs: &'a [impl AttributeExt],
37+
fn parse_unstable<'a>(
38+
cx: &AcceptContext<'_>,
39+
args: &'a ArgParser<'a>,
2440
symbol: Symbol,
25-
) -> impl Iterator<Item = Symbol> + 'a {
26-
let attrs = filter_by_name(attrs, symbol);
27-
let list = attrs
28-
.filter_map(move |attr| {
29-
attr.meta_item_list().or_else(|| {
30-
sess.dcx().emit_err(session_diagnostics::ExpectsFeatureList {
31-
span: attr.span(),
32-
name: symbol.to_ident_string(),
33-
});
34-
None
35-
})
36-
})
37-
.flatten();
38-
39-
list.into_iter().filter_map(move |it| {
40-
let name = it.ident().map(|ident| ident.name);
41-
if name.is_none() {
42-
sess.dcx().emit_err(session_diagnostics::ExpectsFeatures {
43-
span: it.span(),
41+
) -> impl IntoIterator<Item = Symbol> {
42+
let mut res = Vec::new();
43+
44+
let Some(list) = args.list() else {
45+
cx.dcx().emit_err(session_diagnostics::ExpectsFeatureList {
46+
span: cx.attr_span,
47+
name: symbol.to_ident_string(),
48+
});
49+
return res;
50+
};
51+
52+
for param in list.mixed() {
53+
let param_span = param.span();
54+
if let Some(ident) = param.meta_item().and_then(|i| i.word_without_args()) {
55+
res.push(ident.name);
56+
} else {
57+
cx.dcx().emit_err(session_diagnostics::ExpectsFeatures {
58+
span: param_span,
4459
name: symbol.to_ident_string(),
4560
});
4661
}
47-
name
48-
})
62+
}
63+
64+
res
4965
}

compiler/rustc_attr_parsing/src/attributes/cfg.rs

+15-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
//! Parsing and validation of builtin attributes
2-
3-
use rustc_ast::{self as ast, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
1+
// TODO: convert cfg properly.... And learn how cfg works I guess
2+
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
43
use rustc_ast_pretty::pprust;
54
use rustc_attr_data_structures::RustcVersion;
65
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
@@ -9,10 +8,11 @@ use rustc_session::config::ExpectedValues;
98
use rustc_session::lint::BuiltinLintDiag;
109
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
1110
use rustc_session::parse::feature_err;
12-
use rustc_span::{Span, Symbol, kw, sym};
11+
use rustc_span::symbol::kw;
12+
use rustc_span::{Span, Symbol, sym};
1313

14-
use crate::util::UnsupportedLiteralReason;
15-
use crate::{fluent_generated, parse_version, session_diagnostics};
14+
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
15+
use crate::{fluent_generated, parse_version};
1616

1717
#[derive(Clone, Debug)]
1818
pub struct Condition {
@@ -25,7 +25,7 @@ pub struct Condition {
2525

2626
/// Tests if a cfg-pattern matches the cfg set
2727
pub fn cfg_matches(
28-
cfg: &ast::MetaItemInner,
28+
cfg: &MetaItemInner,
2929
sess: &Session,
3030
lint_node_id: NodeId,
3131
features: Option<&Features>,
@@ -80,16 +80,16 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Fea
8080
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
8181
/// evaluate individual items.
8282
pub fn eval_condition(
83-
cfg: &ast::MetaItemInner,
83+
cfg: &MetaItemInner,
8484
sess: &Session,
8585
features: Option<&Features>,
8686
eval: &mut impl FnMut(Condition) -> bool,
8787
) -> bool {
8888
let dcx = sess.dcx();
8989

9090
let cfg = match cfg {
91-
ast::MetaItemInner::MetaItem(meta_item) => meta_item,
92-
ast::MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
91+
MetaItemInner::MetaItem(meta_item) => meta_item,
92+
MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
9393
if let Some(features) = features {
9494
// we can't use `try_gate_cfg` as symbols don't differentiate between `r#true`
9595
// and `true`, and we want to keep the former working without feature gate
@@ -118,7 +118,7 @@ pub fn eval_condition(
118118
};
119119

120120
match &cfg.kind {
121-
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
121+
MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
122122
try_gate_cfg(sym::version, cfg.span, sess, features);
123123
let (min_version, span) = match &mis[..] {
124124
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
@@ -150,7 +150,7 @@ pub fn eval_condition(
150150
RustcVersion::CURRENT >= min_version
151151
}
152152
}
153-
ast::MetaItemKind::List(mis) => {
153+
MetaItemKind::List(mis) => {
154154
for mi in mis.iter() {
155155
if mi.meta_item_or_bool().is_none() {
156156
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
@@ -209,12 +209,7 @@ pub fn eval_condition(
209209
seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
210210
}
211211

212-
res & eval_condition(
213-
&ast::MetaItemInner::MetaItem(mi),
214-
sess,
215-
features,
216-
eval,
217-
)
212+
res & eval_condition(&MetaItemInner::MetaItem(mi), sess, features, eval)
218213
})
219214
}
220215
_ => {
@@ -226,7 +221,7 @@ pub fn eval_condition(
226221
}
227222
}
228223
}
229-
ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
224+
MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
230225
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
231226
true
232227
}
@@ -239,7 +234,7 @@ pub fn eval_condition(
239234
});
240235
true
241236
}
242-
ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
237+
MetaItemKind::Word | MetaItemKind::NameValue(..) => {
243238
let ident = cfg.ident().expect("multi-segment cfg predicate");
244239
eval(Condition {
245240
name: ident.name,

0 commit comments

Comments
 (0)