Skip to content

Commit a01b4cf

Browse files
committed
Revert "Implement macro meta-variable expressions"
This reverts commit 8073a88.
1 parent 7a40b31 commit a01b4cf

File tree

16 files changed

+45
-1057
lines changed

16 files changed

+45
-1057
lines changed

compiler/rustc_ast/src/util/literal.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub enum LitError {
2323

2424
impl LitKind {
2525
/// Converts literal token into a semantic literal.
26-
pub fn from_lit_token(lit: token::Lit) -> Result<LitKind, LitError> {
26+
fn from_lit_token(lit: token::Lit) -> Result<LitKind, LitError> {
2727
let token::Lit { kind, symbol, suffix } = lit;
2828
if suffix.is_some() && !kind.may_have_suffix() {
2929
return Err(LitError::InvalidSuffix);

compiler/rustc_expand/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#![feature(crate_visibility_modifier)]
44
#![feature(decl_macro)]
55
#![feature(if_let_guard)]
6-
#![feature(let_chains)]
76
#![feature(let_else)]
87
#![feature(proc_macro_diagnostic)]
98
#![feature(proc_macro_internals)]

compiler/rustc_expand/src/mbe.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@
66
crate mod macro_check;
77
crate mod macro_parser;
88
crate mod macro_rules;
9-
crate mod metavar_expr;
109
crate mod quoted;
1110
crate mod transcribe;
1211

13-
use metavar_expr::MetaVarExpr;
1412
use rustc_ast::token::{self, NonterminalKind, Token, TokenKind};
1513
use rustc_ast::tokenstream::DelimSpan;
16-
use rustc_data_structures::sync::Lrc;
14+
1715
use rustc_span::symbol::Ident;
1816
use rustc_span::Span;
1917

18+
use rustc_data_structures::sync::Lrc;
19+
2020
/// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note
2121
/// that the delimiter itself might be `NoDelim`.
2222
#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
@@ -73,8 +73,8 @@ enum KleeneOp {
7373
ZeroOrOne,
7474
}
7575

76-
/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, `$(...)`,
77-
/// and `${...}` are "first-class" token trees. Useful for parsing macros.
76+
/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)`
77+
/// are "first-class" token trees. Useful for parsing macros.
7878
#[derive(Debug, Clone, PartialEq, Encodable, Decodable)]
7979
enum TokenTree {
8080
Token(Token),
@@ -85,8 +85,6 @@ enum TokenTree {
8585
MetaVar(Span, Ident),
8686
/// e.g., `$var:expr`. This is only used in the left hand side of MBE macros.
8787
MetaVarDecl(Span, Ident /* name to bind */, Option<NonterminalKind>),
88-
/// A meta-variable expression inside `${...}`
89-
MetaVarExpr(DelimSpan, MetaVarExpr),
9088
}
9189

9290
impl TokenTree {
@@ -141,9 +139,7 @@ impl TokenTree {
141139
TokenTree::Token(Token { span, .. })
142140
| TokenTree::MetaVar(span, _)
143141
| TokenTree::MetaVarDecl(span, _, _) => span,
144-
TokenTree::Delimited(span, _)
145-
| TokenTree::MetaVarExpr(span, _)
146-
| TokenTree::Sequence(span, _) => span.entire(),
142+
TokenTree::Delimited(span, _) | TokenTree::Sequence(span, _) => span.entire(),
147143
}
148144
}
149145

compiler/rustc_expand/src/mbe/macro_check.rs

-8
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,6 @@ fn check_binders(
278278
binders.insert(name, BinderInfo { span, ops: ops.into() });
279279
}
280280
}
281-
// `MetaVarExpr` can not appear in the LHS of a macro arm
282-
TokenTree::MetaVarExpr(..) => {}
283281
TokenTree::Delimited(_, ref del) => {
284282
for tt in &del.tts {
285283
check_binders(sess, node_id, tt, macros, binders, ops, valid);
@@ -337,12 +335,6 @@ fn check_occurrences(
337335
let name = MacroRulesNormalizedIdent::new(name);
338336
check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name);
339337
}
340-
TokenTree::MetaVarExpr(dl, ref mve) => {
341-
let Some(name) = mve.ident().map(MacroRulesNormalizedIdent::new) else {
342-
return;
343-
};
344-
check_ops_is_prefix(sess, node_id, macros, binders, ops, dl.entire(), name);
345-
}
346338
TokenTree::Delimited(_, ref del) => {
347339
check_nested_occurrences(sess, node_id, &del.tts, macros, binders, ops, valid);
348340
}

compiler/rustc_expand/src/mbe/macro_parser.rs

+4-13
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ struct MatcherPos<'root, 'tt> {
200200

201201
// This type is used a lot. Make sure it doesn't unintentionally get bigger.
202202
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
203-
rustc_data_structures::static_assert_size!(MatcherPos<'_, '_>, 240);
203+
rustc_data_structures::static_assert_size!(MatcherPos<'_, '_>, 192);
204204

205205
impl<'root, 'tt> MatcherPos<'root, 'tt> {
206206
/// Generates the top-level matcher position in which the "dot" is before the first token of
@@ -321,16 +321,10 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
321321
ms.iter().fold(0, |count, elt| {
322322
count
323323
+ match *elt {
324+
TokenTree::Sequence(_, ref seq) => seq.num_captures,
324325
TokenTree::Delimited(_, ref delim) => count_names(&delim.tts),
325326
TokenTree::MetaVar(..) => 0,
326327
TokenTree::MetaVarDecl(..) => 1,
327-
// Panicking here would abort execution because `parse_tree` makes use of this
328-
// function. In other words, RHS meta-variable expressions eventually end-up here.
329-
//
330-
// `0` is still returned to inform that no meta-variable was found. `Meta-variables
331-
// != Meta-variable expressions`
332-
TokenTree::MetaVarExpr(..) => 0,
333-
TokenTree::Sequence(_, ref seq) => seq.num_captures,
334328
TokenTree::Token(..) => 0,
335329
}
336330
})
@@ -442,8 +436,7 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
442436
}
443437
Occupied(..) => return Err((sp, format!("duplicated bind name: {}", bind_name))),
444438
},
445-
TokenTree::Token(..) => (),
446-
TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(),
439+
TokenTree::MetaVar(..) | TokenTree::Token(..) => (),
447440
}
448441

449442
Ok(())
@@ -662,9 +655,7 @@ fn parse_tt_inner<'root, 'tt>(
662655
// rules. NOTE that this is not necessarily an error unless _all_ items in
663656
// `cur_items` end up doing this. There may still be some other matchers that do
664657
// end up working out.
665-
TokenTree::Token(..) => {}
666-
667-
TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(),
658+
TokenTree::Token(..) | TokenTree::MetaVar(..) => {}
668659
}
669660
}
670661
}

compiler/rustc_expand/src/mbe/macro_rules.rs

+4-16
Original file line numberDiff line numberDiff line change
@@ -580,10 +580,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
580580
use mbe::TokenTree;
581581
for tt in tts {
582582
match *tt {
583-
TokenTree::Token(..)
584-
| TokenTree::MetaVar(..)
585-
| TokenTree::MetaVarDecl(..)
586-
| TokenTree::MetaVarExpr(..) => (),
583+
TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => (),
587584
TokenTree::Delimited(_, ref del) => {
588585
if !check_lhs_no_empty_seq(sess, &del.tts) {
589586
return false;
@@ -672,10 +669,7 @@ impl FirstSets {
672669
let mut first = TokenSet::empty();
673670
for tt in tts.iter().rev() {
674671
match *tt {
675-
TokenTree::Token(..)
676-
| TokenTree::MetaVar(..)
677-
| TokenTree::MetaVarDecl(..)
678-
| TokenTree::MetaVarExpr(..) => {
672+
TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
679673
first.replace_with(tt.clone());
680674
}
681675
TokenTree::Delimited(span, ref delimited) => {
@@ -737,10 +731,7 @@ impl FirstSets {
737731
for tt in tts.iter() {
738732
assert!(first.maybe_empty);
739733
match *tt {
740-
TokenTree::Token(..)
741-
| TokenTree::MetaVar(..)
742-
| TokenTree::MetaVarDecl(..)
743-
| TokenTree::MetaVarExpr(..) => {
734+
TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
744735
first.add_one(tt.clone());
745736
return first;
746737
}
@@ -916,10 +907,7 @@ fn check_matcher_core(
916907
// First, update `last` so that it corresponds to the set
917908
// of NT tokens that might end the sequence `... token`.
918909
match *token {
919-
TokenTree::Token(..)
920-
| TokenTree::MetaVar(..)
921-
| TokenTree::MetaVarDecl(..)
922-
| TokenTree::MetaVarExpr(..) => {
910+
TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
923911
if token_can_be_followed_by_any(token) {
924912
// don't need to track tokens that work with any,
925913
last.replace_with_irrelevant();

compiler/rustc_expand/src/mbe/quoted.rs

+29-94
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::mbe::macro_parser;
2-
use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};
2+
use crate::mbe::{Delimited, KleeneOp, KleeneToken, SequenceRepetition, TokenTree};
33

44
use rustc_ast::token::{self, Token};
55
use rustc_ast::tokenstream;
66
use rustc_ast::{NodeId, DUMMY_NODE_ID};
77
use rustc_ast_pretty::pprust;
88
use rustc_feature::Features;
9-
use rustc_session::parse::{feature_err, ParseSess};
10-
use rustc_span::symbol::{kw, sym, Ident};
9+
use rustc_session::parse::ParseSess;
10+
use rustc_span::symbol::{kw, Ident};
1111

1212
use rustc_span::edition::Edition;
1313
use rustc_span::{Span, SyntaxContext};
@@ -25,22 +25,22 @@ const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
2525
/// # Parameters
2626
///
2727
/// - `input`: a token stream to read from, the contents of which we are parsing.
28-
/// - `parsing_patterns`: `parse` can be used to parse either the "patterns" or the "body" of a
29-
/// macro. Both take roughly the same form _except_ that:
30-
/// - In a pattern, metavars are declared with their "matcher" type. For example `$var:expr` or
31-
/// `$id:ident`. In this example, `expr` and `ident` are "matchers". They are not present in the
32-
/// body of a macro rule -- just in the pattern.
33-
/// - Metavariable expressions are only valid in the "body", not the "pattern".
28+
/// - `expect_matchers`: `parse` can be used to parse either the "patterns" or the "body" of a
29+
/// macro. Both take roughly the same form _except_ that in a pattern, metavars are declared with
30+
/// their "matcher" type. For example `$var:expr` or `$id:ident`. In this example, `expr` and
31+
/// `ident` are "matchers". They are not present in the body of a macro rule -- just in the
32+
/// pattern, so we pass a parameter to indicate whether to expect them or not.
3433
/// - `sess`: the parsing session. Any errors will be emitted to this session.
3534
/// - `node_id`: the NodeId of the macro we are parsing.
3635
/// - `features`: language features so we can do feature gating.
36+
/// - `edition`: the edition of the crate defining the macro
3737
///
3838
/// # Returns
3939
///
4040
/// A collection of `self::TokenTree`. There may also be some errors emitted to `sess`.
4141
pub(super) fn parse(
4242
input: tokenstream::TokenStream,
43-
parsing_patterns: bool,
43+
expect_matchers: bool,
4444
sess: &ParseSess,
4545
node_id: NodeId,
4646
features: &Features,
@@ -55,9 +55,9 @@ pub(super) fn parse(
5555
while let Some(tree) = trees.next() {
5656
// Given the parsed tree, if there is a metavar and we are expecting matchers, actually
5757
// parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`).
58-
let tree = parse_tree(tree, &mut trees, parsing_patterns, sess, node_id, features, edition);
58+
let tree = parse_tree(tree, &mut trees, expect_matchers, sess, node_id, features, edition);
5959
match tree {
60-
TokenTree::MetaVar(start_sp, ident) if parsing_patterns => {
60+
TokenTree::MetaVar(start_sp, ident) if expect_matchers => {
6161
let span = match trees.next() {
6262
Some(tokenstream::TokenTree::Token(Token { kind: token::Colon, span })) => {
6363
match trees.next() {
@@ -118,14 +118,6 @@ pub(super) fn parse(
118118
result
119119
}
120120

121-
/// Asks for the `macro_metavar_expr` feature if it is not already declared
122-
fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess, span: Span) {
123-
if !features.macro_metavar_expr {
124-
let msg = "meta-variable expressions are unstable";
125-
feature_err(&sess, sym::macro_metavar_expr, span, msg).emit();
126-
}
127-
}
128-
129121
/// Takes a `tokenstream::TokenTree` and returns a `self::TokenTree`. Specifically, this takes a
130122
/// generic `TokenTree`, such as is used in the rest of the compiler, and returns a `TokenTree`
131123
/// for use in parsing a macro.
@@ -137,13 +129,14 @@ fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess,
137129
/// - `tree`: the tree we wish to convert.
138130
/// - `outer_trees`: an iterator over trees. We may need to read more tokens from it in order to finish
139131
/// converting `tree`
140-
/// - `parsing_patterns`: same as [parse].
132+
/// - `expect_matchers`: same as for `parse` (see above).
141133
/// - `sess`: the parsing session. Any errors will be emitted to this session.
142134
/// - `features`: language features so we can do feature gating.
135+
/// - `edition` - the edition of the crate defining the macro
143136
fn parse_tree(
144137
tree: tokenstream::TokenTree,
145138
outer_trees: &mut impl Iterator<Item = tokenstream::TokenTree>,
146-
parsing_patterns: bool,
139+
expect_matchers: bool,
147140
sess: &ParseSess,
148141
node_id: NodeId,
149142
features: &Features,
@@ -165,57 +158,24 @@ fn parse_tree(
165158
}
166159

167160
match next {
168-
// `tree` is followed by a delimited set of token trees.
169-
Some(tokenstream::TokenTree::Delimited(delim_span, delim, tts)) => {
170-
if parsing_patterns {
171-
if delim != token::Paren {
172-
span_dollar_dollar_or_metavar_in_the_lhs_err(
173-
sess,
174-
&Token { kind: token::OpenDelim(delim), span: delim_span.entire() },
175-
);
176-
}
177-
} else {
178-
match delim {
179-
token::Brace => {
180-
// The delimiter is `{`. This indicates the beginning
181-
// of a meta-variable expression (e.g. `${count(ident)}`).
182-
// Try to parse the meta-variable expression.
183-
match MetaVarExpr::parse(&tts, delim_span.entire(), sess) {
184-
Err(mut err) => {
185-
err.emit();
186-
// Returns early the same read `$` to avoid spanning
187-
// unrelated diagnostics that could be performed afterwards
188-
return TokenTree::token(token::Dollar, span);
189-
}
190-
Ok(elem) => {
191-
maybe_emit_macro_metavar_expr_feature(
192-
features,
193-
sess,
194-
delim_span.entire(),
195-
);
196-
return TokenTree::MetaVarExpr(delim_span, elem);
197-
}
198-
}
199-
}
200-
token::Paren => {}
201-
_ => {
202-
let tok = pprust::token_kind_to_string(&token::OpenDelim(delim));
203-
let msg = format!("expected `(` or `{{`, found `{}`", tok);
204-
sess.span_diagnostic.span_err(delim_span.entire(), &msg);
205-
}
206-
}
161+
// `tree` is followed by a delimited set of token trees. This indicates the beginning
162+
// of a repetition sequence in the macro (e.g. `$(pat)*`).
163+
Some(tokenstream::TokenTree::Delimited(span, delim, tts)) => {
164+
// Must have `(` not `{` or `[`
165+
if delim != token::Paren {
166+
let tok = pprust::token_kind_to_string(&token::OpenDelim(delim));
167+
let msg = format!("expected `(`, found `{}`", tok);
168+
sess.span_diagnostic.span_err(span.entire(), &msg);
207169
}
208-
// If we didn't find a metavar expression above, then we must have a
209-
// repetition sequence in the macro (e.g. `$(pat)*`). Parse the
210-
// contents of the sequence itself
211-
let sequence = parse(tts, parsing_patterns, sess, node_id, features, edition);
170+
// Parse the contents of the sequence itself
171+
let sequence = parse(tts, expect_matchers, sess, node_id, features, edition);
212172
// Get the Kleene operator and optional separator
213173
let (separator, kleene) =
214-
parse_sep_and_kleene_op(&mut trees, delim_span.entire(), sess);
174+
parse_sep_and_kleene_op(&mut trees, span.entire(), sess);
215175
// Count the number of captured "names" (i.e., named metavars)
216176
let name_captures = macro_parser::count_names(&sequence);
217177
TokenTree::Sequence(
218-
delim_span,
178+
span,
219179
Lrc::new(SequenceRepetition {
220180
tts: sequence,
221181
separator,
@@ -237,20 +197,7 @@ fn parse_tree(
237197
}
238198
}
239199

240-
// `tree` is followed by another `$`. This is an escaped `$`.
241-
Some(tokenstream::TokenTree::Token(Token { kind: token::Dollar, span })) => {
242-
if parsing_patterns {
243-
span_dollar_dollar_or_metavar_in_the_lhs_err(
244-
sess,
245-
&Token { kind: token::Dollar, span },
246-
);
247-
} else {
248-
maybe_emit_macro_metavar_expr_feature(features, sess, span);
249-
}
250-
TokenTree::token(token::Dollar, span)
251-
}
252-
253-
// `tree` is followed by some other token. This is an error.
200+
// `tree` is followed by a random token. This is an error.
254201
Some(tokenstream::TokenTree::Token(token)) => {
255202
let msg = format!(
256203
"expected identifier, found `{}`",
@@ -274,7 +221,7 @@ fn parse_tree(
274221
span,
275222
Lrc::new(Delimited {
276223
delim,
277-
tts: parse(tts, parsing_patterns, sess, node_id, features, edition),
224+
tts: parse(tts, expect_matchers, sess, node_id, features, edition),
278225
}),
279226
),
280227
}
@@ -362,15 +309,3 @@ fn parse_sep_and_kleene_op(
362309
// Return a dummy
363310
(None, KleeneToken::new(KleeneOp::ZeroOrMore, span))
364311
}
365-
366-
// `$$` or a meta-variable is the lhs of a macro but shouldn't.
367-
//
368-
// For example, `macro_rules! foo { ( ${length()} ) => {} }`
369-
fn span_dollar_dollar_or_metavar_in_the_lhs_err<'sess>(sess: &'sess ParseSess, token: &Token) {
370-
sess.span_diagnostic
371-
.span_err(token.span, &format!("unexpected token: {}", pprust::token_to_string(token)));
372-
sess.span_diagnostic.span_note_without_error(
373-
token.span,
374-
"`$$` and meta-variable expressions are not allowed inside macro parameter definitions",
375-
);
376-
}

0 commit comments

Comments
 (0)