diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index ccc01c3efca5..e8da24e3adda 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -371,6 +371,10 @@ impl ExprCollector<'_> { 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 04279751f0c8..10b9b26bbeaa 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -247,6 +247,15 @@ impl<'a> Printer<'a> { 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 162646550207..3066213ace8e 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 @@ impl Expr { 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 b1f4de826077..8070655cab5c 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -465,6 +465,12 @@ impl<'a> InferenceContext<'a> { 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 39710b8f13eb..347e87ce9720 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/signature_help.rs b/crates/ide/src/signature_help.rs index 6045a787ecc2..f807ba30f40a 100644 --- a/crates/ide/src/signature_help.rs +++ b/crates/ide/src/signature_help.rs @@ -646,7 +646,7 @@ pub fn add_one(x: i32) -> i32 { x + 1 } -pub fn do() { +pub fn r#do() { add_one($0 }"#, expect![[r##" diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index e7d0a8be7f57..a06c6abf286e 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/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs index 81027a7bf33d..efa3997353bf 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs @@ -48,6 +48,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = T![unsafe], T![return], T![yield], + T![do], T![break], T![continue], T![async], @@ -93,6 +94,7 @@ pub(super) fn atom_expr( T![match] => match_expr(p), T![return] => return_expr(p), T![yield] => yield_expr(p), + T![do] if p.nth_at_contextual_kw(1, T![yeet]) => yeet_expr(p), T![continue] => continue_expr(p), T![break] => break_expr(p, r), @@ -533,6 +535,7 @@ fn return_expr(p: &mut Parser<'_>) -> CompletedMarker { } m.complete(p, RETURN_EXPR) } + // test yield_expr // fn foo() { // yield; @@ -548,6 +551,23 @@ fn yield_expr(p: &mut Parser<'_>) -> CompletedMarker { m.complete(p, YIELD_EXPR) } +// test yeet_expr +// fn foo() { +// do yeet; +// do yeet 1 +// } +fn yeet_expr(p: &mut Parser<'_>) -> CompletedMarker { + assert!(p.at(T![do])); + assert!(p.nth_at_contextual_kw(1, T![yeet])); + let m = p.start(); + p.bump(T![do]); + p.bump_remap(T![yeet]); + if p.at_ts(EXPR_FIRST) { + expr(p); + } + m.complete(p, YEET_EXPR) +} + // test continue_expr // fn foo() { // loop { diff --git a/crates/parser/src/parser.rs b/crates/parser/src/parser.rs index 30bd0b3b169e..48aecb35be12 100644 --- a/crates/parser/src/parser.rs +++ b/crates/parser/src/parser.rs @@ -148,11 +148,16 @@ impl<'t> Parser<'t> { kinds.contains(self.current()) } - /// Checks if the current token is contextual keyword with text `t`. + /// Checks if the current token is contextual keyword `kw`. pub(crate) fn at_contextual_kw(&self, kw: SyntaxKind) -> bool { self.inp.contextual_kind(self.pos) == kw } + /// Checks if the nth token is contextual keyword `kw`. + pub(crate) fn nth_at_contextual_kw(&self, n: usize, kw: SyntaxKind) -> bool { + self.inp.contextual_kind(self.pos + n) == kw + } + /// Starts a new node in the syntax tree. All nodes and tokens /// consumed between the `start` and the corresponding `Marker::complete` /// belong to the same node. diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs index c84f45f1f8e4..52b3fc23d59c 100644 --- a/crates/parser/src/syntax_kind/generated.rs +++ b/crates/parser/src/syntax_kind/generated.rs @@ -69,6 +69,7 @@ pub enum SyntaxKind { CONST_KW, CONTINUE_KW, CRATE_KW, + DO_KW, DYN_KW, ELSE_KW, ENUM_KW, @@ -109,6 +110,7 @@ pub enum SyntaxKind { UNION_KW, RAW_KW, MACRO_RULES_KW, + YEET_KW, INT_NUMBER, FLOAT_NUMBER, CHAR, @@ -188,6 +190,7 @@ pub enum SyntaxKind { STMT_LIST, RETURN_EXPR, YIELD_EXPR, + YEET_EXPR, LET_EXPR, UNDERSCORE_EXPR, MACRO_EXPR, @@ -272,6 +275,7 @@ impl SyntaxKind { | CONST_KW | CONTINUE_KW | CRATE_KW + | DO_KW | DYN_KW | ELSE_KW | ENUM_KW @@ -312,6 +316,7 @@ impl SyntaxKind { | UNION_KW | RAW_KW | MACRO_RULES_KW + | YEET_KW ) } pub fn is_punct(self) -> bool { @@ -384,6 +389,7 @@ impl SyntaxKind { "const" => CONST_KW, "continue" => CONTINUE_KW, "crate" => CRATE_KW, + "do" => DO_KW, "dyn" => DYN_KW, "else" => ELSE_KW, "enum" => ENUM_KW, @@ -430,6 +436,7 @@ impl SyntaxKind { "union" => UNION_KW, "raw" => RAW_KW, "macro_rules" => MACRO_RULES_KW, + "yeet" => YEET_KW, _ => return None, }; Some(kw) @@ -470,5 +477,5 @@ impl SyntaxKind { } } #[macro_export] -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 } ; [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 } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; } +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 } ; } pub use T; diff --git a/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rast b/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rast new file mode 100644 index 000000000000..24931bfcd7cd --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rast @@ -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 + YEET_EXPR + DO_KW "do" + WHITESPACE " " + YEET_KW "yeet" + SEMICOLON ";" + WHITESPACE "\n " + YEET_EXPR + DO_KW "do" + WHITESPACE " " + YEET_KW "yeet" + WHITESPACE " " + LITERAL + INT_NUMBER "1" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rs b/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rs new file mode 100644 index 000000000000..624f86c9dc0d --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rs @@ -0,0 +1,4 @@ +fn foo() { + do yeet; + do yeet 1 +} diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index 0a0cb0290d6c..2c67586a3905 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 2ea715f47fb2..86d222723d50 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -1063,6 +1063,17 @@ impl YieldExpr { 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 @@ impl AstNode for YieldExpr { } 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 @@ impl From for Expr { 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 @@ impl AstNode for Expr { | TUPLE_EXPR | WHILE_EXPR | YIELD_EXPR + | YEET_EXPR | LET_EXPR | UNDERSCORE_EXPR ) @@ -3458,6 +3485,7 @@ impl AstNode for Expr { 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 @@ impl AstNode for Expr { 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 @@ impl AstNode for AnyHasAttrs { | TUPLE_EXPR | WHILE_EXPR | YIELD_EXPR + | YEET_EXPR | LET_EXPR | UNDERSCORE_EXPR | STMT_LIST @@ -4655,6 +4685,11 @@ impl std::fmt::Display for YieldExpr { 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 c118ef063593..4ec388914e60 100644 --- a/crates/syntax/src/ast/prec.rs +++ b/crates/syntax/src/ast/prec.rs @@ -130,7 +130,7 @@ impl Expr { // ContinueExpr(_) => (0, 0), - ClosureExpr(_) | ReturnExpr(_) | YieldExpr(_) | BreakExpr(_) => (0, 1), + ClosureExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_) | BreakExpr(_) => (0, 1), RangeExpr(_) => (5, 5), @@ -291,6 +291,7 @@ impl Expr { 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 @@ impl Expr { // 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) diff --git a/crates/syntax/src/tests/ast_src.rs b/crates/syntax/src/tests/ast_src.rs index cf5be1c30fba..3ff6e03006b5 100644 --- a/crates/syntax/src/tests/ast_src.rs +++ b/crates/syntax/src/tests/ast_src.rs @@ -65,12 +65,12 @@ pub(crate) const KINDS_SRC: KindsSrc<'_> = KindsSrc { (">>=", "SHREQ"), ], keywords: &[ - "as", "async", "await", "box", "break", "const", "continue", "crate", "dyn", "else", + "as", "async", "await", "box", "break", "const", "continue", "crate", "do", "dyn", "else", "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct", "super", "trait", "true", "try", "type", "unsafe", "use", "where", "while", "yield", ], - contextual_keywords: &["auto", "default", "existential", "union", "raw", "macro_rules"], + contextual_keywords: &["auto", "default", "existential", "union", "raw", "macro_rules", "yeet"], literals: &["INT_NUMBER", "FLOAT_NUMBER", "CHAR", "BYTE", "STRING", "BYTE_STRING"], tokens: &["ERROR", "IDENT", "WHITESPACE", "LIFETIME_IDENT", "COMMENT", "SHEBANG"], nodes: &[ @@ -142,6 +142,7 @@ pub(crate) const KINDS_SRC: KindsSrc<'_> = KindsSrc { "STMT_LIST", "RETURN_EXPR", "YIELD_EXPR", + "YEET_EXPR", "LET_EXPR", "UNDERSCORE_EXPR", "MACRO_EXPR",