Skip to content

Commit 54af603

Browse files
committed
Add support for become expr/tail calls
1 parent b7cdd93 commit 54af603

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
@@ -398,6 +398,11 @@ impl ExprCollector<'_> {
398398
let expr = e.expr().map(|e| self.collect_expr(e));
399399
self.alloc_expr(Expr::Return { expr }, syntax_ptr)
400400
}
401+
ast::Expr::BecomeExpr(e) => {
402+
let expr =
403+
e.expr().map(|e| self.collect_expr(e)).unwrap_or_else(|| self.missing_expr());
404+
self.alloc_expr(Expr::Become { expr }, syntax_ptr)
405+
}
401406
ast::Expr::YieldExpr(e) => {
402407
self.is_lowering_generator = true;
403408
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
@@ -247,6 +247,11 @@ impl<'a> Printer<'a> {
247247
self.print_expr(*expr);
248248
}
249249
}
250+
Expr::Become { expr } => {
251+
w!(self, "become");
252+
self.whitespace();
253+
self.print_expr(*expr);
254+
}
250255
Expr::Yield { expr } => {
251256
w!(self, "yield");
252257
if let Some(expr) = expr {

crates/hir-def/src/hir.rs

+4
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ pub enum Expr {
219219
Return {
220220
expr: Option<ExprId>,
221221
},
222+
Become {
223+
expr: ExprId,
224+
},
222225
Yield {
223226
expr: Option<ExprId>,
224227
},
@@ -406,6 +409,7 @@ impl Expr {
406409
f(expr);
407410
}
408411
}
412+
Expr::Become { expr } => f(*expr),
409413
Expr::RecordLit { fields, spread, .. } => {
410414
for field in fields.iter() {
411415
f(field.expr);

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

+3
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,9 @@ impl InferenceContext<'_> {
509509
self.consume_expr(expr);
510510
}
511511
}
512+
&Expr::Become { expr } => {
513+
self.consume_expr(expr);
514+
}
512515
Expr::RecordLit { fields, spread, .. } => {
513516
if let &Some(expr) = spread {
514517
self.consume_expr(expr);

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

+22
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ impl<'a> InferenceContext<'a> {
513513
self.result.standard_types.never.clone()
514514
}
515515
&Expr::Return { expr } => self.infer_expr_return(expr),
516+
&Expr::Become { expr } => self.infer_expr_become(expr),
516517
Expr::Yield { expr } => {
517518
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
518519
if let Some(expr) = expr {
@@ -1022,6 +1023,27 @@ impl<'a> InferenceContext<'a> {
10221023
self.result.standard_types.never.clone()
10231024
}
10241025

1026+
fn infer_expr_become(&mut self, expr: ExprId) -> Ty {
1027+
match &self.return_coercion {
1028+
Some(return_coercion) => {
1029+
let ret_ty = return_coercion.expected_ty();
1030+
1031+
let call_expr_ty =
1032+
self.infer_expr_inner(expr, &Expectation::HasType(ret_ty.clone()));
1033+
1034+
// NB: this should *not* coerce.
1035+
// tail calls don't support any coercions except lifetimes ones (like `&'static u8 -> &'a u8`).
1036+
self.unify(&call_expr_ty, &ret_ty);
1037+
}
1038+
None => {
1039+
// FIXME: diagnose `become` outside of functions
1040+
self.infer_expr_no_expect(expr);
1041+
}
1042+
}
1043+
1044+
self.result.standard_types.never.clone()
1045+
}
1046+
10251047
fn infer_expr_box(&mut self, inner_expr: ExprId, expected: &Expectation) -> Ty {
10261048
if let Some(box_id) = self.resolve_boxed_box() {
10271049
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<'a> InferenceContext<'a> {
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(|x| x.expr).chain(*spread))
98101
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
689689
self.set_terminator(current, TerminatorKind::Return, expr_id.into());
690690
Ok(None)
691691
}
692+
Expr::Become { .. } => not_supported!("tail-calls"),
692693
Expr::Yield { .. } => not_supported!("yield"),
693694
Expr::RecordLit { fields, path, spread, ellipsis: _, is_assignee_expr: _ } => {
694695
let spread_place = match spread {

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

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

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

+14
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
5353
T![match],
5454
T![move],
5555
T![return],
56+
T![become],
5657
T![static],
5758
T![try],
5859
T![unsafe],
@@ -95,6 +96,7 @@ pub(super) fn atom_expr(
9596
T![try] => try_block_expr(p, None),
9697
T![match] => match_expr(p),
9798
T![return] => return_expr(p),
99+
T![become] => become_expr(p),
98100
T![yield] => yield_expr(p),
99101
T![do] if p.nth_at_contextual_kw(1, T![yeet]) => yeet_expr(p),
100102
T![continue] => continue_expr(p),
@@ -538,6 +540,18 @@ fn return_expr(p: &mut Parser<'_>) -> CompletedMarker {
538540
m.complete(p, RETURN_EXPR)
539541
}
540542

543+
// test become_expr
544+
// fn foo() {
545+
// become foo();
546+
// }
547+
fn become_expr(p: &mut Parser<'_>) -> CompletedMarker {
548+
assert!(p.at(T![become]));
549+
let m = p.start();
550+
p.bump(T![become]);
551+
expr(p);
552+
m.complete(p, BECOME_EXPR)
553+
}
554+
541555
// test yield_expr
542556
// fn foo() {
543557
// 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,
@@ -190,6 +191,7 @@ pub enum SyntaxKind {
190191
BLOCK_EXPR,
191192
STMT_LIST,
192193
RETURN_EXPR,
194+
BECOME_EXPR,
193195
YIELD_EXPR,
194196
YEET_EXPR,
195197
LET_EXPR,
@@ -298,6 +300,7 @@ impl SyntaxKind {
298300
| PUB_KW
299301
| REF_KW
300302
| RETURN_KW
303+
| BECOME_KW
301304
| SELF_KW
302305
| SELF_TYPE_KW
303306
| STATIC_KW
@@ -412,6 +415,7 @@ impl SyntaxKind {
412415
"pub" => PUB_KW,
413416
"ref" => REF_KW,
414417
"return" => RETURN_KW,
418+
"become" => BECOME_KW,
415419
"self" => SELF_KW,
416420
"Self" => SELF_TYPE_KW,
417421
"static" => STATIC_KW,
@@ -479,5 +483,5 @@ impl SyntaxKind {
479483
}
480484
}
481485
#[macro_export]
482-
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 } ; [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 } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
486+
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 } ; [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 } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
483487
pub use T;
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
@@ -361,6 +361,7 @@ Expr =
361361
| RecordExpr
362362
| RefExpr
363363
| ReturnExpr
364+
| BecomeExpr
364365
| TryExpr
365366
| TupleExpr
366367
| WhileExpr
@@ -507,6 +508,9 @@ MatchGuard =
507508
ReturnExpr =
508509
Attr* 'return' Expr?
509510

511+
BecomeExpr =
512+
Attr* 'become' Expr
513+
510514
YieldExpr =
511515
Attr* 'yield' Expr?
512516

0 commit comments

Comments
 (0)