Auto merge of #15003 - WaffleLapkin:become_unuwuable, r=Veykril
feature: Add basic support for `become` expr/tail calls This follows https://github.com/rust-lang/rfcs/pull/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)
This commit is contained in:
commit
dba59970bc
@ -416,6 +416,11 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
|
|||||||
let expr = e.expr().map(|e| self.collect_expr(e));
|
let expr = e.expr().map(|e| self.collect_expr(e));
|
||||||
self.alloc_expr(Expr::Return { expr }, syntax_ptr)
|
self.alloc_expr(Expr::Return { expr }, syntax_ptr)
|
||||||
}
|
}
|
||||||
|
ast::Expr::BecomeExpr(e) => {
|
||||||
|
let expr =
|
||||||
|
e.expr().map(|e| self.collect_expr(e)).unwrap_or_else(|| self.missing_expr());
|
||||||
|
self.alloc_expr(Expr::Become { expr }, syntax_ptr)
|
||||||
|
}
|
||||||
ast::Expr::YieldExpr(e) => {
|
ast::Expr::YieldExpr(e) => {
|
||||||
self.is_lowering_coroutine = true;
|
self.is_lowering_coroutine = true;
|
||||||
let expr = e.expr().map(|e| self.collect_expr(e));
|
let expr = e.expr().map(|e| self.collect_expr(e));
|
||||||
|
@ -261,6 +261,11 @@ fn print_expr(&mut self, expr: ExprId) {
|
|||||||
self.print_expr(*expr);
|
self.print_expr(*expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::Become { expr } => {
|
||||||
|
w!(self, "become");
|
||||||
|
self.whitespace();
|
||||||
|
self.print_expr(*expr);
|
||||||
|
}
|
||||||
Expr::Yield { expr } => {
|
Expr::Yield { expr } => {
|
||||||
w!(self, "yield");
|
w!(self, "yield");
|
||||||
if let Some(expr) = expr {
|
if let Some(expr) = expr {
|
||||||
|
@ -216,6 +216,9 @@ pub enum Expr {
|
|||||||
Return {
|
Return {
|
||||||
expr: Option<ExprId>,
|
expr: Option<ExprId>,
|
||||||
},
|
},
|
||||||
|
Become {
|
||||||
|
expr: ExprId,
|
||||||
|
},
|
||||||
Yield {
|
Yield {
|
||||||
expr: Option<ExprId>,
|
expr: Option<ExprId>,
|
||||||
},
|
},
|
||||||
@ -410,6 +413,7 @@ pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
|
|||||||
f(expr);
|
f(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::Become { expr } => f(*expr),
|
||||||
Expr::RecordLit { fields, spread, .. } => {
|
Expr::RecordLit { fields, spread, .. } => {
|
||||||
for field in fields.iter() {
|
for field in fields.iter() {
|
||||||
f(field.expr);
|
f(field.expr);
|
||||||
|
@ -531,6 +531,9 @@ fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) {
|
|||||||
self.consume_expr(expr);
|
self.consume_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&Expr::Become { expr } => {
|
||||||
|
self.consume_expr(expr);
|
||||||
|
}
|
||||||
Expr::RecordLit { fields, spread, .. } => {
|
Expr::RecordLit { fields, spread, .. } => {
|
||||||
if let &Some(expr) = spread {
|
if let &Some(expr) = spread {
|
||||||
self.consume_expr(expr);
|
self.consume_expr(expr);
|
||||||
|
@ -502,6 +502,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
|||||||
self.result.standard_types.never.clone()
|
self.result.standard_types.never.clone()
|
||||||
}
|
}
|
||||||
&Expr::Return { expr } => self.infer_expr_return(tgt_expr, expr),
|
&Expr::Return { expr } => self.infer_expr_return(tgt_expr, expr),
|
||||||
|
&Expr::Become { expr } => self.infer_expr_become(expr),
|
||||||
Expr::Yield { expr } => {
|
Expr::Yield { expr } => {
|
||||||
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
|
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
|
||||||
if let Some(expr) = expr {
|
if let Some(expr) = expr {
|
||||||
@ -1084,6 +1085,27 @@ fn infer_expr_return(&mut self, ret: ExprId, expr: Option<ExprId>) -> Ty {
|
|||||||
self.result.standard_types.never.clone()
|
self.result.standard_types.never.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn infer_expr_become(&mut self, expr: ExprId) -> Ty {
|
||||||
|
match &self.return_coercion {
|
||||||
|
Some(return_coercion) => {
|
||||||
|
let ret_ty = return_coercion.expected_ty();
|
||||||
|
|
||||||
|
let call_expr_ty =
|
||||||
|
self.infer_expr_inner(expr, &Expectation::HasType(ret_ty.clone()));
|
||||||
|
|
||||||
|
// NB: this should *not* coerce.
|
||||||
|
// tail calls don't support any coercions except lifetimes ones (like `&'static u8 -> &'a u8`).
|
||||||
|
self.unify(&call_expr_ty, &ret_ty);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// FIXME: diagnose `become` outside of functions
|
||||||
|
self.infer_expr_no_expect(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.result.standard_types.never.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn infer_expr_box(&mut self, inner_expr: ExprId, expected: &Expectation) -> Ty {
|
fn infer_expr_box(&mut self, inner_expr: ExprId, expected: &Expectation) -> Ty {
|
||||||
if let Some(box_id) = self.resolve_boxed_box() {
|
if let Some(box_id) = self.resolve_boxed_box() {
|
||||||
let table = &mut self.table;
|
let table = &mut self.table;
|
||||||
|
@ -93,6 +93,9 @@ fn infer_mut_expr_without_adjust(&mut self, tgt_expr: ExprId, mutability: Mutabi
|
|||||||
self.infer_mut_expr(expr, Mutability::Not);
|
self.infer_mut_expr(expr, Mutability::Not);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::Become { expr } => {
|
||||||
|
self.infer_mut_expr(*expr, Mutability::Not);
|
||||||
|
}
|
||||||
Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => {
|
Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => {
|
||||||
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
|
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
|
||||||
}
|
}
|
||||||
|
@ -775,6 +775,7 @@ fn lower_expr_to_place_without_adjust(
|
|||||||
self.set_terminator(current, TerminatorKind::Return, expr_id.into());
|
self.set_terminator(current, TerminatorKind::Return, expr_id.into());
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
Expr::Become { .. } => not_supported!("tail-calls"),
|
||||||
Expr::Yield { .. } => not_supported!("yield"),
|
Expr::Yield { .. } => not_supported!("yield"),
|
||||||
Expr::RecordLit { fields, path, spread, ellipsis: _, is_assignee_expr: _ } => {
|
Expr::RecordLit { fields, path, spread, ellipsis: _, is_assignee_expr: _ } => {
|
||||||
let spread_place = match spread {
|
let spread_place = match spread {
|
||||||
|
@ -329,6 +329,7 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
|
|||||||
| ast::Expr::RecordExpr(_)
|
| ast::Expr::RecordExpr(_)
|
||||||
| ast::Expr::RefExpr(_)
|
| ast::Expr::RefExpr(_)
|
||||||
| ast::Expr::ReturnExpr(_)
|
| ast::Expr::ReturnExpr(_)
|
||||||
|
| ast::Expr::BecomeExpr(_)
|
||||||
| ast::Expr::TryExpr(_)
|
| ast::Expr::TryExpr(_)
|
||||||
| ast::Expr::TupleExpr(_)
|
| ast::Expr::TupleExpr(_)
|
||||||
| ast::Expr::LetExpr(_)
|
| ast::Expr::LetExpr(_)
|
||||||
|
@ -58,6 +58,7 @@ pub(crate) fn literal(p: &mut Parser<'_>) -> Option<CompletedMarker> {
|
|||||||
T![match],
|
T![match],
|
||||||
T![move],
|
T![move],
|
||||||
T![return],
|
T![return],
|
||||||
|
T![become],
|
||||||
T![static],
|
T![static],
|
||||||
T![try],
|
T![try],
|
||||||
T![unsafe],
|
T![unsafe],
|
||||||
@ -102,6 +103,7 @@ pub(super) fn atom_expr(
|
|||||||
T![try] => try_block_expr(p, None),
|
T![try] => try_block_expr(p, None),
|
||||||
T![match] => match_expr(p),
|
T![match] => match_expr(p),
|
||||||
T![return] => return_expr(p),
|
T![return] => return_expr(p),
|
||||||
|
T![become] => become_expr(p),
|
||||||
T![yield] => yield_expr(p),
|
T![yield] => yield_expr(p),
|
||||||
T![do] if p.nth_at_contextual_kw(1, T![yeet]) => yeet_expr(p),
|
T![do] if p.nth_at_contextual_kw(1, T![yeet]) => yeet_expr(p),
|
||||||
T![continue] => continue_expr(p),
|
T![continue] => continue_expr(p),
|
||||||
@ -621,6 +623,18 @@ fn return_expr(p: &mut Parser<'_>) -> CompletedMarker {
|
|||||||
m.complete(p, RETURN_EXPR)
|
m.complete(p, RETURN_EXPR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test become_expr
|
||||||
|
// fn foo() {
|
||||||
|
// become foo();
|
||||||
|
// }
|
||||||
|
fn become_expr(p: &mut Parser<'_>) -> CompletedMarker {
|
||||||
|
assert!(p.at(T![become]));
|
||||||
|
let m = p.start();
|
||||||
|
p.bump(T![become]);
|
||||||
|
expr(p);
|
||||||
|
m.complete(p, BECOME_EXPR)
|
||||||
|
}
|
||||||
|
|
||||||
// test yield_expr
|
// test yield_expr
|
||||||
// fn foo() {
|
// fn foo() {
|
||||||
// yield;
|
// yield;
|
||||||
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,31 @@
|
|||||||
|
SOURCE_FILE
|
||||||
|
FN
|
||||||
|
FN_KW "fn"
|
||||||
|
WHITESPACE " "
|
||||||
|
NAME
|
||||||
|
IDENT "foo"
|
||||||
|
PARAM_LIST
|
||||||
|
L_PAREN "("
|
||||||
|
R_PAREN ")"
|
||||||
|
WHITESPACE " "
|
||||||
|
BLOCK_EXPR
|
||||||
|
STMT_LIST
|
||||||
|
L_CURLY "{"
|
||||||
|
WHITESPACE "\n "
|
||||||
|
EXPR_STMT
|
||||||
|
BECOME_EXPR
|
||||||
|
BECOME_KW "become"
|
||||||
|
WHITESPACE " "
|
||||||
|
CALL_EXPR
|
||||||
|
PATH_EXPR
|
||||||
|
PATH
|
||||||
|
PATH_SEGMENT
|
||||||
|
NAME_REF
|
||||||
|
IDENT "foo"
|
||||||
|
ARG_LIST
|
||||||
|
L_PAREN "("
|
||||||
|
R_PAREN ")"
|
||||||
|
SEMICOLON ";"
|
||||||
|
WHITESPACE "\n"
|
||||||
|
R_CURLY "}"
|
||||||
|
WHITESPACE "\n"
|
@ -0,0 +1,3 @@
|
|||||||
|
fn foo() {
|
||||||
|
become foo();
|
||||||
|
}
|
@ -367,6 +367,7 @@ Expr =
|
|||||||
| RecordExpr
|
| RecordExpr
|
||||||
| RefExpr
|
| RefExpr
|
||||||
| ReturnExpr
|
| ReturnExpr
|
||||||
|
| BecomeExpr
|
||||||
| TryExpr
|
| TryExpr
|
||||||
| TupleExpr
|
| TupleExpr
|
||||||
| WhileExpr
|
| WhileExpr
|
||||||
@ -528,6 +529,9 @@ MatchGuard =
|
|||||||
ReturnExpr =
|
ReturnExpr =
|
||||||
Attr* 'return' Expr?
|
Attr* 'return' Expr?
|
||||||
|
|
||||||
|
BecomeExpr =
|
||||||
|
Attr* 'become' Expr
|
||||||
|
|
||||||
YieldExpr =
|
YieldExpr =
|
||||||
Attr* 'yield' Expr?
|
Attr* 'yield' Expr?
|
||||||
|
|
||||||
|
@ -1095,6 +1095,16 @@ pub fn return_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax,
|
|||||||
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct BecomeExpr {
|
||||||
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
}
|
||||||
|
impl ast::HasAttrs for BecomeExpr {}
|
||||||
|
impl BecomeExpr {
|
||||||
|
pub fn become_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![become]) }
|
||||||
|
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct TryExpr {
|
pub struct TryExpr {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
@ -1633,6 +1643,7 @@ pub enum Expr {
|
|||||||
RecordExpr(RecordExpr),
|
RecordExpr(RecordExpr),
|
||||||
RefExpr(RefExpr),
|
RefExpr(RefExpr),
|
||||||
ReturnExpr(ReturnExpr),
|
ReturnExpr(ReturnExpr),
|
||||||
|
BecomeExpr(BecomeExpr),
|
||||||
TryExpr(TryExpr),
|
TryExpr(TryExpr),
|
||||||
TupleExpr(TupleExpr),
|
TupleExpr(TupleExpr),
|
||||||
WhileExpr(WhileExpr),
|
WhileExpr(WhileExpr),
|
||||||
@ -2792,6 +2803,17 @@ fn cast(syntax: SyntaxNode) -> Option<Self> {
|
|||||||
}
|
}
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
}
|
}
|
||||||
|
impl AstNode for BecomeExpr {
|
||||||
|
fn can_cast(kind: SyntaxKind) -> bool { kind == BECOME_EXPR }
|
||||||
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
|
if Self::can_cast(syntax.kind()) {
|
||||||
|
Some(Self { syntax })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
|
}
|
||||||
impl AstNode for TryExpr {
|
impl AstNode for TryExpr {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR }
|
fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR }
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
@ -3540,6 +3562,9 @@ fn from(node: RefExpr) -> Expr { Expr::RefExpr(node) }
|
|||||||
impl From<ReturnExpr> for Expr {
|
impl From<ReturnExpr> for Expr {
|
||||||
fn from(node: ReturnExpr) -> Expr { Expr::ReturnExpr(node) }
|
fn from(node: ReturnExpr) -> Expr { Expr::ReturnExpr(node) }
|
||||||
}
|
}
|
||||||
|
impl From<BecomeExpr> for Expr {
|
||||||
|
fn from(node: BecomeExpr) -> Expr { Expr::BecomeExpr(node) }
|
||||||
|
}
|
||||||
impl From<TryExpr> for Expr {
|
impl From<TryExpr> for Expr {
|
||||||
fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
|
fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
|
||||||
}
|
}
|
||||||
@ -3593,6 +3618,7 @@ fn can_cast(kind: SyntaxKind) -> bool {
|
|||||||
| RECORD_EXPR
|
| RECORD_EXPR
|
||||||
| REF_EXPR
|
| REF_EXPR
|
||||||
| RETURN_EXPR
|
| RETURN_EXPR
|
||||||
|
| BECOME_EXPR
|
||||||
| TRY_EXPR
|
| TRY_EXPR
|
||||||
| TUPLE_EXPR
|
| TUPLE_EXPR
|
||||||
| WHILE_EXPR
|
| WHILE_EXPR
|
||||||
@ -3632,6 +3658,7 @@ fn cast(syntax: SyntaxNode) -> Option<Self> {
|
|||||||
RECORD_EXPR => Expr::RecordExpr(RecordExpr { syntax }),
|
RECORD_EXPR => Expr::RecordExpr(RecordExpr { syntax }),
|
||||||
REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
|
REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
|
||||||
RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }),
|
RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }),
|
||||||
|
BECOME_EXPR => Expr::BecomeExpr(BecomeExpr { syntax }),
|
||||||
TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
|
TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
|
||||||
TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }),
|
TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }),
|
||||||
WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }),
|
WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }),
|
||||||
@ -3673,6 +3700,7 @@ fn syntax(&self) -> &SyntaxNode {
|
|||||||
Expr::RecordExpr(it) => &it.syntax,
|
Expr::RecordExpr(it) => &it.syntax,
|
||||||
Expr::RefExpr(it) => &it.syntax,
|
Expr::RefExpr(it) => &it.syntax,
|
||||||
Expr::ReturnExpr(it) => &it.syntax,
|
Expr::ReturnExpr(it) => &it.syntax,
|
||||||
|
Expr::BecomeExpr(it) => &it.syntax,
|
||||||
Expr::TryExpr(it) => &it.syntax,
|
Expr::TryExpr(it) => &it.syntax,
|
||||||
Expr::TupleExpr(it) => &it.syntax,
|
Expr::TupleExpr(it) => &it.syntax,
|
||||||
Expr::WhileExpr(it) => &it.syntax,
|
Expr::WhileExpr(it) => &it.syntax,
|
||||||
@ -4150,6 +4178,7 @@ fn can_cast(kind: SyntaxKind) -> bool {
|
|||||||
| RANGE_EXPR
|
| RANGE_EXPR
|
||||||
| REF_EXPR
|
| REF_EXPR
|
||||||
| RETURN_EXPR
|
| RETURN_EXPR
|
||||||
|
| BECOME_EXPR
|
||||||
| TRY_EXPR
|
| TRY_EXPR
|
||||||
| TUPLE_EXPR
|
| TUPLE_EXPR
|
||||||
| WHILE_EXPR
|
| WHILE_EXPR
|
||||||
@ -4851,6 +4880,11 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl std::fmt::Display for BecomeExpr {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl std::fmt::Display for TryExpr {
|
impl std::fmt::Display for TryExpr {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
@ -130,8 +130,8 @@ fn binding_power(&self) -> (u8, u8) {
|
|||||||
//
|
//
|
||||||
ContinueExpr(_) => (0, 0),
|
ContinueExpr(_) => (0, 0),
|
||||||
|
|
||||||
ClosureExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_) | BreakExpr(_)
|
ClosureExpr(_) | ReturnExpr(_) | BecomeExpr(_) | YieldExpr(_) | YeetExpr(_)
|
||||||
| OffsetOfExpr(_) | FormatArgsExpr(_) | AsmExpr(_) => (0, 1),
|
| BreakExpr(_) | OffsetOfExpr(_) | FormatArgsExpr(_) | AsmExpr(_) => (0, 1),
|
||||||
|
|
||||||
RangeExpr(_) => (5, 5),
|
RangeExpr(_) => (5, 5),
|
||||||
|
|
||||||
@ -288,6 +288,7 @@ fn order(this: &Expr) -> rowan::TextSize {
|
|||||||
PrefixExpr(e) => e.op_token(),
|
PrefixExpr(e) => e.op_token(),
|
||||||
RefExpr(e) => e.amp_token(),
|
RefExpr(e) => e.amp_token(),
|
||||||
ReturnExpr(e) => e.return_token(),
|
ReturnExpr(e) => e.return_token(),
|
||||||
|
BecomeExpr(e) => e.become_token(),
|
||||||
TryExpr(e) => e.question_mark_token(),
|
TryExpr(e) => e.question_mark_token(),
|
||||||
YieldExpr(e) => e.yield_token(),
|
YieldExpr(e) => e.yield_token(),
|
||||||
YeetExpr(e) => e.do_token(),
|
YeetExpr(e) => e.do_token(),
|
||||||
@ -316,7 +317,8 @@ fn child_is_followed_by_a_block(&self) -> bool {
|
|||||||
|
|
||||||
// For BinExpr and RangeExpr this is technically wrong -- the child can be on the left...
|
// For BinExpr and RangeExpr this is technically wrong -- the child can be on the left...
|
||||||
BinExpr(_) | RangeExpr(_) | BreakExpr(_) | ContinueExpr(_) | PrefixExpr(_)
|
BinExpr(_) | RangeExpr(_) | BreakExpr(_) | ContinueExpr(_) | PrefixExpr(_)
|
||||||
| RefExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_) | LetExpr(_) => self
|
| RefExpr(_) | ReturnExpr(_) | BecomeExpr(_) | YieldExpr(_) | YeetExpr(_)
|
||||||
|
| LetExpr(_) => self
|
||||||
.syntax()
|
.syntax()
|
||||||
.parent()
|
.parent()
|
||||||
.and_then(Expr::cast)
|
.and_then(Expr::cast)
|
||||||
|
@ -67,8 +67,9 @@ pub(crate) struct KindsSrc<'a> {
|
|||||||
keywords: &[
|
keywords: &[
|
||||||
"as", "async", "await", "box", "break", "const", "continue", "crate", "do", "dyn", "else",
|
"as", "async", "await", "box", "break", "const", "continue", "crate", "do", "dyn", "else",
|
||||||
"enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "macro",
|
"enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "macro",
|
||||||
"match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct",
|
"match", "mod", "move", "mut", "pub", "ref", "return", "become", "self", "Self", "static",
|
||||||
"super", "trait", "true", "try", "type", "unsafe", "use", "where", "while", "yield",
|
"struct", "super", "trait", "true", "try", "type", "unsafe", "use", "where", "while",
|
||||||
|
"yield",
|
||||||
],
|
],
|
||||||
contextual_keywords: &[
|
contextual_keywords: &[
|
||||||
"auto",
|
"auto",
|
||||||
@ -154,6 +155,7 @@ pub(crate) struct KindsSrc<'a> {
|
|||||||
"BLOCK_EXPR",
|
"BLOCK_EXPR",
|
||||||
"STMT_LIST",
|
"STMT_LIST",
|
||||||
"RETURN_EXPR",
|
"RETURN_EXPR",
|
||||||
|
"BECOME_EXPR",
|
||||||
"YIELD_EXPR",
|
"YIELD_EXPR",
|
||||||
"YEET_EXPR",
|
"YEET_EXPR",
|
||||||
"LET_EXPR",
|
"LET_EXPR",
|
||||||
|
Loading…
Reference in New Issue
Block a user