Auto merge of #13857 - WaffleLapkin:yeet, r=Veykril
feat: Implement yeeting See tracking issue: https://github.com/rust-lang/rust/issues/96373 Before: ![2022-12-29_03-19](https://user-images.githubusercontent.com/38225716/209884634-e34e98fb-615d-4954-9614-7f9ce6291678.png) After: ![2022-12-29_03-21](https://user-images.githubusercontent.com/38225716/209884633-4bba5eba-6dcc-4714-86cb-5c0d1f358364.png)
This commit is contained in:
commit
20b0ae4afe
@ -371,6 +371,10 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
|
||||
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);
|
||||
|
@ -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),
|
||||
|
@ -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 @@ 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);
|
||||
}
|
||||
|
@ -474,6 +474,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 {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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##"
|
||||
|
@ -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(),
|
||||
|
@ -48,6 +48,7 @@ pub(crate) fn literal(p: &mut Parser<'_>) -> Option<CompletedMarker> {
|
||||
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 {
|
||||
|
@ -148,11 +148,16 @@ pub(crate) fn at_ts(&self, kinds: TokenSet) -> bool {
|
||||
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.
|
||||
|
File diff suppressed because one or more lines are too long
31
crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rast
Normal file
31
crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rast
Normal file
@ -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"
|
@ -0,0 +1,4 @@
|
||||
fn foo() {
|
||||
do yeet;
|
||||
do yeet 1
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -1063,6 +1063,17 @@ pub fn yield_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax,
|
||||
pub fn expr(&self) -> Option<Expr> { 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<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 @@ fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
}
|
||||
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 @@ fn from(node: WhileExpr) -> Expr { Expr::WhileExpr(node) }
|
||||
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 @@ 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<Self> {
|
||||
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)
|
||||
|
@ -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)
|
||||
|
@ -65,12 +65,12 @@ pub(crate) struct KindsSrc<'a> {
|
||||
(">>=", "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) struct KindsSrc<'a> {
|
||||
"STMT_LIST",
|
||||
"RETURN_EXPR",
|
||||
"YIELD_EXPR",
|
||||
"YEET_EXPR",
|
||||
"LET_EXPR",
|
||||
"UNDERSCORE_EXPR",
|
||||
"MACRO_EXPR",
|
||||
|
Loading…
Reference in New Issue
Block a user