Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/body/lower.rs4
-rw-r--r--crates/hir-def/src/body/pretty.rs9
-rw-r--r--crates/hir-def/src/expr.rs8
-rw-r--r--crates/hir-ty/src/infer/expr.rs6
-rw-r--r--crates/ide-db/src/syntax_helpers/node_ext.rs3
-rw-r--r--crates/ide/src/signature_help.rs2
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs1
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs20
-rw-r--r--crates/parser/src/parser.rs7
-rw-r--r--crates/parser/src/syntax_kind/generated.rs9
-rw-r--r--crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rast31
-rw-r--r--crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rs4
-rw-r--r--crates/syntax/rust.ungram4
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs35
-rw-r--r--crates/syntax/src/ast/prec.rs6
-rw-r--r--crates/syntax/src/tests/ast_src.rs5
16 files changed, 145 insertions, 9 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index ccc01c3efc..e8da24e3ad 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 04279751f0..10b9b26bbe 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 1626465502..3066213ace 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<ExprId>,
},
+ Yeet {
+ expr: Option<ExprId>,
+ },
RecordLit {
path: Option<Box<Path>>,
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 d4050f9af4..53fc7a5949 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -474,6 +474,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 39710b8f13..347e87ce97 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 6045a787ec..f807ba30f4 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 e7d0a8be7f..a06c6abf28 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::<ast::YeetExpr>(&token) => h | HlMod::ControlFlow,
T![for] if parent_matches::<ast::ForExpr>(&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 81027a7bf3..efa3997353 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 30bd0b3b16..48aecb35be 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 c84f45f1f8..52b3fc23d5 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 0000000000..24931bfcd7
--- /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 0000000000..624f86c9dc
--- /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 0a0cb0290d..2c67586a39 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 2ea715f47f..86d222723d 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -1064,6 +1064,17 @@ impl YieldExpr {
}
#[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<SyntaxToken> { support::token(&self.syntax, T![do]) }
+ pub fn yeet_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![yeet]) }
+ pub fn expr(&self) -> Option<Expr> { 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<Self> {
+ 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<Self> {
@@ -3382,6 +3405,9 @@ impl From<WhileExpr> for Expr {
impl From<YieldExpr> for Expr {
fn from(node: YieldExpr) -> Expr { Expr::YieldExpr(node) }
}
+impl From<YeetExpr> for Expr {
+ fn from(node: YeetExpr) -> Expr { Expr::YeetExpr(node) }
+}
impl From<LetExpr> 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 c118ef0635..4ec388914e 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 cf5be1c30f..3ff6e03006 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",