Merge #1380
1380: [#1083] Try block syntax r=matklad a=andreytkachenko The `try` block syntax Co-authored-by: Andrey Tkachenko <andreytkachenko64@gmail.com>
This commit is contained in:
commit
ba31481599
@ -6,7 +6,7 @@ use rustc_hash::FxHashMap;
|
|||||||
use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
|
use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
SyntaxNodePtr, AstPtr, AstNode,
|
SyntaxNodePtr, AstPtr, AstNode,
|
||||||
ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralKind,ArrayExprKind, TypeAscriptionOwner},
|
ast::{self, TryBlockBodyOwner, LoopBodyOwner, ArgListOwner, NameOwner, LiteralKind,ArrayExprKind, TypeAscriptionOwner},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -216,6 +216,9 @@ pub enum Expr {
|
|||||||
Try {
|
Try {
|
||||||
expr: ExprId,
|
expr: ExprId,
|
||||||
},
|
},
|
||||||
|
TryBlock {
|
||||||
|
body: ExprId,
|
||||||
|
},
|
||||||
Cast {
|
Cast {
|
||||||
expr: ExprId,
|
expr: ExprId,
|
||||||
type_ref: TypeRef,
|
type_ref: TypeRef,
|
||||||
@ -299,6 +302,7 @@ impl Expr {
|
|||||||
f(*expr);
|
f(*expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::TryBlock { body } => f(*body),
|
||||||
Expr::Loop { body } => f(*body),
|
Expr::Loop { body } => f(*body),
|
||||||
Expr::While { condition, body } => {
|
Expr::While { condition, body } => {
|
||||||
f(*condition);
|
f(*condition);
|
||||||
@ -578,6 +582,10 @@ where
|
|||||||
self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
|
self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::ExprKind::TryBlockExpr(e) => {
|
||||||
|
let body = self.collect_block_opt(e.try_body());
|
||||||
|
self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
|
||||||
|
}
|
||||||
ast::ExprKind::BlockExpr(e) => self.collect_block_opt(e.block()),
|
ast::ExprKind::BlockExpr(e) => self.collect_block_opt(e.block()),
|
||||||
ast::ExprKind::LoopExpr(e) => {
|
ast::ExprKind::LoopExpr(e) => {
|
||||||
let body = self.collect_block_opt(e.loop_body());
|
let body = self.collect_block_opt(e.loop_body());
|
||||||
|
@ -946,6 +946,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
then_ty
|
then_ty
|
||||||
}
|
}
|
||||||
Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
|
Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
|
||||||
|
Expr::TryBlock { body } => {
|
||||||
|
let _inner = self.infer_expr(*body, expected);
|
||||||
|
// FIXME should be std::result::Result<{inner}, _>
|
||||||
|
Ty::Unknown
|
||||||
|
}
|
||||||
Expr::Loop { body } => {
|
Expr::Loop { body } => {
|
||||||
self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
|
self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
|
||||||
// FIXME handle break with value
|
// FIXME handle break with value
|
||||||
|
@ -52,6 +52,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
|
|||||||
CONTINUE_KW,
|
CONTINUE_KW,
|
||||||
LIFETIME,
|
LIFETIME,
|
||||||
ASYNC_KW,
|
ASYNC_KW,
|
||||||
|
TRY_KW,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW];
|
const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW];
|
||||||
@ -75,6 +76,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
|
|||||||
T![loop] => loop_expr(p, None),
|
T![loop] => loop_expr(p, None),
|
||||||
T![for] => for_expr(p, None),
|
T![for] => for_expr(p, None),
|
||||||
T![while] => while_expr(p, None),
|
T![while] => while_expr(p, None),
|
||||||
|
T![try] => try_block_expr(p, None),
|
||||||
LIFETIME if la == T![:] => {
|
LIFETIME if la == T![:] => {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
label(p);
|
label(p);
|
||||||
@ -116,7 +118,9 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let blocklike = match done.kind() {
|
let blocklike = match done.kind() {
|
||||||
IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => BlockLike::Block,
|
IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_BLOCK_EXPR => {
|
||||||
|
BlockLike::Block
|
||||||
|
}
|
||||||
_ => BlockLike::NotBlock,
|
_ => BlockLike::NotBlock,
|
||||||
};
|
};
|
||||||
Some((done, blocklike))
|
Some((done, blocklike))
|
||||||
@ -491,3 +495,15 @@ fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
|
|||||||
}
|
}
|
||||||
m.complete(p, BREAK_EXPR)
|
m.complete(p, BREAK_EXPR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test try_block_expr
|
||||||
|
// fn foo() {
|
||||||
|
// let _ = try {};
|
||||||
|
// }
|
||||||
|
fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
|
||||||
|
assert!(p.at(T![try]));
|
||||||
|
let m = m.unwrap_or_else(|| p.start());
|
||||||
|
p.bump();
|
||||||
|
block(p);
|
||||||
|
m.complete(p, TRY_EXPR)
|
||||||
|
}
|
||||||
|
@ -103,6 +103,7 @@ pub enum SyntaxKind {
|
|||||||
LET_KW,
|
LET_KW,
|
||||||
MOVE_KW,
|
MOVE_KW,
|
||||||
RETURN_KW,
|
RETURN_KW,
|
||||||
|
TRY_KW,
|
||||||
AUTO_KW,
|
AUTO_KW,
|
||||||
DEFAULT_KW,
|
DEFAULT_KW,
|
||||||
UNION_KW,
|
UNION_KW,
|
||||||
@ -184,6 +185,7 @@ pub enum SyntaxKind {
|
|||||||
STRUCT_LIT,
|
STRUCT_LIT,
|
||||||
NAMED_FIELD_LIST,
|
NAMED_FIELD_LIST,
|
||||||
NAMED_FIELD,
|
NAMED_FIELD,
|
||||||
|
TRY_BLOCK_EXPR,
|
||||||
CALL_EXPR,
|
CALL_EXPR,
|
||||||
INDEX_EXPR,
|
INDEX_EXPR,
|
||||||
METHOD_CALL_EXPR,
|
METHOD_CALL_EXPR,
|
||||||
@ -331,6 +333,7 @@ macro_rules! T {
|
|||||||
(let) => { $crate::SyntaxKind::LET_KW };
|
(let) => { $crate::SyntaxKind::LET_KW };
|
||||||
(move) => { $crate::SyntaxKind::MOVE_KW };
|
(move) => { $crate::SyntaxKind::MOVE_KW };
|
||||||
(return) => { $crate::SyntaxKind::RETURN_KW };
|
(return) => { $crate::SyntaxKind::RETURN_KW };
|
||||||
|
(try) => { $crate::SyntaxKind::TRY_KW };
|
||||||
(auto) => { $crate::SyntaxKind::AUTO_KW };
|
(auto) => { $crate::SyntaxKind::AUTO_KW };
|
||||||
(default) => { $crate::SyntaxKind::DEFAULT_KW };
|
(default) => { $crate::SyntaxKind::DEFAULT_KW };
|
||||||
(union) => { $crate::SyntaxKind::UNION_KW };
|
(union) => { $crate::SyntaxKind::UNION_KW };
|
||||||
@ -388,6 +391,7 @@ impl SyntaxKind {
|
|||||||
| LET_KW
|
| LET_KW
|
||||||
| MOVE_KW
|
| MOVE_KW
|
||||||
| RETURN_KW
|
| RETURN_KW
|
||||||
|
| TRY_KW
|
||||||
| AUTO_KW
|
| AUTO_KW
|
||||||
| DEFAULT_KW
|
| DEFAULT_KW
|
||||||
| UNION_KW
|
| UNION_KW
|
||||||
@ -559,6 +563,7 @@ impl SyntaxKind {
|
|||||||
LET_KW => &SyntaxInfo { name: "LET_KW" },
|
LET_KW => &SyntaxInfo { name: "LET_KW" },
|
||||||
MOVE_KW => &SyntaxInfo { name: "MOVE_KW" },
|
MOVE_KW => &SyntaxInfo { name: "MOVE_KW" },
|
||||||
RETURN_KW => &SyntaxInfo { name: "RETURN_KW" },
|
RETURN_KW => &SyntaxInfo { name: "RETURN_KW" },
|
||||||
|
TRY_KW => &SyntaxInfo { name: "TRY_KW" },
|
||||||
AUTO_KW => &SyntaxInfo { name: "AUTO_KW" },
|
AUTO_KW => &SyntaxInfo { name: "AUTO_KW" },
|
||||||
DEFAULT_KW => &SyntaxInfo { name: "DEFAULT_KW" },
|
DEFAULT_KW => &SyntaxInfo { name: "DEFAULT_KW" },
|
||||||
UNION_KW => &SyntaxInfo { name: "UNION_KW" },
|
UNION_KW => &SyntaxInfo { name: "UNION_KW" },
|
||||||
@ -640,6 +645,7 @@ impl SyntaxKind {
|
|||||||
STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" },
|
STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" },
|
||||||
NAMED_FIELD_LIST => &SyntaxInfo { name: "NAMED_FIELD_LIST" },
|
NAMED_FIELD_LIST => &SyntaxInfo { name: "NAMED_FIELD_LIST" },
|
||||||
NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
|
NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
|
||||||
|
TRY_BLOCK_EXPR => &SyntaxInfo { name: "TRY_BLOCK_EXPR" },
|
||||||
CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" },
|
CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" },
|
||||||
INDEX_EXPR => &SyntaxInfo { name: "INDEX_EXPR" },
|
INDEX_EXPR => &SyntaxInfo { name: "INDEX_EXPR" },
|
||||||
METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" },
|
METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" },
|
||||||
@ -734,6 +740,7 @@ impl SyntaxKind {
|
|||||||
"let" => LET_KW,
|
"let" => LET_KW,
|
||||||
"move" => MOVE_KW,
|
"move" => MOVE_KW,
|
||||||
"return" => RETURN_KW,
|
"return" => RETURN_KW,
|
||||||
|
"try" => TRY_KW,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(kw)
|
Some(kw)
|
||||||
|
@ -713,6 +713,7 @@ pub enum ExprKind<'a> {
|
|||||||
MethodCallExpr(&'a MethodCallExpr),
|
MethodCallExpr(&'a MethodCallExpr),
|
||||||
FieldExpr(&'a FieldExpr),
|
FieldExpr(&'a FieldExpr),
|
||||||
TryExpr(&'a TryExpr),
|
TryExpr(&'a TryExpr),
|
||||||
|
TryBlockExpr(&'a TryBlockExpr),
|
||||||
CastExpr(&'a CastExpr),
|
CastExpr(&'a CastExpr),
|
||||||
RefExpr(&'a RefExpr),
|
RefExpr(&'a RefExpr),
|
||||||
PrefixExpr(&'a PrefixExpr),
|
PrefixExpr(&'a PrefixExpr),
|
||||||
@ -826,6 +827,11 @@ impl<'a> From<&'a TryExpr> for &'a Expr {
|
|||||||
Expr::cast(&n.syntax).unwrap()
|
Expr::cast(&n.syntax).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'a> From<&'a TryBlockExpr> for &'a Expr {
|
||||||
|
fn from(n: &'a TryBlockExpr) -> &'a Expr {
|
||||||
|
Expr::cast(&n.syntax).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
impl<'a> From<&'a CastExpr> for &'a Expr {
|
impl<'a> From<&'a CastExpr> for &'a Expr {
|
||||||
fn from(n: &'a CastExpr) -> &'a Expr {
|
fn from(n: &'a CastExpr) -> &'a Expr {
|
||||||
Expr::cast(&n.syntax).unwrap()
|
Expr::cast(&n.syntax).unwrap()
|
||||||
@ -887,6 +893,7 @@ impl AstNode for Expr {
|
|||||||
| METHOD_CALL_EXPR
|
| METHOD_CALL_EXPR
|
||||||
| FIELD_EXPR
|
| FIELD_EXPR
|
||||||
| TRY_EXPR
|
| TRY_EXPR
|
||||||
|
| TRY_BLOCK_EXPR
|
||||||
| CAST_EXPR
|
| CAST_EXPR
|
||||||
| REF_EXPR
|
| REF_EXPR
|
||||||
| PREFIX_EXPR
|
| PREFIX_EXPR
|
||||||
@ -929,6 +936,7 @@ impl Expr {
|
|||||||
METHOD_CALL_EXPR => ExprKind::MethodCallExpr(MethodCallExpr::cast(&self.syntax).unwrap()),
|
METHOD_CALL_EXPR => ExprKind::MethodCallExpr(MethodCallExpr::cast(&self.syntax).unwrap()),
|
||||||
FIELD_EXPR => ExprKind::FieldExpr(FieldExpr::cast(&self.syntax).unwrap()),
|
FIELD_EXPR => ExprKind::FieldExpr(FieldExpr::cast(&self.syntax).unwrap()),
|
||||||
TRY_EXPR => ExprKind::TryExpr(TryExpr::cast(&self.syntax).unwrap()),
|
TRY_EXPR => ExprKind::TryExpr(TryExpr::cast(&self.syntax).unwrap()),
|
||||||
|
TRY_BLOCK_EXPR => ExprKind::TryBlockExpr(TryBlockExpr::cast(&self.syntax).unwrap()),
|
||||||
CAST_EXPR => ExprKind::CastExpr(CastExpr::cast(&self.syntax).unwrap()),
|
CAST_EXPR => ExprKind::CastExpr(CastExpr::cast(&self.syntax).unwrap()),
|
||||||
REF_EXPR => ExprKind::RefExpr(RefExpr::cast(&self.syntax).unwrap()),
|
REF_EXPR => ExprKind::RefExpr(RefExpr::cast(&self.syntax).unwrap()),
|
||||||
PREFIX_EXPR => ExprKind::PrefixExpr(PrefixExpr::cast(&self.syntax).unwrap()),
|
PREFIX_EXPR => ExprKind::PrefixExpr(PrefixExpr::cast(&self.syntax).unwrap()),
|
||||||
@ -3672,6 +3680,35 @@ impl TraitDef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TryBlockExpr
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct TryBlockExpr {
|
||||||
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
}
|
||||||
|
unsafe impl TransparentNewType for TryBlockExpr {
|
||||||
|
type Repr = rowan::SyntaxNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AstNode for TryBlockExpr {
|
||||||
|
fn cast(syntax: &SyntaxNode) -> Option<&Self> {
|
||||||
|
match syntax.kind() {
|
||||||
|
TRY_BLOCK_EXPR => Some(TryBlockExpr::from_repr(syntax.into_repr())),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToOwned for TryBlockExpr {
|
||||||
|
type Owned = TreeArc<TryBlockExpr>;
|
||||||
|
fn to_owned(&self) -> TreeArc<TryBlockExpr> { TreeArc::cast(self.syntax.to_owned()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ast::TryBlockBodyOwner for TryBlockExpr {}
|
||||||
|
impl TryBlockExpr {}
|
||||||
|
|
||||||
// TryExpr
|
// TryExpr
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
@ -33,6 +33,12 @@ pub trait LoopBodyOwner: AstNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait TryBlockBodyOwner: AstNode {
|
||||||
|
fn try_body(&self) -> Option<&ast::Block> {
|
||||||
|
child_opt(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ArgListOwner: AstNode {
|
pub trait ArgListOwner: AstNode {
|
||||||
fn arg_list(&self) -> Option<&ast::ArgList> {
|
fn arg_list(&self) -> Option<&ast::ArgList> {
|
||||||
child_opt(self)
|
child_opt(self)
|
||||||
|
@ -95,6 +95,7 @@ Grammar(
|
|||||||
"let",
|
"let",
|
||||||
"move",
|
"move",
|
||||||
"return",
|
"return",
|
||||||
|
"try",
|
||||||
],
|
],
|
||||||
contextual_keywords: [
|
contextual_keywords: [
|
||||||
"auto",
|
"auto",
|
||||||
@ -189,6 +190,7 @@ Grammar(
|
|||||||
"STRUCT_LIT",
|
"STRUCT_LIT",
|
||||||
"NAMED_FIELD_LIST",
|
"NAMED_FIELD_LIST",
|
||||||
"NAMED_FIELD",
|
"NAMED_FIELD",
|
||||||
|
"TRY_BLOCK_EXPR",
|
||||||
|
|
||||||
// postfix
|
// postfix
|
||||||
"CALL_EXPR",
|
"CALL_EXPR",
|
||||||
@ -417,6 +419,9 @@ Grammar(
|
|||||||
"LoopExpr": (
|
"LoopExpr": (
|
||||||
traits: ["LoopBodyOwner"],
|
traits: ["LoopBodyOwner"],
|
||||||
),
|
),
|
||||||
|
"TryBlockExpr": (
|
||||||
|
traits: ["TryBlockBodyOwner"],
|
||||||
|
),
|
||||||
"ForExpr": (
|
"ForExpr": (
|
||||||
traits: ["LoopBodyOwner"],
|
traits: ["LoopBodyOwner"],
|
||||||
options: [
|
options: [
|
||||||
@ -499,6 +504,7 @@ Grammar(
|
|||||||
"MethodCallExpr",
|
"MethodCallExpr",
|
||||||
"FieldExpr",
|
"FieldExpr",
|
||||||
"TryExpr",
|
"TryExpr",
|
||||||
|
"TryBlockExpr",
|
||||||
"CastExpr",
|
"CastExpr",
|
||||||
"RefExpr",
|
"RefExpr",
|
||||||
"PrefixExpr",
|
"PrefixExpr",
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
fn foo() {
|
||||||
|
let _ = try {};
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
SOURCE_FILE@[0; 33)
|
||||||
|
FN_DEF@[0; 32)
|
||||||
|
FN_KW@[0; 2) "fn"
|
||||||
|
WHITESPACE@[2; 3) " "
|
||||||
|
NAME@[3; 6)
|
||||||
|
IDENT@[3; 6) "foo"
|
||||||
|
PARAM_LIST@[6; 8)
|
||||||
|
L_PAREN@[6; 7) "("
|
||||||
|
R_PAREN@[7; 8) ")"
|
||||||
|
WHITESPACE@[8; 9) " "
|
||||||
|
BLOCK@[9; 32)
|
||||||
|
L_CURLY@[9; 10) "{"
|
||||||
|
WHITESPACE@[10; 15) "\n "
|
||||||
|
LET_STMT@[15; 30)
|
||||||
|
LET_KW@[15; 18) "let"
|
||||||
|
WHITESPACE@[18; 19) " "
|
||||||
|
PLACEHOLDER_PAT@[19; 20)
|
||||||
|
UNDERSCORE@[19; 20) "_"
|
||||||
|
WHITESPACE@[20; 21) " "
|
||||||
|
EQ@[21; 22) "="
|
||||||
|
WHITESPACE@[22; 23) " "
|
||||||
|
TRY_EXPR@[23; 29)
|
||||||
|
TRY_KW@[23; 26) "try"
|
||||||
|
WHITESPACE@[26; 27) " "
|
||||||
|
BLOCK@[27; 29)
|
||||||
|
L_CURLY@[27; 28) "{"
|
||||||
|
R_CURLY@[28; 29) "}"
|
||||||
|
SEMI@[29; 30) ";"
|
||||||
|
WHITESPACE@[30; 31) "\n"
|
||||||
|
R_CURLY@[31; 32) "}"
|
||||||
|
WHITESPACE@[32; 33) "\n"
|
Loading…
x
Reference in New Issue
Block a user