From 346bf5fb5b9ce94b7fa24d466ba82ec709f95286 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 28 Dec 2022 23:17:13 +0000 Subject: [PATCH] Implement `do yeet` expression --- crates/hir-def/src/body/lower.rs | 4 +++ crates/hir-def/src/body/pretty.rs | 9 +++++ crates/hir-def/src/expr.rs | 8 ++++- crates/hir-ty/src/infer/expr.rs | 6 ++++ crates/ide-db/src/syntax_helpers/node_ext.rs | 3 +- .../ide/src/syntax_highlighting/highlight.rs | 1 + crates/syntax/rust.ungram | 4 +++ crates/syntax/src/ast/generated/nodes.rs | 35 +++++++++++++++++++ crates/syntax/src/ast/prec.rs | 6 ++-- 9 files changed, 72 insertions(+), 4 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index ccc01c3efca..e8da24e3add 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -371,6 +371,10 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option { let expr = e.expr().map(|e| self.collect_expr(e)); self.alloc_expr(Expr::Yield { expr }, syntax_ptr) } + ast::Expr::YeetExpr(e) => { + let expr = e.expr().map(|e| self.collect_expr(e)); + self.alloc_expr(Expr::Yeet { expr }, syntax_ptr) + } ast::Expr::RecordExpr(e) => { let path = e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new); diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index 04279751f0c..10b9b26bbea 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -247,6 +247,15 @@ fn print_expr(&mut self, expr: ExprId) { self.print_expr(*expr); } } + Expr::Yeet { expr } => { + w!(self, "do"); + self.whitespace(); + w!(self, "yeet"); + if let Some(expr) = expr { + self.whitespace(); + self.print_expr(*expr); + } + } Expr::RecordLit { path, fields, spread, ellipsis, is_assignee_expr: _ } => { match path { Some(path) => self.print_path(path), diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs index 16264655020..3066213ace8 100644 --- a/crates/hir-def/src/expr.rs +++ b/crates/hir-def/src/expr.rs @@ -137,6 +137,9 @@ pub enum Expr { Yield { expr: Option, }, + Yeet { + expr: Option, + }, RecordLit { path: Option>, fields: Box<[RecordLitField]>, @@ -313,7 +316,10 @@ pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) { arms.iter().map(|arm| arm.expr).for_each(f); } Expr::Continue { .. } => {} - Expr::Break { expr, .. } | Expr::Return { expr } | Expr::Yield { expr } => { + Expr::Break { expr, .. } + | Expr::Return { expr } + | Expr::Yield { expr } + | Expr::Yeet { expr } => { if let &Some(expr) = expr { f(expr); } diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index b1f4de82607..8070655cab5 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -465,6 +465,12 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { TyKind::Error.intern(Interner) } } + Expr::Yeet { expr } => { + if let &Some(expr) = expr { + self.infer_expr_inner(expr, &Expectation::None); + } + TyKind::Never.intern(Interner) + } Expr::RecordLit { path, fields, spread, .. } => { let (ty, def_id) = self.resolve_variant(path.as_deref(), false); if let Some(variant) = def_id { diff --git a/crates/ide-db/src/syntax_helpers/node_ext.rs b/crates/ide-db/src/syntax_helpers/node_ext.rs index 39710b8f13e..347e87ce972 100644 --- a/crates/ide-db/src/syntax_helpers/node_ext.rs +++ b/crates/ide-db/src/syntax_helpers/node_ext.rs @@ -328,7 +328,8 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) { | ast::Expr::WhileExpr(_) | ast::Expr::LetExpr(_) | ast::Expr::UnderscoreExpr(_) - | ast::Expr::YieldExpr(_) => cb(expr), + | ast::Expr::YieldExpr(_) + | ast::Expr::YeetExpr(_) => cb(expr), } } diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index e7d0a8be7f5..a06c6abf286 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -174,6 +174,7 @@ fn keyword( | T![return] | T![while] | T![yield] => h | HlMod::ControlFlow, + T![do] | T![yeet] if parent_matches::(&token) => h | HlMod::ControlFlow, T![for] if parent_matches::(&token) => h | HlMod::ControlFlow, T![unsafe] => h | HlMod::Unsafe, T![true] | T![false] => HlTag::BoolLiteral.into(), diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index 0a0cb0290d6..2c67586a390 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -359,6 +359,7 @@ Expr = | TupleExpr | WhileExpr | YieldExpr +| YeetExpr | LetExpr | UnderscoreExpr @@ -503,6 +504,9 @@ ReturnExpr = YieldExpr = Attr* 'yield' Expr? +YeetExpr = + Attr* 'do' 'yeet' Expr? + LetExpr = Attr* 'let' Pat '=' Expr diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 2ea715f47fb..86d222723d5 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -1063,6 +1063,17 @@ pub fn yield_token(&self) -> Option { support::token(&self.syntax, pub fn expr(&self) -> Option { support::child(&self.syntax) } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct YeetExpr { + pub(crate) syntax: SyntaxNode, +} +impl ast::HasAttrs for YeetExpr {} +impl YeetExpr { + pub fn do_token(&self) -> Option { support::token(&self.syntax, T![do]) } + pub fn yeet_token(&self) -> Option { support::token(&self.syntax, T![yeet]) } + pub fn expr(&self) -> Option { support::child(&self.syntax) } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LetExpr { pub(crate) syntax: SyntaxNode, @@ -1541,6 +1552,7 @@ pub enum Expr { TupleExpr(TupleExpr), WhileExpr(WhileExpr), YieldExpr(YieldExpr), + YeetExpr(YeetExpr), LetExpr(LetExpr), UnderscoreExpr(UnderscoreExpr), } @@ -2694,6 +2706,17 @@ fn cast(syntax: SyntaxNode) -> Option { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for YeetExpr { + fn can_cast(kind: SyntaxKind) -> bool { kind == YEET_EXPR } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} impl AstNode for LetExpr { fn can_cast(kind: SyntaxKind) -> bool { kind == LET_EXPR } fn cast(syntax: SyntaxNode) -> Option { @@ -3382,6 +3405,9 @@ fn from(node: WhileExpr) -> Expr { Expr::WhileExpr(node) } impl From for Expr { fn from(node: YieldExpr) -> Expr { Expr::YieldExpr(node) } } +impl From for Expr { + fn from(node: YeetExpr) -> Expr { Expr::YeetExpr(node) } +} impl From for Expr { fn from(node: LetExpr) -> Expr { Expr::LetExpr(node) } } @@ -3422,6 +3448,7 @@ fn can_cast(kind: SyntaxKind) -> bool { | TUPLE_EXPR | WHILE_EXPR | YIELD_EXPR + | YEET_EXPR | LET_EXPR | UNDERSCORE_EXPR ) @@ -3458,6 +3485,7 @@ fn cast(syntax: SyntaxNode) -> Option { TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }), WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }), YIELD_EXPR => Expr::YieldExpr(YieldExpr { syntax }), + YEET_EXPR => Expr::YeetExpr(YeetExpr { syntax }), LET_EXPR => Expr::LetExpr(LetExpr { syntax }), UNDERSCORE_EXPR => Expr::UnderscoreExpr(UnderscoreExpr { syntax }), _ => return None, @@ -3496,6 +3524,7 @@ fn syntax(&self) -> &SyntaxNode { Expr::TupleExpr(it) => &it.syntax, Expr::WhileExpr(it) => &it.syntax, Expr::YieldExpr(it) => &it.syntax, + Expr::YeetExpr(it) => &it.syntax, Expr::LetExpr(it) => &it.syntax, Expr::UnderscoreExpr(it) => &it.syntax, } @@ -3963,6 +3992,7 @@ fn can_cast(kind: SyntaxKind) -> bool { | TUPLE_EXPR | WHILE_EXPR | YIELD_EXPR + | YEET_EXPR | LET_EXPR | UNDERSCORE_EXPR | STMT_LIST @@ -4655,6 +4685,11 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for YeetExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for LetExpr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/crates/syntax/src/ast/prec.rs b/crates/syntax/src/ast/prec.rs index c118ef06359..4ec388914e6 100644 --- a/crates/syntax/src/ast/prec.rs +++ b/crates/syntax/src/ast/prec.rs @@ -130,7 +130,7 @@ fn binding_power(&self) -> (u8, u8) { // ContinueExpr(_) => (0, 0), - ClosureExpr(_) | ReturnExpr(_) | YieldExpr(_) | BreakExpr(_) => (0, 1), + ClosureExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_) | BreakExpr(_) => (0, 1), RangeExpr(_) => (5, 5), @@ -291,6 +291,7 @@ fn order(this: &Expr) -> rowan::TextSize { ReturnExpr(e) => e.return_token(), TryExpr(e) => e.question_mark_token(), YieldExpr(e) => e.yield_token(), + YeetExpr(e) => e.do_token(), LetExpr(e) => e.let_token(), ArrayExpr(_) | TupleExpr(_) | Literal(_) | PathExpr(_) | ParenExpr(_) @@ -313,7 +314,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... BinExpr(_) | RangeExpr(_) | BoxExpr(_) | BreakExpr(_) | ContinueExpr(_) - | PrefixExpr(_) | RefExpr(_) | ReturnExpr(_) | YieldExpr(_) | LetExpr(_) => self + | PrefixExpr(_) | RefExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_) + | LetExpr(_) => self .syntax() .parent() .and_then(Expr::cast) -- 2.44.0