Skip to content

Commit 1125b68

Browse files
Port cfg_select! to the new attribute parsing system
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
1 parent af73f23 commit 1125b68

File tree

4 files changed

+77
-55
lines changed

4 files changed

+77
-55
lines changed

compiler/rustc_builtin_macros/src/cfg_select.rs

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
use rustc_ast::token::Token;
22
use rustc_ast::tokenstream::TokenStream;
3-
use rustc_ast::{MetaItemInner, token};
3+
use rustc_ast::{AttrStyle, token};
44
use rustc_attr_parsing as attr;
5-
use rustc_errors::PResult;
5+
use rustc_attr_parsing::parser::MetaItemOrLitParser;
6+
use rustc_attr_parsing::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry};
67
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
8+
use rustc_feature::AttributeTemplate;
9+
use rustc_hir::AttrPath;
10+
use rustc_hir::attrs::CfgEntry;
711
use rustc_parse::exp;
812
use rustc_parse::parser::Parser;
9-
use rustc_span::{Ident, Span, sym};
13+
use rustc_span::{ErrorGuaranteed, Ident, Span, sym};
1014

1115
use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};
1216

1317
enum CfgSelectPredicate {
14-
Cfg(MetaItemInner),
18+
Cfg(CfgEntry),
1519
Wildcard(Token),
1620
}
1721

1822
#[derive(Default)]
1923
struct CfgSelectBranches {
2024
/// All the conditional branches.
21-
pub reachable: Vec<(MetaItemInner, TokenStream, Span)>,
25+
pub reachable: Vec<(CfgEntry, TokenStream, Span)>,
2226
/// The first wildcard `_ => { ... }` branch.
2327
pub wildcard: Option<(Token, TokenStream, Span)>,
2428
/// All branches after the first wildcard, including further wildcards.
@@ -29,12 +33,15 @@ struct CfgSelectBranches {
2933
/// Selects the first arm whose predicate evaluates to true.
3034
fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
3135
for (cfg, tt, arm_span) in branches.reachable {
32-
if attr::cfg_matches(
33-
&cfg,
36+
if attr::eval_config_entry(
3437
&ecx.sess,
38+
&cfg,
3539
ecx.current_expansion.lint_node_id,
3640
Some(ecx.ecfg.features),
37-
) {
41+
ShouldEmit::ErrorsAndLints,
42+
)
43+
.as_bool()
44+
{
3845
return Some((tt, arm_span));
3946
}
4047
}
@@ -47,7 +54,7 @@ pub(super) fn expand_cfg_select<'cx>(
4754
sp: Span,
4855
tts: TokenStream,
4956
) -> MacroExpanderResult<'cx> {
50-
ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) {
57+
ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts), ecx) {
5158
Ok(branches) => {
5259
if let Some((underscore, _, _)) = branches.wildcard {
5360
// Warn for every unreachable predicate. We store the fully parsed branch for rustfmt.
@@ -75,22 +82,22 @@ pub(super) fn expand_cfg_select<'cx>(
7582
DummyResult::any(sp, guar)
7683
}
7784
}
78-
Err(err) => {
79-
let guar = err.emit();
80-
DummyResult::any(sp, guar)
81-
}
85+
Err(guar) => DummyResult::any(sp, guar),
8286
})
8387
}
8488

85-
fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> {
89+
fn parse_cfg_select<'a>(
90+
p: &mut Parser<'a>,
91+
cx: &ExtCtxt<'_>,
92+
) -> Result<CfgSelectBranches, ErrorGuaranteed> {
8693
let mut branches = CfgSelectBranches::default();
8794

8895
while p.token != token::Eof {
8996
if p.eat_keyword(exp!(Underscore)) {
9097
let underscore = p.prev_token;
91-
p.expect(exp!(FatArrow))?;
98+
p.expect(exp!(FatArrow)).map_err(|e| e.emit())?;
9299

93-
let tts = p.parse_delimited_token_tree()?;
100+
let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?;
94101
let span = underscore.span.to(p.token.span);
95102

96103
match branches.wildcard {
@@ -100,17 +107,36 @@ fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> {
100107
}
101108
}
102109
} else {
103-
let meta_item = p.parse_meta_item_inner()?;
104-
p.expect(exp!(FatArrow))?;
110+
let meta = MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints)
111+
.map_err(|diag| diag.emit())?;
112+
let cfg_span = meta.span();
113+
let cfg = AttributeParser::parse_single_args(
114+
cx.sess,
115+
cfg_span,
116+
cfg_span,
117+
AttrStyle::Inner,
118+
AttrPath {
119+
segments: vec![Ident::from_str("cfg_select")].into_boxed_slice(),
120+
span: cfg_span,
121+
},
122+
ParsedDescription::Macro,
123+
cfg_span,
124+
cx.current_expansion.lint_node_id,
125+
Some(cx.ecfg.features),
126+
ShouldEmit::ErrorsAndLints,
127+
&meta,
128+
parse_cfg_entry,
129+
&AttributeTemplate::default(),
130+
)?;
105131

106-
let tts = p.parse_delimited_token_tree()?;
107-
let span = meta_item.span().to(p.token.span);
132+
p.expect(exp!(FatArrow)).map_err(|e| e.emit())?;
133+
134+
let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?;
135+
let span = cfg_span.to(p.token.span);
108136

109137
match branches.wildcard {
110-
None => branches.reachable.push((meta_item, tts, span)),
111-
Some(_) => {
112-
branches.unreachable.push((CfgSelectPredicate::Cfg(meta_item), tts, span))
113-
}
138+
None => branches.reachable.push((cfg, tts, span)),
139+
Some(_) => branches.unreachable.push((CfgSelectPredicate::Cfg(cfg), tts, span)),
114140
}
115141
}
116142
}

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,18 @@ pub enum CfgEntry {
194194
Version(Option<RustcVersion>, Span),
195195
}
196196

197+
impl CfgEntry {
198+
pub fn span(&self) -> Span {
199+
let (CfgEntry::All(_, span)
200+
| CfgEntry::Any(_, span)
201+
| CfgEntry::Not(_, span)
202+
| CfgEntry::Bool(_, span)
203+
| CfgEntry::NameValue { span, .. }
204+
| CfgEntry::Version(_, span)) = self;
205+
*span
206+
}
207+
}
208+
197209
/// Possible values for the `#[linkage]` attribute, allowing to specify the
198210
/// linkage type for a `MonoItem`.
199211
///

tests/ui/macros/cfg_select.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,25 +63,25 @@ cfg_select! {}
6363

6464
cfg_select! {
6565
=> {}
66-
//~^ ERROR expected unsuffixed literal, found `=>`
66+
//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>`
6767
}
6868

6969
cfg_select! {
7070
() => {}
71-
//~^ ERROR expected unsuffixed literal, found `(`
71+
//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `(`
7272
}
7373

74-
cfg_select! { //~ ERROR none of the predicates in this `cfg_select` evaluated to true
74+
cfg_select! {
7575
"str" => {}
76-
//~^ ERROR literal in `cfg` predicate value must be a boolean
76+
//~^ ERROR malformed `cfg_select` macro input [E0539]
7777
}
7878

7979
cfg_select! {
8080
a::b => {}
81-
//~^ ERROR `cfg` predicate key must be an identifier
81+
//~^ ERROR malformed `cfg_select` macro input [E0539]
8282
}
8383

84-
cfg_select! { //~ ERROR none of the predicates in this `cfg_select` evaluated to true
84+
cfg_select! {
8585
a() => {}
8686
//~^ ERROR invalid predicate `a` [E0537]
8787
}

tests/ui/macros/cfg_select.stderr

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,54 +21,38 @@ error: none of the predicates in this `cfg_select` evaluated to true
2121
LL | cfg_select! {}
2222
| ^^^^^^^^^^^^^^
2323

24-
error: expected unsuffixed literal, found `=>`
24+
error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>`
2525
--> $DIR/cfg_select.rs:65:5
2626
|
2727
LL | => {}
2828
| ^^
2929

30-
error: expected unsuffixed literal, found `(`
30+
error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `(`
3131
--> $DIR/cfg_select.rs:70:5
3232
|
3333
LL | () => {}
3434
| ^
3535

36-
error[E0565]: literal in `cfg` predicate value must be a boolean
36+
error[E0539]: malformed `cfg_select` macro input
3737
--> $DIR/cfg_select.rs:75:5
3838
|
3939
LL | "str" => {}
40-
| ^^^^^
41-
42-
error: none of the predicates in this `cfg_select` evaluated to true
43-
--> $DIR/cfg_select.rs:74:1
40+
| ^^^^^ expected a valid identifier here
4441
|
45-
LL | / cfg_select! {
46-
LL | | "str" => {}
47-
LL | |
48-
LL | | }
49-
| |_^
5042

51-
error: `cfg` predicate key must be an identifier
43+
error[E0539]: malformed `cfg_select` macro input
5244
--> $DIR/cfg_select.rs:80:5
5345
|
5446
LL | a::b => {}
55-
| ^^^^
47+
| ^^^^ expected a valid identifier here
48+
|
5649

5750
error[E0537]: invalid predicate `a`
5851
--> $DIR/cfg_select.rs:85:5
5952
|
6053
LL | a() => {}
6154
| ^^^
6255

63-
error: none of the predicates in this `cfg_select` evaluated to true
64-
--> $DIR/cfg_select.rs:84:1
65-
|
66-
LL | / cfg_select! {
67-
LL | | a() => {}
68-
LL | |
69-
LL | | }
70-
| |_^
71-
7256
error: expected one of `(`, `::`, `=>`, or `=`, found `+`
7357
--> $DIR/cfg_select.rs:90:7
7458
|
@@ -81,7 +65,7 @@ error: expected one of `(`, `::`, `=>`, or `=`, found `!`
8165
LL | cfg!() => {}
8266
| ^ expected one of `(`, `::`, `=>`, or `=`
8367

84-
error: aborting due to 11 previous errors; 1 warning emitted
68+
error: aborting due to 9 previous errors; 1 warning emitted
8569

86-
Some errors have detailed explanations: E0537, E0565.
70+
Some errors have detailed explanations: E0537, E0539.
8771
For more information about an error, try `rustc --explain E0537`.

0 commit comments

Comments
 (0)