Skip to content

Commit e0c190f

Browse files
Move parse_cfg_attr to rustc_attr_parsing
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
1 parent 52cc311 commit e0c190f

File tree

9 files changed

+106
-105
lines changed

9 files changed

+106
-105
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,13 @@ attr_parsing_unused_multiple =
264264
265265
attr_parsing_whole_archive_needs_static =
266266
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: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
1-
use rustc_ast::{LitKind, NodeId};
1+
use rustc_ast::token::Delimiter;
2+
use rustc_ast::tokenstream::DelimSpan;
3+
use rustc_ast::{AttrItem, Attribute, LitKind, MetaItemInner, NodeId, ast, token};
4+
use rustc_errors::PResult;
25
use rustc_feature::{AttributeTemplate, Features, template};
36
use rustc_hir::RustcVersion;
47
use rustc_hir::attrs::CfgEntry;
8+
use rustc_parse::parser::{ForceCollect, Parser};
9+
use rustc_parse::{exp, parse_in};
510
use rustc_session::Session;
611
use rustc_session::config::ExpectedValues;
712
use rustc_session::lint::BuiltinLintDiag;
813
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
9-
use rustc_session::parse::feature_err;
14+
use rustc_session::parse::{ParseSess, feature_err};
1015
use rustc_span::{Span, Symbol, sym};
1116
use thin_vec::ThinVec;
1217

1318
use crate::context::{AcceptContext, ShouldEmit, Stage};
1419
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
20+
use crate::session_diagnostics::{CfgAttrBadDelim, MalformedCfgAttr, MetaBadDelimSugg};
1521
use crate::{
1622
CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg,
1723
};
@@ -301,3 +307,66 @@ impl EvalConfigResult {
301307
}
302308
}
303309

310+
pub fn parse_cfg_attr(
311+
cfg_attr: &Attribute,
312+
psess: &ParseSess,
313+
) -> Option<(MetaItemInner, Vec<(AttrItem, Span)>)> {
314+
const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
315+
const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
316+
<https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>";
317+
318+
match cfg_attr.get_normal_item().args {
319+
ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens })
320+
if !tokens.is_empty() =>
321+
{
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)
325+
}) {
326+
Ok(r) => return Some(r),
327+
Err(e) => {
328+
e.with_help(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`"))
329+
.with_note(CFG_ATTR_NOTE_REF)
330+
.emit();
331+
}
332+
}
333+
}
334+
_ => {
335+
psess
336+
.dcx()
337+
.emit_err(MalformedCfgAttr { span: cfg_attr.span, sugg: CFG_ATTR_GRAMMAR_HELP });
338+
}
339+
}
340+
None
341+
}
342+
343+
fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
344+
if let Delimiter::Parenthesis = delim {
345+
return;
346+
}
347+
psess.dcx().emit_err(CfgAttrBadDelim {
348+
span: span.entire(),
349+
sugg: MetaBadDelimSugg { open: span.open, close: span.close },
350+
});
351+
}
352+
353+
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
354+
fn parse_cfg_attr_internal<'a>(
355+
parser: &mut Parser<'a>,
356+
) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> {
357+
let cfg_predicate = parser.parse_meta_item_inner()?;
358+
parser.expect(exp!(Comma))?;
359+
360+
// Presumably, the majority of the time there will only be one attr.
361+
let mut expanded_attrs = Vec::with_capacity(1);
362+
while parser.token != token::Eof {
363+
let lo = parser.token.span;
364+
let item = parser.parse_attr_item(ForceCollect::Yes)?;
365+
expanded_attrs.push((item, lo.to(parser.prev_token.span)));
366+
if !parser.eat(exp!(Comma)) {
367+
break;
368+
}
369+
}
370+
371+
Ok((cfg_predicate, expanded_attrs))
372+
}

compiler/rustc_attr_parsing/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ mod session_diagnostics;
105105
mod target_checking;
106106
pub mod validate_attr;
107107

108-
pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg};
108+
pub use attributes::cfg::{
109+
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr,
110+
};
109111
pub use attributes::cfg_old::*;
110112
pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};
111113
pub use context::{Early, Late, OmitDoc, ShouldEmit};

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,3 +971,22 @@ pub(crate) struct LimitInvalid<'a> {
971971
pub value_span: Span,
972972
pub error_str: &'a str,
973973
}
974+
975+
#[derive(Diagnostic)]
976+
#[diag(attr_parsing_cfg_attr_bad_delim)]
977+
pub(crate) struct CfgAttrBadDelim {
978+
#[primary_span]
979+
pub span: Span,
980+
#[subdiagnostic]
981+
pub sugg: MetaBadDelimSugg,
982+
}
983+
984+
#[derive(Diagnostic)]
985+
#[diag(attr_parsing_malformed_cfg_attr)]
986+
#[note]
987+
pub(crate) struct MalformedCfgAttr {
988+
#[primary_span]
989+
#[suggestion(style = "verbose", code = "{sugg}")]
990+
pub span: Span,
991+
pub sugg: &'static str,
992+
}

compiler/rustc_expand/src/config.rs

Lines changed: 1 addition & 1 deletion
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_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
306+
rustc_attr_parsing::parse_cfg_attr(cfg_attr, &self.sess.psess)
307307
else {
308308
return vec![trace_attr];
309309
};

compiler/rustc_parse/messages.ftl

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ parse_cannot_be_raw_lifetime = `{$ident}` cannot be a raw lifetime
122122
parse_catch_after_try = keyword `catch` cannot follow a `try` block
123123
.help = try using `match` on the result of the `try` block instead
124124
125-
parse_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
126125
parse_colon_as_semi = statements are terminated with a semicolon
127126
.suggestion = use a semicolon instead
128127
@@ -573,10 +572,6 @@ parse_macro_rules_missing_bang = expected `!` after `macro_rules`
573572
parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}`
574573
.suggestion = try exporting the macro
575574
576-
parse_malformed_cfg_attr = malformed `cfg_attr` attribute input
577-
.suggestion = missing condition and attribute
578-
.note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
579-
580575
parse_malformed_loop_label = malformed loop label
581576
.suggestion = use the correct loop label format
582577
@@ -610,8 +605,6 @@ parse_maybe_report_ambiguous_plus =
610605
ambiguous `+` in a type
611606
.suggestion = use parentheses to disambiguate
612607
613-
parse_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
614-
615608
parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}`
616609
.label_unmatched = mismatched closing delimiter
617610
.label_opening_candidate = closing delimiter possibly meant for this

compiler/rustc_parse/src/errors.rs

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3351,34 +3351,6 @@ pub(crate) struct KwBadCase<'a> {
33513351
pub kw: &'a str,
33523352
}
33533353

3354-
#[derive(Diagnostic)]
3355-
#[diag(parse_cfg_attr_bad_delim)]
3356-
pub(crate) struct CfgAttrBadDelim {
3357-
#[primary_span]
3358-
pub span: Span,
3359-
#[subdiagnostic]
3360-
pub sugg: MetaBadDelimSugg,
3361-
}
3362-
3363-
#[derive(Subdiagnostic)]
3364-
#[multipart_suggestion(parse_meta_bad_delim_suggestion, applicability = "machine-applicable")]
3365-
pub(crate) struct MetaBadDelimSugg {
3366-
#[suggestion_part(code = "(")]
3367-
pub open: Span,
3368-
#[suggestion_part(code = ")")]
3369-
pub close: Span,
3370-
}
3371-
3372-
#[derive(Diagnostic)]
3373-
#[diag(parse_malformed_cfg_attr)]
3374-
#[note]
3375-
pub(crate) struct MalformedCfgAttr {
3376-
#[primary_span]
3377-
#[suggestion(style = "verbose", code = "{sugg}")]
3378-
pub span: Span,
3379-
pub sugg: &'static str,
3380-
}
3381-
33823354
#[derive(Diagnostic)]
33833355
#[diag(parse_unknown_builtin_construct)]
33843356
pub(crate) struct UnknownBuiltinConstruct {

compiler/rustc_parse/src/lib.rs

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use std::str::Utf8Error;
1818
use std::sync::Arc;
1919

2020
use rustc_ast as ast;
21-
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
22-
use rustc_ast::{AttrItem, Attribute, MetaItemInner, token};
21+
use rustc_ast::token;
22+
use rustc_ast::tokenstream::TokenStream;
2323
use rustc_ast_pretty::pprust;
2424
use rustc_errors::{Diag, EmissionGuarantee, FatalError, PResult, pluralize};
2525
use rustc_session::parse::ParseSess;
@@ -32,7 +32,6 @@ pub const MACRO_ARGUMENTS: Option<&str> = Some("macro arguments");
3232
#[macro_use]
3333
pub mod parser;
3434
use parser::Parser;
35-
use rustc_ast::token::Delimiter;
3635

3736
use crate::lexer::StripTokens;
3837

@@ -230,45 +229,3 @@ pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> Tok
230229
Some(krate.spans.inner_span),
231230
))
232231
}
233-
234-
pub fn parse_cfg_attr(
235-
cfg_attr: &Attribute,
236-
psess: &ParseSess,
237-
) -> Option<(MetaItemInner, Vec<(AttrItem, Span)>)> {
238-
const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
239-
const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
240-
<https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>";
241-
242-
match cfg_attr.get_normal_item().args {
243-
ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens })
244-
if !tokens.is_empty() =>
245-
{
246-
check_cfg_attr_bad_delim(psess, dspan, delim);
247-
match parse_in(psess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
248-
Ok(r) => return Some(r),
249-
Err(e) => {
250-
e.with_help(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`"))
251-
.with_note(CFG_ATTR_NOTE_REF)
252-
.emit();
253-
}
254-
}
255-
}
256-
_ => {
257-
psess.dcx().emit_err(errors::MalformedCfgAttr {
258-
span: cfg_attr.span,
259-
sugg: CFG_ATTR_GRAMMAR_HELP,
260-
});
261-
}
262-
}
263-
None
264-
}
265-
266-
fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
267-
if let Delimiter::Parenthesis = delim {
268-
return;
269-
}
270-
psess.dcx().emit_err(errors::CfgAttrBadDelim {
271-
span: span.entire(),
272-
sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close },
273-
});
274-
}

compiler/rustc_parse/src/parser/attr.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -377,27 +377,6 @@ impl<'a> Parser<'a> {
377377
Ok(lit)
378378
}
379379

380-
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
381-
pub fn parse_cfg_attr(
382-
&mut self,
383-
) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> {
384-
let cfg_predicate = self.parse_meta_item_inner()?;
385-
self.expect(exp!(Comma))?;
386-
387-
// Presumably, the majority of the time there will only be one attr.
388-
let mut expanded_attrs = Vec::with_capacity(1);
389-
while self.token != token::Eof {
390-
let lo = self.token.span;
391-
let item = self.parse_attr_item(ForceCollect::Yes)?;
392-
expanded_attrs.push((item, lo.to(self.prev_token.span)));
393-
if !self.eat(exp!(Comma)) {
394-
break;
395-
}
396-
}
397-
398-
Ok((cfg_predicate, expanded_attrs))
399-
}
400-
401380
/// Matches `COMMASEP(meta_item_inner)`.
402381
pub fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::MetaItemInner>> {
403382
// Presumably, the majority of the time there will only be one attr.

0 commit comments

Comments
 (0)