Skip to content

Commit dba5997

Browse files
committed
Auto merge of #15003 - WaffleLapkin:become_unuwuable, r=Veykril
feature: Add basic support for `become` expr/tail calls This follows rust-lang/rfcs#3407 and my WIP implementation in the compiler. Notice that I haven't even *opened* a compiler PR (although I plan to soon), so this feature doesn't really exist outside of my WIP branches. I've used this to help me test my implementation; opening a PR before I forget. (feel free to ignore this for now, given all of the above)
2 parents 3bb8d3a + e146139 commit dba5997

File tree

16 files changed

+144
-6
lines changed

16 files changed

+144
-6
lines changed

crates/hir-def/src/body/lower.rs

+5
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,11 @@ impl ExprCollector<'_> {
416416
let expr = e.expr().map(|e| self.collect_expr(e));
417417
self.alloc_expr(Expr::Return { expr }, syntax_ptr)
418418
}
419+
ast::Expr::BecomeExpr(e) => {
420+
let expr =
421+
e.expr().map(|e| self.collect_expr(e)).unwrap_or_else(|| self.missing_expr());
422+
self.alloc_expr(Expr::Become { expr }, syntax_ptr)
423+
}
419424
ast::Expr::YieldExpr(e) => {
420425
self.is_lowering_coroutine = true;
421426
let expr = e.expr().map(|e| self.collect_expr(e));

crates/hir-def/src/body/pretty.rs

+5
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ impl Printer<'_> {
261261
self.print_expr(*expr);
262262
}
263263
}
264+
Expr::Become { expr } => {
265+
w!(self, "become");
266+
self.whitespace();
267+
self.print_expr(*expr);
268+
}
264269
Expr::Yield { expr } => {
265270
w!(self, "yield");
266271
if let Some(expr) = expr {

crates/hir-def/src/hir.rs

+4
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ pub enum Expr {
216216
Return {
217217
expr: Option<ExprId>,
218218
},
219+
Become {
220+
expr: ExprId,
221+
},
219222
Yield {
220223
expr: Option<ExprId>,
221224
},
@@ -410,6 +413,7 @@ impl Expr {
410413
f(expr);
411414
}
412415
}
416+
Expr::Become { expr } => f(*expr),
413417
Expr::RecordLit { fields, spread, .. } => {
414418
for field in fields.iter() {
415419
f(field.expr);

crates/hir-ty/src/infer/closure.rs

+3
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,9 @@ impl InferenceContext<'_> {
531531
self.consume_expr(expr);
532532
}
533533
}
534+
&Expr::Become { expr } => {
535+
self.consume_expr(expr);
536+
}
534537
Expr::RecordLit { fields, spread, .. } => {
535538
if let &Some(expr) = spread {
536539
self.consume_expr(expr);

crates/hir-ty/src/infer/expr.rs

+22
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ impl InferenceContext<'_> {
502502
self.result.standard_types.never.clone()
503503
}
504504
&Expr::Return { expr } => self.infer_expr_return(tgt_expr, expr),
505+
&Expr::Become { expr } => self.infer_expr_become(expr),
505506
Expr::Yield { expr } => {
506507
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
507508
if let Some(expr) = expr {
@@ -1084,6 +1085,27 @@ impl InferenceContext<'_> {
10841085
self.result.standard_types.never.clone()
10851086
}
10861087

1088+
fn infer_expr_become(&mut self, expr: ExprId) -> Ty {
1089+
match &self.return_coercion {
1090+
Some(return_coercion) => {
1091+
let ret_ty = return_coercion.expected_ty();
1092+
1093+
let call_expr_ty =
1094+
self.infer_expr_inner(expr, &Expectation::HasType(ret_ty.clone()));
1095+
1096+
// NB: this should *not* coerce.
1097+
// tail calls don't support any coercions except lifetimes ones (like `&'static u8 -> &'a u8`).
1098+
self.unify(&call_expr_ty, &ret_ty);
1099+
}
1100+
None => {
1101+
// FIXME: diagnose `become` outside of functions
1102+
self.infer_expr_no_expect(expr);
1103+
}
1104+
}
1105+
1106+
self.result.standard_types.never.clone()
1107+
}
1108+
10871109
fn infer_expr_box(&mut self, inner_expr: ExprId, expected: &Expectation) -> Ty {
10881110
if let Some(box_id) = self.resolve_boxed_box() {
10891111
let table = &mut self.table;

crates/hir-ty/src/infer/mutability.rs

+3
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ impl InferenceContext<'_> {
9393
self.infer_mut_expr(expr, Mutability::Not);
9494
}
9595
}
96+
Expr::Become { expr } => {
97+
self.infer_mut_expr(*expr, Mutability::Not);
98+
}
9699
Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => {
97100
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
98101
}

crates/hir-ty/src/mir/lower.rs

+1
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
775775
self.set_terminator(current, TerminatorKind::Return, expr_id.into());
776776
Ok(None)
777777
}
778+
Expr::Become { .. } => not_supported!("tail-calls"),
778779
Expr::Yield { .. } => not_supported!("yield"),
779780
Expr::RecordLit { fields, path, spread, ellipsis: _, is_assignee_expr: _ } => {
780781
let spread_place = match spread {

crates/ide-db/src/syntax_helpers/node_ext.rs

+1
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
329329
| ast::Expr::RecordExpr(_)
330330
| ast::Expr::RefExpr(_)
331331
| ast::Expr::ReturnExpr(_)
332+
| ast::Expr::BecomeExpr(_)
332333
| ast::Expr::TryExpr(_)
333334
| ast::Expr::TupleExpr(_)
334335
| ast::Expr::LetExpr(_)

crates/parser/src/grammar/expressions/atom.rs

+14
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
5858
T![match],
5959
T![move],
6060
T![return],
61+
T![become],
6162
T![static],
6263
T![try],
6364
T![unsafe],
@@ -102,6 +103,7 @@ pub(super) fn atom_expr(
102103
T![try] => try_block_expr(p, None),
103104
T![match] => match_expr(p),
104105
T![return] => return_expr(p),
106+
T![become] => become_expr(p),
105107
T![yield] => yield_expr(p),
106108
T![do] if p.nth_at_contextual_kw(1, T![yeet]) => yeet_expr(p),
107109
T![continue] => continue_expr(p),
@@ -621,6 +623,18 @@ fn return_expr(p: &mut Parser<'_>) -> CompletedMarker {
621623
m.complete(p, RETURN_EXPR)
622624
}
623625

626+
// test become_expr
627+
// fn foo() {
628+
// become foo();
629+
// }
630+
fn become_expr(p: &mut Parser<'_>) -> CompletedMarker {
631+
assert!(p.at(T![become]));
632+
let m = p.start();
633+
p.bump(T![become]);
634+
expr(p);
635+
m.complete(p, BECOME_EXPR)
636+
}
637+
624638
// test yield_expr
625639
// fn foo() {
626640
// yield;

crates/parser/src/syntax_kind/generated.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub enum SyntaxKind {
9090
PUB_KW,
9191
REF_KW,
9292
RETURN_KW,
93+
BECOME_KW,
9394
SELF_KW,
9495
SELF_TYPE_KW,
9596
STATIC_KW,
@@ -195,6 +196,7 @@ pub enum SyntaxKind {
195196
BLOCK_EXPR,
196197
STMT_LIST,
197198
RETURN_EXPR,
199+
BECOME_EXPR,
198200
YIELD_EXPR,
199201
YEET_EXPR,
200202
LET_EXPR,
@@ -307,6 +309,7 @@ impl SyntaxKind {
307309
| PUB_KW
308310
| REF_KW
309311
| RETURN_KW
312+
| BECOME_KW
310313
| SELF_KW
311314
| SELF_TYPE_KW
312315
| STATIC_KW
@@ -425,6 +428,7 @@ impl SyntaxKind {
425428
"pub" => PUB_KW,
426429
"ref" => REF_KW,
427430
"return" => RETURN_KW,
431+
"become" => BECOME_KW,
428432
"self" => SELF_KW,
429433
"Self" => SELF_TYPE_KW,
430434
"static" => STATIC_KW,
@@ -496,4 +500,4 @@ impl SyntaxKind {
496500
}
497501
}
498502
#[macro_export]
499-
macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
503+
macro_rules ! T { [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [existential] => { $ crate :: SyntaxKind :: EXISTENTIAL_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "foo"
7+
PARAM_LIST
8+
L_PAREN "("
9+
R_PAREN ")"
10+
WHITESPACE " "
11+
BLOCK_EXPR
12+
STMT_LIST
13+
L_CURLY "{"
14+
WHITESPACE "\n "
15+
EXPR_STMT
16+
BECOME_EXPR
17+
BECOME_KW "become"
18+
WHITESPACE " "
19+
CALL_EXPR
20+
PATH_EXPR
21+
PATH
22+
PATH_SEGMENT
23+
NAME_REF
24+
IDENT "foo"
25+
ARG_LIST
26+
L_PAREN "("
27+
R_PAREN ")"
28+
SEMICOLON ";"
29+
WHITESPACE "\n"
30+
R_CURLY "}"
31+
WHITESPACE "\n"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn foo() {
2+
become foo();
3+
}

crates/syntax/rust.ungram

+4
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ Expr =
367367
| RecordExpr
368368
| RefExpr
369369
| ReturnExpr
370+
| BecomeExpr
370371
| TryExpr
371372
| TupleExpr
372373
| WhileExpr
@@ -528,6 +529,9 @@ MatchGuard =
528529
ReturnExpr =
529530
Attr* 'return' Expr?
530531

532+
BecomeExpr =
533+
Attr* 'become' Expr
534+
531535
YieldExpr =
532536
Attr* 'yield' Expr?
533537

0 commit comments

Comments
 (0)