Auto merge of #18137 - ShoyuVanilla:expr-2021, r=Veykril
feat: Implement `expr_2021` Resolves #18062
This commit is contained in:
commit
44f8545b3c
@ -146,7 +146,7 @@ fn collect_from_op(op: &Op, token_trees: &mut Vec<tt::TokenTree<Span>>, seed: &m
|
||||
Some(MetaVarKind::Pat) => token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Path) => token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Literal) => token_trees.push(make_literal("1")),
|
||||
Some(MetaVarKind::Expr) => token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Expr(_)) => token_trees.push(make_ident("foo")),
|
||||
Some(MetaVarKind::Lifetime) => {
|
||||
token_trees.push(make_punct('\''));
|
||||
token_trees.push(make_ident("a"));
|
||||
|
@ -69,7 +69,7 @@
|
||||
use crate::{
|
||||
expander::{Binding, Bindings, ExpandResult, Fragment},
|
||||
expect_fragment,
|
||||
parser::{MetaVarKind, Op, RepeatKind, Separator},
|
||||
parser::{ExprKind, MetaVarKind, Op, RepeatKind, Separator},
|
||||
ExpandError, ExpandErrorKind, MetaTemplate, ValueResult,
|
||||
};
|
||||
|
||||
@ -769,23 +769,28 @@ fn match_meta_var(
|
||||
it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
|
||||
});
|
||||
}
|
||||
MetaVarKind::Expr => {
|
||||
// `expr` should not match underscores, let expressions, or inline const. The latter
|
||||
// two are for [backwards compatibility][0].
|
||||
MetaVarKind::Expr(expr) => {
|
||||
// `expr_2021` should not match underscores, let expressions, or inline const.
|
||||
// The latter two are for [backwards compatibility][0].
|
||||
// And `expr` also should not contain let expressions but may contain the other two
|
||||
// since `Edition2024`.
|
||||
// HACK: Macro expansion should not be done using "rollback and try another alternative".
|
||||
// rustc [explicitly checks the next token][1].
|
||||
// [0]: https://github.com/rust-lang/rust/issues/86730
|
||||
// [1]: https://github.com/rust-lang/rust/blob/f0c4da499/compiler/rustc_expand/src/mbe/macro_parser.rs#L576
|
||||
match input.peek_n(0) {
|
||||
Some(tt::TokenTree::Leaf(tt::Leaf::Ident(it)))
|
||||
if it.sym == sym::underscore
|
||||
|| it.sym == sym::let_
|
||||
|| it.sym == sym::const_ =>
|
||||
{
|
||||
Some(tt::TokenTree::Leaf(tt::Leaf::Ident(it))) => {
|
||||
let is_err = if matches!(expr, ExprKind::Expr2021) {
|
||||
it.sym == sym::underscore || it.sym == sym::let_ || it.sym == sym::const_
|
||||
} else {
|
||||
it.sym == sym::let_
|
||||
};
|
||||
if is_err {
|
||||
return ExpandResult::only_err(ExpandError::new(
|
||||
it.span,
|
||||
ExpandErrorKind::NoMatchingRule,
|
||||
))
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
@ -97,7 +97,7 @@ macro_rules! binding_err {
|
||||
| MetaVarKind::Ty
|
||||
| MetaVarKind::Pat
|
||||
| MetaVarKind::PatParam
|
||||
| MetaVarKind::Expr
|
||||
| MetaVarKind::Expr(_)
|
||||
| MetaVarKind::Ident => {
|
||||
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
|
||||
sym: sym::missing.clone(),
|
||||
|
@ -105,6 +105,16 @@ pub(crate) enum RepeatKind {
|
||||
ZeroOrOne,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum ExprKind {
|
||||
// Matches expressions using the post-edition 2024. Was written using
|
||||
// `expr` in edition 2024 or later.
|
||||
Expr,
|
||||
// Matches expressions using the pre-edition 2024 rules.
|
||||
// Either written using `expr` in edition 2021 or earlier or.was written using `expr_2021`.
|
||||
Expr2021,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum MetaVarKind {
|
||||
Path,
|
||||
@ -116,7 +126,7 @@ pub(crate) enum MetaVarKind {
|
||||
Meta,
|
||||
Item,
|
||||
Vis,
|
||||
Expr,
|
||||
Expr(ExprKind),
|
||||
Ident,
|
||||
Tt,
|
||||
Lifetime,
|
||||
@ -277,17 +287,27 @@ fn eat_fragment_kind(
|
||||
let kind = match ident.sym.as_str() {
|
||||
"path" => MetaVarKind::Path,
|
||||
"ty" => MetaVarKind::Ty,
|
||||
"pat" => match edition(ident.span.ctx) {
|
||||
Edition::Edition2015 | Edition::Edition2018 => MetaVarKind::PatParam,
|
||||
Edition::Edition2021 | Edition::Edition2024 => MetaVarKind::Pat,
|
||||
},
|
||||
"pat" => {
|
||||
if edition(ident.span.ctx).at_least_2021() {
|
||||
MetaVarKind::Pat
|
||||
} else {
|
||||
MetaVarKind::PatParam
|
||||
}
|
||||
}
|
||||
"pat_param" => MetaVarKind::PatParam,
|
||||
"stmt" => MetaVarKind::Stmt,
|
||||
"block" => MetaVarKind::Block,
|
||||
"meta" => MetaVarKind::Meta,
|
||||
"item" => MetaVarKind::Item,
|
||||
"vis" => MetaVarKind::Vis,
|
||||
"expr" => MetaVarKind::Expr,
|
||||
"expr" => {
|
||||
if edition(ident.span.ctx).at_least_2024() {
|
||||
MetaVarKind::Expr(ExprKind::Expr)
|
||||
} else {
|
||||
MetaVarKind::Expr(ExprKind::Expr2021)
|
||||
}
|
||||
}
|
||||
"expr_2021" => MetaVarKind::Expr(ExprKind::Expr2021),
|
||||
"ident" => MetaVarKind::Ident,
|
||||
"tt" => MetaVarKind::Tt,
|
||||
"lifetime" => MetaVarKind::Lifetime,
|
||||
|
@ -177,3 +177,149 @@ fn main(){
|
||||
}"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expr_2021() {
|
||||
check(
|
||||
Edition::Edition2024,
|
||||
Edition::Edition2024,
|
||||
r#"
|
||||
($($e:expr),* $(,)?) => {
|
||||
$($e);* ;
|
||||
};
|
||||
"#,
|
||||
r#"
|
||||
_,
|
||||
const { 1 },
|
||||
"#,
|
||||
expect![[r#"
|
||||
SUBTREE $$ 1:0@0..25#0 1:0@0..25#0
|
||||
IDENT _ 1:0@5..6#0
|
||||
PUNCH ; [joint] 0:0@36..37#0
|
||||
SUBTREE () 0:0@34..35#0 0:0@34..35#0
|
||||
IDENT const 1:0@12..17#0
|
||||
SUBTREE {} 1:0@18..19#0 1:0@22..23#0
|
||||
LITERAL Integer 1 1:0@20..21#0
|
||||
PUNCH ; [alone] 0:0@39..40#0
|
||||
|
||||
_;
|
||||
(const {
|
||||
1
|
||||
});"#]],
|
||||
);
|
||||
check(
|
||||
Edition::Edition2021,
|
||||
Edition::Edition2024,
|
||||
r#"
|
||||
($($e:expr),* $(,)?) => {
|
||||
$($e);* ;
|
||||
};
|
||||
"#,
|
||||
r#"
|
||||
_,
|
||||
"#,
|
||||
expect![[r#"
|
||||
ExpandError {
|
||||
inner: (
|
||||
1:0@5..6#0,
|
||||
NoMatchingRule,
|
||||
),
|
||||
}
|
||||
|
||||
SUBTREE $$ 1:0@0..8#0 1:0@0..8#0
|
||||
PUNCH ; [alone] 0:0@39..40#0
|
||||
|
||||
;"#]],
|
||||
);
|
||||
check(
|
||||
Edition::Edition2021,
|
||||
Edition::Edition2024,
|
||||
r#"
|
||||
($($e:expr),* $(,)?) => {
|
||||
$($e);* ;
|
||||
};
|
||||
"#,
|
||||
r#"
|
||||
const { 1 },
|
||||
"#,
|
||||
expect![[r#"
|
||||
ExpandError {
|
||||
inner: (
|
||||
1:0@5..10#0,
|
||||
NoMatchingRule,
|
||||
),
|
||||
}
|
||||
|
||||
SUBTREE $$ 1:0@0..18#0 1:0@0..18#0
|
||||
PUNCH ; [alone] 0:0@39..40#0
|
||||
|
||||
;"#]],
|
||||
);
|
||||
check(
|
||||
Edition::Edition2024,
|
||||
Edition::Edition2024,
|
||||
r#"
|
||||
($($e:expr_2021),* $(,)?) => {
|
||||
$($e);* ;
|
||||
};
|
||||
"#,
|
||||
r#"
|
||||
4,
|
||||
"literal",
|
||||
funcall(),
|
||||
future.await,
|
||||
break 'foo bar,
|
||||
"#,
|
||||
expect![[r#"
|
||||
SUBTREE $$ 1:0@0..76#0 1:0@0..76#0
|
||||
LITERAL Integer 4 1:0@5..6#0
|
||||
PUNCH ; [joint] 0:0@41..42#0
|
||||
LITERAL Str literal 1:0@12..21#0
|
||||
PUNCH ; [joint] 0:0@41..42#0
|
||||
SUBTREE () 0:0@39..40#0 0:0@39..40#0
|
||||
IDENT funcall 1:0@27..34#0
|
||||
SUBTREE () 1:0@34..35#0 1:0@35..36#0
|
||||
PUNCH ; [joint] 0:0@41..42#0
|
||||
SUBTREE () 0:0@39..40#0 0:0@39..40#0
|
||||
IDENT future 1:0@42..48#0
|
||||
PUNCH . [alone] 1:0@48..49#0
|
||||
IDENT await 1:0@49..54#0
|
||||
PUNCH ; [joint] 0:0@41..42#0
|
||||
SUBTREE () 0:0@39..40#0 0:0@39..40#0
|
||||
IDENT break 1:0@60..65#0
|
||||
PUNCH ' [joint] 1:0@66..67#0
|
||||
IDENT foo 1:0@67..70#0
|
||||
IDENT bar 1:0@71..74#0
|
||||
PUNCH ; [alone] 0:0@44..45#0
|
||||
|
||||
4;
|
||||
"literal";
|
||||
(funcall());
|
||||
(future.await);
|
||||
(break 'foo bar);"#]],
|
||||
);
|
||||
check(
|
||||
Edition::Edition2024,
|
||||
Edition::Edition2024,
|
||||
r#"
|
||||
($($e:expr_2021),* $(,)?) => {
|
||||
$($e);* ;
|
||||
};
|
||||
"#,
|
||||
r#"
|
||||
_,
|
||||
"#,
|
||||
expect![[r#"
|
||||
ExpandError {
|
||||
inner: (
|
||||
1:0@5..6#0,
|
||||
NoMatchingRule,
|
||||
),
|
||||
}
|
||||
|
||||
SUBTREE $$ 1:0@0..8#0 1:0@0..8#0
|
||||
PUNCH ; [alone] 0:0@44..45#0
|
||||
|
||||
;"#]],
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user