Skip to content

Commit 10cf134

Browse files
Port #[cfg_attr] to the new attribute parsing infrastructure
Signed-off-by: Jonathan Brouwer <[email protected]>
1 parent 29ac1a3 commit 10cf134

File tree

5 files changed

+109
-43
lines changed

5 files changed

+109
-43
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ attr_parsing_as_needed_compatibility =
44
attr_parsing_bundle_needs_static =
55
linking modifier `bundle` is only compatible with `static` linking kind
66
7+
attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
8+
79
attr_parsing_cfg_predicate_identifier =
810
`cfg` predicate key must be an identifier
911
@@ -150,6 +152,9 @@ attr_parsing_link_requires_name =
150152
`#[link]` attribute requires a `name = "string"` argument
151153
.label = missing `name` argument
152154
155+
attr_parsing_malformed_cfg_attr = malformed `cfg_attr` attribute input
156+
.suggestion = missing condition and attribute
157+
.note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
153158
attr_parsing_meta_bad_delim = wrong meta list delimiters
154159
attr_parsing_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
155160
@@ -264,13 +269,3 @@ attr_parsing_unused_multiple =
264269
265270
attr_parsing_whole_archive_needs_static =
266271
linking modifier `whole-archive` is only compatible with `static` linking kind
267-
268-
attr_parsing_limit_invalid =
269-
`limit` must be a non-negative integer
270-
.label = {$error_str}
271-
272-
attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
273-
274-
attr_parsing_malformed_cfg_attr = malformed `cfg_attr` attribute input
275-
.suggestion = missing condition and attribute
276-
.note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_ast::token::Delimiter;
22
use rustc_ast::tokenstream::DelimSpan;
3-
use rustc_ast::{AttrItem, Attribute, LitKind, MetaItemInner, NodeId, ast, token};
3+
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, NodeId, ast, token};
44
use rustc_errors::PResult;
55
use rustc_feature::{AttributeTemplate, Features, template};
66
use rustc_hir::RustcVersion;
@@ -19,7 +19,8 @@ use crate::context::{AcceptContext, ShouldEmit, Stage};
1919
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
2020
use crate::session_diagnostics::{CfgAttrBadDelim, MalformedCfgAttr, MetaBadDelimSugg};
2121
use crate::{
22-
CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg,
22+
AttributeParser, CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics,
23+
try_gate_cfg,
2324
};
2425

2526
pub const CFG_TEMPLATE: AttributeTemplate = template!(
@@ -309,8 +310,9 @@ impl EvalConfigResult {
309310

310311
pub fn parse_cfg_attr(
311312
cfg_attr: &Attribute,
312-
psess: &ParseSess,
313-
) -> Option<(MetaItemInner, Vec<(AttrItem, Span)>)> {
313+
sess: &Session,
314+
features: Option<&Features>,
315+
) -> Option<(CfgEntry, Vec<(AttrItem, Span)>)> {
314316
const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
315317
const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
316318
<https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>";
@@ -319,9 +321,9 @@ pub fn parse_cfg_attr(
319321
ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens })
320322
if !tokens.is_empty() =>
321323
{
322-
check_cfg_attr_bad_delim(psess, dspan, delim);
323-
match parse_in(psess, tokens.clone(), "`cfg_attr` input", |p| {
324-
parse_cfg_attr_internal(p)
324+
check_cfg_attr_bad_delim(&sess.psess, dspan, delim);
325+
match parse_in(&sess.psess, tokens.clone(), "`cfg_attr` input", |p| {
326+
parse_cfg_attr_internal(p, sess, features)
325327
}) {
326328
Ok(r) => return Some(r),
327329
Err(e) => {
@@ -332,8 +334,7 @@ pub fn parse_cfg_attr(
332334
}
333335
}
334336
_ => {
335-
psess
336-
.dcx()
337+
sess.dcx()
337338
.emit_err(MalformedCfgAttr { span: cfg_attr.span, sugg: CFG_ATTR_GRAMMAR_HELP });
338339
}
339340
}
@@ -353,8 +354,33 @@ fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter
353354
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
354355
fn parse_cfg_attr_internal<'a>(
355356
parser: &mut Parser<'a>,
356-
) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> {
357-
let cfg_predicate = parser.parse_meta_item_inner()?;
357+
sess: &'a Session,
358+
features: Option<&Features>,
359+
) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> {
360+
// Parse cfg predicate
361+
let pred_start = parser.token.span;
362+
let meta = MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints)?;
363+
let pred_span = pred_start.with_hi(parser.token.span.hi());
364+
365+
let cfg_predicate = AttributeParser::parse_single_sub(
366+
sess,
367+
pred_span,
368+
pred_span,
369+
CRATE_NODE_ID,
370+
features,
371+
ShouldEmit::ErrorsAndLints,
372+
&meta,
373+
parse_cfg_entry,
374+
&CFG_TEMPLATE,
375+
)
376+
.ok_or_else(|| {
377+
let mut diag = sess.dcx().struct_err(
378+
"cfg_entry parsing failing with `ShouldEmit::ErrorsAndLints` should emit a error.",
379+
);
380+
diag.downgrade_to_delayed_bug();
381+
diag
382+
})?;
383+
358384
parser.expect(exp!(Comma))?;
359385

360386
// Presumably, the majority of the time there will only be one attr.

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use rustc_ast as ast;
4-
use rustc_ast::NodeId;
4+
use rustc_ast::{AttrStyle, NodeId};
55
use rustc_errors::DiagCtxtHandle;
66
use rustc_feature::{AttributeTemplate, Features};
77
use rustc_hir::attrs::AttributeKind;
@@ -152,6 +152,41 @@ impl<'sess> AttributeParser<'sess, Early> {
152152
};
153153
parse_fn(&mut cx, args)
154154
}
155+
156+
pub fn parse_single_sub<T, I>(
157+
sess: &'sess Session,
158+
attr_span: Span,
159+
target_span: Span,
160+
target_node_id: NodeId,
161+
features: Option<&'sess Features>,
162+
emit_errors: ShouldEmit,
163+
args: &I,
164+
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> Option<T>,
165+
template: &AttributeTemplate,
166+
) -> Option<T> {
167+
let mut parser = Self {
168+
features,
169+
tools: Vec::new(),
170+
parse_only: None,
171+
sess,
172+
stage: Early { emit_errors },
173+
};
174+
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
175+
shared: SharedContext {
176+
cx: &mut parser,
177+
target_span,
178+
target_id: target_node_id,
179+
emit_lint: &mut |lint| {
180+
crate::lints::emit_attribute_lint(&lint, sess);
181+
},
182+
},
183+
attr_span,
184+
attr_style: AttrStyle::Inner,
185+
template,
186+
attr_path: AttrPath { segments: Box::new([]), span: attr_span },
187+
};
188+
parse_fn(&mut cx, args)
189+
}
155190
}
156191

157192
impl<'sess, S: Stage> AttributeParser<'sess, S> {

compiler/rustc_attr_parsing/src/parser.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::fmt::{Debug, Display};
88

99
use rustc_ast::token::{self, Delimiter, MetaVarKind};
1010
use rustc_ast::tokenstream::TokenStream;
11-
use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path};
11+
use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path};
1212
use rustc_ast_pretty::pprust;
1313
use rustc_errors::{Diag, PResult};
1414
use rustc_hir::{self as hir, AttrPath};
@@ -124,7 +124,11 @@ impl<'a> ArgParser<'a> {
124124
return None;
125125
}
126126

127-
Self::List(MetaItemListParser::new(args, psess, should_emit)?)
127+
Self::List(
128+
MetaItemListParser::new(&args.tokens, args.dspan.entire(), psess, should_emit)
129+
.map_err(|e| should_emit.emit_err(e))
130+
.ok()?,
131+
)
128132
}
129133
AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser {
130134
eq_span: *eq_span,
@@ -186,7 +190,15 @@ pub enum MetaItemOrLitParser<'a> {
186190
Err(Span, ErrorGuaranteed),
187191
}
188192

189-
impl<'a> MetaItemOrLitParser<'a> {
193+
impl<'sess> MetaItemOrLitParser<'sess> {
194+
pub fn parse_single(
195+
parser: &mut Parser<'sess>,
196+
should_emit: ShouldEmit,
197+
) -> PResult<'sess, MetaItemOrLitParser<'static>> {
198+
let mut this = MetaItemListParserContext { parser, should_emit };
199+
this.parse_meta_item_inner()
200+
}
201+
190202
pub fn span(&self) -> Span {
191203
match self {
192204
MetaItemOrLitParser::MetaItemParser(generic_meta_item_parser) => {
@@ -204,7 +216,7 @@ impl<'a> MetaItemOrLitParser<'a> {
204216
}
205217
}
206218

207-
pub fn meta_item(&self) -> Option<&MetaItemParser<'a>> {
219+
pub fn meta_item(&self) -> Option<&MetaItemParser<'sess>> {
208220
match self {
209221
MetaItemOrLitParser::MetaItemParser(parser) => Some(parser),
210222
_ => None,
@@ -542,23 +554,13 @@ pub struct MetaItemListParser<'a> {
542554
}
543555

544556
impl<'a> MetaItemListParser<'a> {
545-
fn new<'sess>(
546-
delim: &'a DelimArgs,
557+
pub(crate) fn new<'sess>(
558+
tokens: &'a TokenStream,
559+
span: Span,
547560
psess: &'sess ParseSess,
548561
should_emit: ShouldEmit,
549-
) -> Option<Self> {
550-
match MetaItemListParserContext::parse(
551-
delim.tokens.clone(),
552-
psess,
553-
delim.dspan.entire(),
554-
should_emit,
555-
) {
556-
Ok(s) => Some(s),
557-
Err(e) => {
558-
should_emit.emit_err(e);
559-
None
560-
}
561-
}
562+
) -> Result<Self, Diag<'sess>> {
563+
MetaItemListParserContext::parse(tokens.clone(), psess, span, should_emit)
562564
}
563565

564566
/// Lets you pick and choose as what you want to parse each element in the list

compiler/rustc_expand/src/config.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ impl<'a> StripUnconfigured<'a> {
303303
let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace);
304304

305305
let Some((cfg_predicate, expanded_attrs)) =
306-
rustc_attr_parsing::parse_cfg_attr(cfg_attr, &self.sess.psess)
306+
rustc_attr_parsing::parse_cfg_attr(cfg_attr, &self.sess, self.features)
307307
else {
308308
return vec![trace_attr];
309309
};
@@ -318,7 +318,15 @@ impl<'a> StripUnconfigured<'a> {
318318
);
319319
}
320320

321-
if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) {
321+
if !attr::eval_config_entry(
322+
self.sess,
323+
&cfg_predicate,
324+
ast::CRATE_NODE_ID,
325+
self.features,
326+
ShouldEmit::ErrorsAndLints,
327+
)
328+
.as_bool()
329+
{
322330
return vec![trace_attr];
323331
}
324332

0 commit comments

Comments
 (0)