From 281c9eeaff8eac4e666089f80f67cf684e1d001b Mon Sep 17 00:00:00 2001 From: Andrey Tkachenko Date: Thu, 6 Jun 2019 15:36:16 +0400 Subject: [#1083] Try block syntax --- crates/ra_hir/src/expr.rs | 10 +++++- crates/ra_hir/src/ty/infer.rs | 6 ++++ crates/ra_parser/src/grammar/expressions/atom.rs | 18 ++++++++++- crates/ra_parser/src/syntax_kind/generated.rs | 7 ++++ crates/ra_syntax/src/ast/generated.rs | 37 ++++++++++++++++++++++ crates/ra_syntax/src/ast/traits.rs | 6 ++++ crates/ra_syntax/src/grammar.ron | 6 ++++ .../tests/data/parser/ok/0051_try_block.rs | 5 +++ .../tests/data/parser/ok/0051_try_block.txt | 32 +++++++++++++++++++ 9 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 crates/ra_syntax/tests/data/parser/ok/0051_try_block.rs create mode 100644 crates/ra_syntax/tests/data/parser/ok/0051_try_block.txt (limited to 'crates') diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 51913d37b..9d9769859 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -6,7 +6,7 @@ use rustc_hash::FxHashMap; use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; use ra_syntax::{ SyntaxNodePtr, AstPtr, AstNode, - ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralKind,ArrayExprKind, TypeAscriptionOwner}, + ast::{self, TryBlockBodyOwner, LoopBodyOwner, ArgListOwner, NameOwner, LiteralKind,ArrayExprKind, TypeAscriptionOwner}, }; use crate::{ @@ -216,6 +216,9 @@ pub enum Expr { Try { expr: ExprId, }, + TryBlock { + body: ExprId, + }, Cast { expr: ExprId, type_ref: TypeRef, @@ -299,6 +302,7 @@ impl Expr { f(*expr); } } + Expr::TryBlock { body } => f(*body), Expr::Loop { body } => f(*body), Expr::While { condition, body } => { f(*condition); @@ -578,6 +582,10 @@ where 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::LoopExpr(e) => { let body = self.collect_block_opt(e.loop_body()); diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 905fe9f0e..579307d8a 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -946,6 +946,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { then_ty } 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 } => { self.infer_expr(*body, &Expectation::has_type(Ty::unit())); // FIXME handle break with value diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 8b1a1de49..0df47d33d 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -52,6 +52,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = CONTINUE_KW, LIFETIME, ASYNC_KW, + TRY_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![for] => for_expr(p, None), T![while] => while_expr(p, None), + T![try] => try_expr(p, None), LIFETIME if la == T![:] => { let m = p.start(); label(p); @@ -116,7 +118,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar } }; 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, }; Some((done, blocklike)) @@ -491,3 +493,17 @@ fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { } m.complete(p, BREAK_EXPR) } + +// test try_expr +// fn foo() { +// try { +// +// } +// } +fn try_expr(p: &mut Parser, m: Option) -> CompletedMarker { + assert!(p.at(T![try])); + let m = m.unwrap_or_else(|| p.start()); + p.bump(); + block(p); + m.complete(p, TRY_EXPR) +} diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index d7926bd91..2c021f3e9 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -103,6 +103,7 @@ pub enum SyntaxKind { LET_KW, MOVE_KW, RETURN_KW, + TRY_KW, AUTO_KW, DEFAULT_KW, UNION_KW, @@ -184,6 +185,7 @@ pub enum SyntaxKind { STRUCT_LIT, NAMED_FIELD_LIST, NAMED_FIELD, + TRY_BLOCK_EXPR, CALL_EXPR, INDEX_EXPR, METHOD_CALL_EXPR, @@ -331,6 +333,7 @@ macro_rules! T { (let) => { $crate::SyntaxKind::LET_KW }; (move) => { $crate::SyntaxKind::MOVE_KW }; (return) => { $crate::SyntaxKind::RETURN_KW }; + (try) => { $crate::SyntaxKind::TRY_KW }; (auto) => { $crate::SyntaxKind::AUTO_KW }; (default) => { $crate::SyntaxKind::DEFAULT_KW }; (union) => { $crate::SyntaxKind::UNION_KW }; @@ -388,6 +391,7 @@ impl SyntaxKind { | LET_KW | MOVE_KW | RETURN_KW + | TRY_KW | AUTO_KW | DEFAULT_KW | UNION_KW @@ -559,6 +563,7 @@ impl SyntaxKind { LET_KW => &SyntaxInfo { name: "LET_KW" }, MOVE_KW => &SyntaxInfo { name: "MOVE_KW" }, RETURN_KW => &SyntaxInfo { name: "RETURN_KW" }, + TRY_KW => &SyntaxInfo { name: "TRY_KW" }, AUTO_KW => &SyntaxInfo { name: "AUTO_KW" }, DEFAULT_KW => &SyntaxInfo { name: "DEFAULT_KW" }, UNION_KW => &SyntaxInfo { name: "UNION_KW" }, @@ -640,6 +645,7 @@ impl SyntaxKind { STRUCT_LIT => &SyntaxInfo { name: "STRUCT_LIT" }, NAMED_FIELD_LIST => &SyntaxInfo { name: "NAMED_FIELD_LIST" }, NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" }, + TRY_BLOCK_EXPR => &SyntaxInfo { name: "TRY_BLOCK_EXPR" }, CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" }, INDEX_EXPR => &SyntaxInfo { name: "INDEX_EXPR" }, METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" }, @@ -734,6 +740,7 @@ impl SyntaxKind { "let" => LET_KW, "move" => MOVE_KW, "return" => RETURN_KW, + "try" => TRY_KW, _ => return None, }; Some(kw) diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index e73fe22e9..1d888e709 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -713,6 +713,7 @@ pub enum ExprKind<'a> { MethodCallExpr(&'a MethodCallExpr), FieldExpr(&'a FieldExpr), TryExpr(&'a TryExpr), + TryBlockExpr(&'a TryBlockExpr), CastExpr(&'a CastExpr), RefExpr(&'a RefExpr), PrefixExpr(&'a PrefixExpr), @@ -826,6 +827,11 @@ impl<'a> From<&'a TryExpr> for &'a Expr { 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 { fn from(n: &'a CastExpr) -> &'a Expr { Expr::cast(&n.syntax).unwrap() @@ -887,6 +893,7 @@ impl AstNode for Expr { | METHOD_CALL_EXPR | FIELD_EXPR | TRY_EXPR + | TRY_BLOCK_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR @@ -929,6 +936,7 @@ impl Expr { METHOD_CALL_EXPR => ExprKind::MethodCallExpr(MethodCallExpr::cast(&self.syntax).unwrap()), FIELD_EXPR => ExprKind::FieldExpr(FieldExpr::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()), REF_EXPR => ExprKind::RefExpr(RefExpr::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; + fn to_owned(&self) -> TreeArc { TreeArc::cast(self.syntax.to_owned()) } +} + + +impl ast::TryBlockBodyOwner for TryBlockExpr {} +impl TryBlockExpr {} + // TryExpr #[derive(Debug, PartialEq, Eq, Hash)] #[repr(transparent)] diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index 1c90cf148..433485400 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs @@ -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 { fn arg_list(&self) -> Option<&ast::ArgList> { child_opt(self) diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index b8665bbc8..1c2714307 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -95,6 +95,7 @@ Grammar( "let", "move", "return", + "try", ], contextual_keywords: [ "auto", @@ -189,6 +190,7 @@ Grammar( "STRUCT_LIT", "NAMED_FIELD_LIST", "NAMED_FIELD", + "TRY_BLOCK_EXPR", // postfix "CALL_EXPR", @@ -417,6 +419,9 @@ Grammar( "LoopExpr": ( traits: ["LoopBodyOwner"], ), + "TryBlockExpr": ( + traits: ["TryBlockBodyOwner"], + ), "ForExpr": ( traits: ["LoopBodyOwner"], options: [ @@ -499,6 +504,7 @@ Grammar( "MethodCallExpr", "FieldExpr", "TryExpr", + "TryBlockExpr", "CastExpr", "RefExpr", "PrefixExpr", diff --git a/crates/ra_syntax/tests/data/parser/ok/0051_try_block.rs b/crates/ra_syntax/tests/data/parser/ok/0051_try_block.rs new file mode 100644 index 000000000..8cc11ddcc --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0051_try_block.rs @@ -0,0 +1,5 @@ +fn main() { + let res = try { + + }; +} diff --git a/crates/ra_syntax/tests/data/parser/ok/0051_try_block.txt b/crates/ra_syntax/tests/data/parser/ok/0051_try_block.txt new file mode 100644 index 000000000..f94eb3bcd --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0051_try_block.txt @@ -0,0 +1,32 @@ +SOURCE_FILE@[0; 41) + FN_DEF@[0; 41) + FN_KW@[0; 2) "fn" + WHITESPACE@[2; 3) " " + NAME@[3; 7) + IDENT@[3; 7) "main" + PARAM_LIST@[7; 9) + L_PAREN@[7; 8) "(" + R_PAREN@[8; 9) ")" + WHITESPACE@[9; 10) " " + BLOCK@[10; 41) + L_CURLY@[10; 11) "{" + WHITESPACE@[11; 16) "\n " + LET_STMT@[16; 39) + LET_KW@[16; 19) "let" + WHITESPACE@[19; 20) " " + BIND_PAT@[20; 23) + NAME@[20; 23) + IDENT@[20; 23) "res" + WHITESPACE@[23; 24) " " + EQ@[24; 25) "=" + WHITESPACE@[25; 26) " " + TRY_EXPR@[26; 38) + TRY_KW@[26; 29) "try" + WHITESPACE@[29; 30) " " + BLOCK@[30; 38) + L_CURLY@[30; 31) "{" + WHITESPACE@[31; 37) "\n\n " + R_CURLY@[37; 38) "}" + SEMI@[38; 39) ";" + WHITESPACE@[39; 40) "\n" + R_CURLY@[40; 41) "}" \ No newline at end of file -- cgit v1.2.3 From 505b8d873ffe422358bb4ff47dc82d6c76d0772e Mon Sep 17 00:00:00 2001 From: Andrey Tkachenko Date: Thu, 6 Jun 2019 16:26:54 +0400 Subject: [#1083] Try block syntax: fix tests --- crates/ra_hir/src/ty/infer.rs | 1 - crates/ra_parser/src/grammar/expressions/atom.rs | 14 +++++----- .../data/parser/inline/ok/0130_try_block_expr.rs | 3 ++ .../data/parser/inline/ok/0130_try_block_expr.txt | 31 +++++++++++++++++++++ .../tests/data/parser/ok/0051_try_block.rs | 5 ---- .../tests/data/parser/ok/0051_try_block.txt | 32 ---------------------- 6 files changed, 41 insertions(+), 45 deletions(-) create mode 100644 crates/ra_syntax/tests/data/parser/inline/ok/0130_try_block_expr.rs create mode 100644 crates/ra_syntax/tests/data/parser/inline/ok/0130_try_block_expr.txt delete mode 100644 crates/ra_syntax/tests/data/parser/ok/0051_try_block.rs delete mode 100644 crates/ra_syntax/tests/data/parser/ok/0051_try_block.txt (limited to 'crates') diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 579307d8a..6cc5dbc6f 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -948,7 +948,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { 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 } diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 0df47d33d..725fb99f6 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -76,7 +76,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar T![loop] => loop_expr(p, None), T![for] => for_expr(p, None), T![while] => while_expr(p, None), - T![try] => try_expr(p, None), + T![try] => try_block_expr(p, None), LIFETIME if la == T![:] => { let m = p.start(); label(p); @@ -118,7 +118,9 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar } }; let blocklike = match done.kind() { - IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_BLOCK_EXPR => BlockLike::Block, + IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_BLOCK_EXPR => { + BlockLike::Block + } _ => BlockLike::NotBlock, }; Some((done, blocklike)) @@ -494,13 +496,11 @@ fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { m.complete(p, BREAK_EXPR) } -// test try_expr +// test try_block_expr // fn foo() { -// try { -// -// } +// let _ = try {}; // } -fn try_expr(p: &mut Parser, m: Option) -> CompletedMarker { +fn try_block_expr(p: &mut Parser, m: Option) -> CompletedMarker { assert!(p.at(T![try])); let m = m.unwrap_or_else(|| p.start()); p.bump(); diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0130_try_block_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0130_try_block_expr.rs new file mode 100644 index 000000000..0f1b41eb6 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0130_try_block_expr.rs @@ -0,0 +1,3 @@ +fn foo() { + let _ = try {}; +} diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0130_try_block_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0130_try_block_expr.txt new file mode 100644 index 000000000..53f49b9b5 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0130_try_block_expr.txt @@ -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" diff --git a/crates/ra_syntax/tests/data/parser/ok/0051_try_block.rs b/crates/ra_syntax/tests/data/parser/ok/0051_try_block.rs deleted file mode 100644 index 8cc11ddcc..000000000 --- a/crates/ra_syntax/tests/data/parser/ok/0051_try_block.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - let res = try { - - }; -} diff --git a/crates/ra_syntax/tests/data/parser/ok/0051_try_block.txt b/crates/ra_syntax/tests/data/parser/ok/0051_try_block.txt deleted file mode 100644 index f94eb3bcd..000000000 --- a/crates/ra_syntax/tests/data/parser/ok/0051_try_block.txt +++ /dev/null @@ -1,32 +0,0 @@ -SOURCE_FILE@[0; 41) - FN_DEF@[0; 41) - FN_KW@[0; 2) "fn" - WHITESPACE@[2; 3) " " - NAME@[3; 7) - IDENT@[3; 7) "main" - PARAM_LIST@[7; 9) - L_PAREN@[7; 8) "(" - R_PAREN@[8; 9) ")" - WHITESPACE@[9; 10) " " - BLOCK@[10; 41) - L_CURLY@[10; 11) "{" - WHITESPACE@[11; 16) "\n " - LET_STMT@[16; 39) - LET_KW@[16; 19) "let" - WHITESPACE@[19; 20) " " - BIND_PAT@[20; 23) - NAME@[20; 23) - IDENT@[20; 23) "res" - WHITESPACE@[23; 24) " " - EQ@[24; 25) "=" - WHITESPACE@[25; 26) " " - TRY_EXPR@[26; 38) - TRY_KW@[26; 29) "try" - WHITESPACE@[29; 30) " " - BLOCK@[30; 38) - L_CURLY@[30; 31) "{" - WHITESPACE@[31; 37) "\n\n " - R_CURLY@[37; 38) "}" - SEMI@[38; 39) ";" - WHITESPACE@[39; 40) "\n" - R_CURLY@[40; 41) "}" \ No newline at end of file -- cgit v1.2.3