Skip to content

Commit cfe1942

Browse files
authored
Rollup merge of #143245 - tgross35:metavariable-expr-organization, r=petrochenkov
mbe: Add tests and restructure metavariable expressions Add tests that show better diagnostics, and factor `concat` handling to a separate function. Each commit message has further details. This performs the nonfunctional perparation for further changes such as #142950 and #142975 .
2 parents e2ea213 + a1a0669 commit cfe1942

33 files changed

+739
-668
lines changed

compiler/rustc_expand/messages.ftl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,6 @@ expand_malformed_feature_attribute =
109109
110110
expand_meta_var_dif_seq_matchers = {$msg}
111111
112-
expand_meta_var_expr_unrecognized_var =
113-
variable `{$key}` is not recognized in meta-variable expression
114-
115112
expand_missing_fragment_specifier = missing fragment specifier
116113
.note = fragment specifiers must be provided
117114
.suggestion_add_fragspec = try adding a specifier here
@@ -136,6 +133,9 @@ expand_module_multiple_candidates =
136133
expand_must_repeat_once =
137134
this must repeat at least once
138135
136+
expand_mve_unrecognized_var =
137+
variable `{$key}` is not recognized in meta-variable expression
138+
139139
expand_non_inline_modules_in_proc_macro_input_are_unstable =
140140
non-inline modules in proc macro input are unstable
141141

compiler/rustc_expand/src/errors.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,6 @@ pub(crate) struct CountRepetitionMisplaced {
2727
pub span: Span,
2828
}
2929

30-
#[derive(Diagnostic)]
31-
#[diag(expand_meta_var_expr_unrecognized_var)]
32-
pub(crate) struct MetaVarExprUnrecognizedVar {
33-
#[primary_span]
34-
pub span: Span,
35-
pub key: MacroRulesNormalizedIdent,
36-
}
37-
3830
#[derive(Diagnostic)]
3931
#[diag(expand_var_still_repeating)]
4032
pub(crate) struct VarStillRepeating {
@@ -499,3 +491,16 @@ pub(crate) struct ProcMacroBackCompat {
499491
pub crate_name: String,
500492
pub fixed_version: String,
501493
}
494+
495+
pub(crate) use metavar_exprs::*;
496+
mod metavar_exprs {
497+
use super::*;
498+
499+
#[derive(Diagnostic)]
500+
#[diag(expand_mve_unrecognized_var)]
501+
pub(crate) struct MveUnrecognizedVar {
502+
#[primary_span]
503+
pub span: Span,
504+
pub key: MacroRulesNormalizedIdent,
505+
}
506+
}

compiler/rustc_expand/src/mbe/metavar_expr.rs

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -47,46 +47,7 @@ impl MetaVarExpr {
4747
check_trailing_token(&mut iter, psess)?;
4848
let mut iter = args.iter();
4949
let rslt = match ident.as_str() {
50-
"concat" => {
51-
let mut result = Vec::new();
52-
loop {
53-
let is_var = try_eat_dollar(&mut iter);
54-
let token = parse_token(&mut iter, psess, outer_span)?;
55-
let element = if is_var {
56-
MetaVarExprConcatElem::Var(parse_ident_from_token(psess, token)?)
57-
} else if let TokenKind::Literal(Lit {
58-
kind: token::LitKind::Str,
59-
symbol,
60-
suffix: None,
61-
}) = token.kind
62-
{
63-
MetaVarExprConcatElem::Literal(symbol)
64-
} else {
65-
match parse_ident_from_token(psess, token) {
66-
Err(err) => {
67-
err.cancel();
68-
return Err(psess
69-
.dcx()
70-
.struct_span_err(token.span, UNSUPPORTED_CONCAT_ELEM_ERR));
71-
}
72-
Ok(elem) => MetaVarExprConcatElem::Ident(elem),
73-
}
74-
};
75-
result.push(element);
76-
if iter.peek().is_none() {
77-
break;
78-
}
79-
if !try_eat_comma(&mut iter) {
80-
return Err(psess.dcx().struct_span_err(outer_span, "expected comma"));
81-
}
82-
}
83-
if result.len() < 2 {
84-
return Err(psess
85-
.dcx()
86-
.struct_span_err(ident.span, "`concat` must have at least two elements"));
87-
}
88-
MetaVarExpr::Concat(result.into())
89-
}
50+
"concat" => parse_concat(&mut iter, psess, outer_span, ident.span)?,
9051
"count" => parse_count(&mut iter, psess, ident.span)?,
9152
"ignore" => {
9253
eat_dollar(&mut iter, psess, ident.span)?;
@@ -126,6 +87,22 @@ impl MetaVarExpr {
12687
}
12788
}
12889

90+
// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
91+
fn check_trailing_token<'psess>(
92+
iter: &mut TokenStreamIter<'_>,
93+
psess: &'psess ParseSess,
94+
) -> PResult<'psess, ()> {
95+
if let Some(tt) = iter.next() {
96+
let mut diag = psess
97+
.dcx()
98+
.struct_span_err(tt.span(), format!("unexpected token: {}", pprust::tt_to_string(tt)));
99+
diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens");
100+
Err(diag)
101+
} else {
102+
Ok(())
103+
}
104+
}
105+
129106
/// Indicates what is placed in a `concat` parameter. For example, literals
130107
/// (`${concat("foo", "bar")}`) or adhoc identifiers (`${concat(foo, bar)}`).
131108
#[derive(Debug, Decodable, Encodable, PartialEq)]
@@ -140,20 +117,48 @@ pub(crate) enum MetaVarExprConcatElem {
140117
Var(Ident),
141118
}
142119

143-
// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
144-
fn check_trailing_token<'psess>(
120+
/// Parse a meta-variable `concat` expression: `concat($metavar, ident, ...)`.
121+
fn parse_concat<'psess>(
145122
iter: &mut TokenStreamIter<'_>,
146123
psess: &'psess ParseSess,
147-
) -> PResult<'psess, ()> {
148-
if let Some(tt) = iter.next() {
149-
let mut diag = psess
124+
outer_span: Span,
125+
expr_ident_span: Span,
126+
) -> PResult<'psess, MetaVarExpr> {
127+
let mut result = Vec::new();
128+
loop {
129+
let is_var = try_eat_dollar(iter);
130+
let token = parse_token(iter, psess, outer_span)?;
131+
let element = if is_var {
132+
MetaVarExprConcatElem::Var(parse_ident_from_token(psess, token)?)
133+
} else if let TokenKind::Literal(Lit { kind: token::LitKind::Str, symbol, suffix: None }) =
134+
token.kind
135+
{
136+
MetaVarExprConcatElem::Literal(symbol)
137+
} else {
138+
match parse_ident_from_token(psess, token) {
139+
Err(err) => {
140+
err.cancel();
141+
return Err(psess
142+
.dcx()
143+
.struct_span_err(token.span, UNSUPPORTED_CONCAT_ELEM_ERR));
144+
}
145+
Ok(elem) => MetaVarExprConcatElem::Ident(elem),
146+
}
147+
};
148+
result.push(element);
149+
if iter.peek().is_none() {
150+
break;
151+
}
152+
if !try_eat_comma(iter) {
153+
return Err(psess.dcx().struct_span_err(outer_span, "expected comma"));
154+
}
155+
}
156+
if result.len() < 2 {
157+
return Err(psess
150158
.dcx()
151-
.struct_span_err(tt.span(), format!("unexpected token: {}", pprust::tt_to_string(tt)));
152-
diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens");
153-
Err(diag)
154-
} else {
155-
Ok(())
159+
.struct_span_err(expr_ident_span, "`concat` must have at least two elements"));
156160
}
161+
Ok(MetaVarExpr::Concat(result.into()))
157162
}
158163

159164
/// Parse a meta-variable `count` expression: `count(ident[, depth])`

compiler/rustc_expand/src/mbe/transcribe.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_span::{
1717
use smallvec::{SmallVec, smallvec};
1818

1919
use crate::errors::{
20-
CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce,
20+
CountRepetitionMisplaced, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar,
2121
NoSyntaxVarsExprRepeat, VarStillRepeating,
2222
};
2323
use crate::mbe::macro_parser::NamedMatch;
@@ -879,7 +879,7 @@ where
879879
{
880880
let span = ident.span;
881881
let key = MacroRulesNormalizedIdent::new(ident);
882-
interp.get(&key).ok_or_else(|| dcx.create_err(MetaVarExprUnrecognizedVar { span, key }))
882+
interp.get(&key).ok_or_else(|| dcx.create_err(MveUnrecognizedVar { span, key }))
883883
}
884884

885885
/// Used by meta-variable expressions when an user input is out of the actual declared bounds. For

src/tools/tidy/src/issues.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2846,7 +2846,6 @@ ui/macros/issue-98466.rs
28462846
ui/macros/issue-99261.rs
28472847
ui/macros/issue-99265.rs
28482848
ui/macros/issue-99907.rs
2849-
ui/macros/rfc-3086-metavar-expr/issue-111904.rs
28502849
ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs
28512850
ui/malformed/issue-69341-malformed-derive-inert.rs
28522851
ui/marker_trait_attr/issue-61651-type-mismatch.rs

tests/ui/macros/macro-metavar-expr-concat/hygiene.stderr renamed to tests/ui/macros/metavar-expressions/concat-hygiene.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0425]: cannot find value `abcdef` in this scope
2-
--> $DIR/hygiene.rs:5:10
2+
--> $DIR/concat-hygiene.rs:5:10
33
|
44
LL | ${concat($lhs, $rhs)}
55
| ^^^^^^^^^^^^^^^^^^^^ not found in this scope

tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr renamed to tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,87 @@
11
error: expected identifier or string literal
2-
--> $DIR/raw-identifiers.rs:28:22
2+
--> $DIR/concat-raw-identifiers.rs:28:22
33
|
44
LL | let ${concat(r#abc, abc)}: () = ();
55
| ^^^^^
66

77
error: expected identifier or string literal
8-
--> $DIR/raw-identifiers.rs:32:27
8+
--> $DIR/concat-raw-identifiers.rs:32:27
99
|
1010
LL | let ${concat(abc, r#abc)}: () = ();
1111
| ^^^^^
1212

1313
error: expected identifier or string literal
14-
--> $DIR/raw-identifiers.rs:35:22
14+
--> $DIR/concat-raw-identifiers.rs:35:22
1515
|
1616
LL | let ${concat(r#abc, r#abc)}: () = ();
1717
| ^^^^^
1818

1919
error: `${concat(..)}` currently does not support raw identifiers
20-
--> $DIR/raw-identifiers.rs:5:28
20+
--> $DIR/concat-raw-identifiers.rs:5:28
2121
|
2222
LL | let ${concat(abc, $rhs)}: () = ();
2323
| ^^^
2424

2525
error: `${concat(..)}` currently does not support raw identifiers
26-
--> $DIR/raw-identifiers.rs:12:23
26+
--> $DIR/concat-raw-identifiers.rs:12:23
2727
|
2828
LL | let ${concat($lhs, abc)}: () = ();
2929
| ^^^
3030

3131
error: `${concat(..)}` currently does not support raw identifiers
32-
--> $DIR/raw-identifiers.rs:19:23
32+
--> $DIR/concat-raw-identifiers.rs:19:23
3333
|
3434
LL | let ${concat($lhs, $rhs)}: () = ();
3535
| ^^^
3636

3737
error: `${concat(..)}` currently does not support raw identifiers
38-
--> $DIR/raw-identifiers.rs:19:29
38+
--> $DIR/concat-raw-identifiers.rs:19:29
3939
|
4040
LL | let ${concat($lhs, $rhs)}: () = ();
4141
| ^^^
4242

4343
error: `${concat(..)}` currently does not support raw identifiers
44-
--> $DIR/raw-identifiers.rs:19:23
44+
--> $DIR/concat-raw-identifiers.rs:19:23
4545
|
4646
LL | let ${concat($lhs, $rhs)}: () = ();
4747
| ^^^
4848
|
4949
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
5050

5151
error: `${concat(..)}` currently does not support raw identifiers
52-
--> $DIR/raw-identifiers.rs:42:28
52+
--> $DIR/concat-raw-identifiers.rs:42:28
5353
|
5454
LL | let ${concat(abc, $rhs)}: () = ();
5555
| ^^^
5656

5757
error: `${concat(..)}` currently does not support raw identifiers
58-
--> $DIR/raw-identifiers.rs:49:23
58+
--> $DIR/concat-raw-identifiers.rs:49:23
5959
|
6060
LL | let ${concat($lhs, abc)}: () = ();
6161
| ^^^
6262

6363
error: `${concat(..)}` currently does not support raw identifiers
64-
--> $DIR/raw-identifiers.rs:56:23
64+
--> $DIR/concat-raw-identifiers.rs:56:23
6565
|
6666
LL | let ${concat($lhs, $rhs)}: () = ();
6767
| ^^^
6868

6969
error: `${concat(..)}` currently does not support raw identifiers
70-
--> $DIR/raw-identifiers.rs:56:29
70+
--> $DIR/concat-raw-identifiers.rs:56:29
7171
|
7272
LL | let ${concat($lhs, $rhs)}: () = ();
7373
| ^^^
7474

7575
error: `${concat(..)}` currently does not support raw identifiers
76-
--> $DIR/raw-identifiers.rs:56:23
76+
--> $DIR/concat-raw-identifiers.rs:56:23
7777
|
7878
LL | let ${concat($lhs, $rhs)}: () = ();
7979
| ^^^
8080
|
8181
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
8282

8383
error: expected pattern, found `$`
84-
--> $DIR/raw-identifiers.rs:28:13
84+
--> $DIR/concat-raw-identifiers.rs:28:13
8585
|
8686
LL | let ${concat(r#abc, abc)}: () = ();
8787
| ^ expected pattern

tests/ui/macros/macro-metavar-expr-concat/repetitions.stderr renamed to tests/ui/macros/metavar-expressions/concat-repetitions.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
error: invalid syntax
2-
--> $DIR/repetitions.rs:14:20
2+
--> $DIR/concat-repetitions.rs:14:20
33
|
44
LL | const ${concat($a, Z)}: i32 = 3;
55
| ^^^^^^^^^^^^^^^
66

77
error: invalid syntax
8-
--> $DIR/repetitions.rs:22:17
8+
--> $DIR/concat-repetitions.rs:22:17
99
|
1010
LL | read::<${concat($t, $en)}>()
1111
| ^^^^^^^^^^^^^^^^^
1212

1313
error: invalid syntax
14-
--> $DIR/repetitions.rs:22:17
14+
--> $DIR/concat-repetitions.rs:22:17
1515
|
1616
LL | read::<${concat($t, $en)}>()
1717
| ^^^^^^^^^^^^^^^^^
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Our diagnostics should be able to point to a specific input that caused an invalid
2+
// identifier.
3+
4+
#![feature(macro_metavar_expr_concat)]
5+
6+
// See what we can do without expanding anything
7+
macro_rules! pre_expansion {
8+
($a:ident) => {
9+
${concat("hi", " bye ")};
10+
${concat("hi", "-", "bye")};
11+
${concat($a, "-")};
12+
}
13+
}
14+
15+
macro_rules! post_expansion {
16+
($a:literal) => {
17+
const _: () = ${concat("hi", $a, "bye")};
18+
//~^ ERROR is not generating a valid identifier
19+
}
20+
}
21+
22+
post_expansion!("!");
23+
24+
macro_rules! post_expansion_many {
25+
($a:ident, $b:ident, $c:ident, $d:literal, $e:ident) => {
26+
const _: () = ${concat($a, $b, $c, $d, $e)};
27+
//~^ ERROR is not generating a valid identifier
28+
}
29+
}
30+
31+
post_expansion_many!(a, b, c, ".d", e);
32+
33+
fn main() {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: `${concat(..)}` is not generating a valid identifier
2+
--> $DIR/concat-trace-errors.rs:17:24
3+
|
4+
LL | const _: () = ${concat("hi", $a, "bye")};
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
...
7+
LL | post_expansion!("!");
8+
| -------------------- in this macro invocation
9+
|
10+
= note: this error originates in the macro `post_expansion` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
12+
error: `${concat(..)}` is not generating a valid identifier
13+
--> $DIR/concat-trace-errors.rs:26:24
14+
|
15+
LL | const _: () = ${concat($a, $b, $c, $d, $e)};
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
...
18+
LL | post_expansion_many!(a, b, c, ".d", e);
19+
| -------------------------------------- in this macro invocation
20+
|
21+
= note: this error originates in the macro `post_expansion_many` (in Nightly builds, run with -Z macro-backtrace for more info)
22+
23+
error: aborting due to 2 previous errors
24+

0 commit comments

Comments
 (0)