Skip to content

Commit fd26d34

Browse files
committed
[macro_metavar_expr_concat] Add support for literals
1 parent 6be96e3 commit fd26d34

File tree

5 files changed

+94
-17
lines changed

5 files changed

+94
-17
lines changed

compiler/rustc_expand/src/mbe/metavar_expr.rs

+2
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ impl MetaVarExpr {
119119
}
120120
}
121121

122+
/// Indicates what is placed in a `concat` parameter. For example, literals
123+
/// (`${concat("foo", "bar")}`) or adhoc identifiers (`${concat(foo, bar)}`).
122124
#[derive(Debug, Decodable, Encodable, PartialEq)]
123125
pub(crate) enum MetaVarExprConcatElem {
124126
/// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be

compiler/rustc_expand/src/mbe/transcribe.rs

+23-12
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
66
use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR};
77
use crate::mbe::{self, KleeneOp, MetaVarExpr};
88
use rustc_ast::mut_visit::{self, MutVisitor};
9-
use rustc_ast::token::IdentIsRaw;
10-
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
9+
use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind};
10+
use rustc_ast::token::{IdentIsRaw, Lit, LitKind};
1111
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
12+
use rustc_ast::ExprKind;
1213
use rustc_data_structures::fx::FxHashMap;
1314
use rustc_errors::{pluralize, Diag, DiagCtxtHandle, PResult};
1415
use rustc_parse::lexer::nfc_normalize;
@@ -750,7 +751,7 @@ fn transcribe_metavar_expr<'a>(
750751
Ok(())
751752
}
752753

753-
/// Extracts an identifier that can be originated from a `$var:ident` variable or from a token tree.
754+
/// Extracts an metavariable value that can be an identifier, a token tree or a literal.
754755
fn extract_ident<'a>(
755756
dcx: DiagCtxtHandle<'a>,
756757
ident: Ident,
@@ -763,19 +764,29 @@ fn extract_ident<'a>(
763764
}
764765
return Ok(nt_ident.to_string());
765766
}
766-
if let ParseNtResult::Tt(TokenTree::Token(
767-
Token { kind: TokenKind::Ident(token_ident, is_raw), .. },
768-
_,
769-
)) = pnr
770-
{
771-
if let IdentIsRaw::Yes = is_raw {
772-
return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
767+
768+
if let ParseNtResult::Tt(TokenTree::Token(Token { kind, .. }, _)) = pnr {
769+
if let TokenKind::Ident(symbol, is_raw) = kind {
770+
if let IdentIsRaw::Yes = is_raw {
771+
return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
772+
}
773+
return Ok(symbol.to_string());
773774
}
774-
return Ok(token_ident.to_string());
775+
776+
if let TokenKind::Literal(Lit { kind: LitKind::Str, symbol, suffix: None }) = kind {
777+
return Ok(symbol.to_string());
778+
}
779+
}
780+
781+
if let ParseNtResult::Nt(nt) = pnr
782+
&& let Nonterminal::NtLiteral(expr) = &**nt
783+
&& let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind
784+
{
785+
return Ok(symbol.to_string());
775786
}
776787
}
777788
Err(dcx.struct_span_err(
778789
ident.span,
779-
"`${concat(..)}` currently only accepts identifiers or meta-variables as parameters",
790+
"`${concat(..)}` currently only accepts identifiers, token trees or literals",
780791
))
781792
}

tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs

+15
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ macro_rules! unsupported_literals {
9898
}};
9999
}
100100

101+
macro_rules! bad_literal_parameter {
102+
($literal:literal) => {
103+
const ${concat(_foo, $literal)}: () = ();
104+
//~^ ERROR `${concat(..)}` is not generating a valid identifier
105+
//~| ERROR `${concat(..)}` is not generating a valid identifier
106+
//~| ERROR `${concat(..)}` is not generating a valid identifier
107+
//~| ERROR `${concat(..)}` is not generating a valid identifier
108+
}
109+
}
110+
101111
fn main() {
102112
wrong_concat_declarations!(1);
103113

@@ -113,4 +123,9 @@ fn main() {
113123
unsupported_literals!(_abc);
114124

115125
empty!();
126+
127+
bad_literal_parameter!("\u{00BD}");
128+
bad_literal_parameter!("\x41");
129+
bad_literal_parameter!("🤷");
130+
bad_literal_parameter!("d[-_-]b");
116131
}

tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr

+46-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ error: expected identifier or string literal
6464
LL | let ${concat($ident, 1)}: () = ();
6565
| ^
6666

67-
error: `${concat(..)}` currently only accepts identifiers or meta-variables as parameters
67+
error: `${concat(..)}` currently only accepts identifiers, token trees or literals
6868
--> $DIR/syntax-errors.rs:22:19
6969
|
7070
LL | ${concat($ex, aaaa)}
@@ -131,5 +131,49 @@ LL | empty!();
131131
|
132132
= note: this error originates in the macro `empty` (in Nightly builds, run with -Z macro-backtrace for more info)
133133

134-
error: aborting due to 18 previous errors
134+
error: `${concat(..)}` is not generating a valid identifier
135+
--> $DIR/syntax-errors.rs:103:16
136+
|
137+
LL | const ${concat(_foo, $literal)}: () = ();
138+
| ^^^^^^^^^^^^^^^^^^^^^^^^
139+
...
140+
LL | bad_literal_parameter!("\u{00BD}");
141+
| ---------------------------------- in this macro invocation
142+
|
143+
= note: this error originates in the macro `bad_literal_parameter` (in Nightly builds, run with -Z macro-backtrace for more info)
144+
145+
error: `${concat(..)}` is not generating a valid identifier
146+
--> $DIR/syntax-errors.rs:103:16
147+
|
148+
LL | const ${concat(_foo, $literal)}: () = ();
149+
| ^^^^^^^^^^^^^^^^^^^^^^^^
150+
...
151+
LL | bad_literal_parameter!("\x41");
152+
| ------------------------------ in this macro invocation
153+
|
154+
= note: this error originates in the macro `bad_literal_parameter` (in Nightly builds, run with -Z macro-backtrace for more info)
155+
156+
error: `${concat(..)}` is not generating a valid identifier
157+
--> $DIR/syntax-errors.rs:103:16
158+
|
159+
LL | const ${concat(_foo, $literal)}: () = ();
160+
| ^^^^^^^^^^^^^^^^^^^^^^^^
161+
...
162+
LL | bad_literal_parameter!("🤷");
163+
| ---------------------------- in this macro invocation
164+
|
165+
= note: this error originates in the macro `bad_literal_parameter` (in Nightly builds, run with -Z macro-backtrace for more info)
166+
167+
error: `${concat(..)}` is not generating a valid identifier
168+
--> $DIR/syntax-errors.rs:103:16
169+
|
170+
LL | const ${concat(_foo, $literal)}: () = ();
171+
| ^^^^^^^^^^^^^^^^^^^^^^^^
172+
...
173+
LL | bad_literal_parameter!("d[-_-]b");
174+
| --------------------------------- in this macro invocation
175+
|
176+
= note: this error originates in the macro `bad_literal_parameter` (in Nightly builds, run with -Z macro-backtrace for more info)
177+
178+
error: aborting due to 22 previous errors
135179

tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
#![feature(macro_metavar_expr_concat)]
44

55
macro_rules! turn_to_page {
6-
($ident:ident) => {
6+
($ident:ident, $literal:literal, $tt:tt) => {
77
const ${concat("Ḧ", $ident)}: i32 = 394;
8+
const ${concat("Ḧ", $literal)}: i32 = 394;
9+
const ${concat("Ḧ", $tt)}: i32 = 394;
810
};
911
}
1012

1113
fn main() {
12-
turn_to_page!(P);
13-
assert_eq!(ḦP, 394);
14+
turn_to_page!(P1, "Ṕ2",);
15+
assert_eq!(ḦṔ, 394);
16+
assert_eq!(ḦP1, 394);
17+
assert_eq!(ḦṔ2, 394);
18+
1419
}

0 commit comments

Comments
 (0)