self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
}
+ ast::Expr::TryBlockExpr(e) => {
+ let body = self.collect_block_opt(e.body());
+ self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
+ }
ast::Expr::BlockExpr(e) => self.collect_block(e),
ast::Expr::LoopExpr(e) => {
let body = self.collect_block_opt(e.loop_body());
Try {
expr: ExprId,
},
+ TryBlock {
+ body: ExprId,
+ },
Cast {
expr: ExprId,
type_ref: TypeRef,
f(*expr);
}
}
+ Expr::TryBlock { body } => f(*body),
Expr::Loop { body } => f(*body),
Expr::While { condition, body } => {
f(*condition);
self.coerce_merge_branch(&then_ty, &else_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
T![box] => box_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);
}
};
let blocklike = match done.kind() {
- IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_EXPR => {
+ IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_BLOCK_EXPR => {
BlockLike::Block
}
_ => BlockLike::NotBlock,
// fn foo() {
// let _ = try {};
// }
-fn try_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
+fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(T![try]));
let m = m.unwrap_or_else(|| p.start());
// Special-case `try!` as macro.
RECORD_LIT,
RECORD_FIELD_LIST,
RECORD_FIELD,
+ TRY_BLOCK_EXPR,
BOX_EXPR,
CALL_EXPR,
INDEX_EXPR,
};
pub use self::{
- expr_extensions::{
- ArrayExprKind, BinOp, BlockModifier, ElseBranch, LiteralKind, PrefixOp, RangeOp,
- },
+ expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
extensions::{
AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
StructKind, TypeBoundKind, VisibilityKind,
| ast::Expr::WhileExpr(_)
| ast::Expr::BlockExpr(_)
| ast::Expr::MatchExpr(_)
- | ast::Expr::TryExpr(_) => true,
+ | ast::Expr::TryBlockExpr(_) => true,
_ => false,
}
}
}
}
-pub enum BlockModifier {
- Async(SyntaxToken),
- Unsafe(SyntaxToken),
-}
-
impl ast::BlockExpr {
- pub fn modifier(&self) -> Option<BlockModifier> {
- if let Some(token) = self.async_token() {
- return Some(BlockModifier::Async(token));
- }
- if let Some(token) = self.unsafe_token() {
- return Some(BlockModifier::Unsafe(token));
- }
- None
- }
-
/// false if the block is an intrinsic part of the syntax and can't be
/// replaced with arbitrary expression.
///
/// const FOO: () = { stand_alone };
/// ```
pub fn is_standalone(&self) -> bool {
- if self.modifier().is_some() {
+ if self.unsafe_token().is_some() || self.async_token().is_some() {
return false;
}
- let parent = match self.syntax().parent() {
- Some(it) => it,
+ let kind = match self.syntax().parent() {
None => return true,
+ Some(it) => it.kind(),
};
- match parent.kind() {
- FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR => false,
+ match kind {
+ FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | TRY_BLOCK_EXPR => false,
_ => true,
}
}
pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
}
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TryBlockExpr {
+ pub(crate) syntax: SyntaxNode,
+}
+impl ast::AttrsOwner for TryBlockExpr {}
+impl TryBlockExpr {
+ pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
+ pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
+}
+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ForExpr {
pub(crate) syntax: SyntaxNode,
FieldExpr(FieldExpr),
AwaitExpr(AwaitExpr),
TryExpr(TryExpr),
+ TryBlockExpr(TryBlockExpr),
CastExpr(CastExpr),
RefExpr(RefExpr),
PrefixExpr(PrefixExpr),
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
+impl AstNode for TryBlockExpr {
+ fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_BLOCK_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 ForExpr {
fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR }
fn cast(syntax: SyntaxNode) -> Option<Self> {
impl From<TryExpr> for Expr {
fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
}
+impl From<TryBlockExpr> for Expr {
+ fn from(node: TryBlockExpr) -> Expr { Expr::TryBlockExpr(node) }
+}
impl From<CastExpr> for Expr {
fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) }
}
TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR
| LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL
| BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR
- | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | CAST_EXPR | REF_EXPR
- | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL | BOX_EXPR => true,
+ | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | TRY_BLOCK_EXPR
+ | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL
+ | BOX_EXPR => true,
_ => false,
}
}
FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }),
AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }),
TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
+ TRY_BLOCK_EXPR => Expr::TryBlockExpr(TryBlockExpr { syntax }),
CAST_EXPR => Expr::CastExpr(CastExpr { syntax }),
REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }),
Expr::FieldExpr(it) => &it.syntax,
Expr::AwaitExpr(it) => &it.syntax,
Expr::TryExpr(it) => &it.syntax,
+ Expr::TryBlockExpr(it) => &it.syntax,
Expr::CastExpr(it) => &it.syntax,
Expr::RefExpr(it) => &it.syntax,
Expr::PrefixExpr(it) => &it.syntax,
std::fmt::Display::fmt(self.syntax(), f)
}
}
+impl std::fmt::Display for TryBlockExpr {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.syntax(), f)
+ }
+}
impl std::fmt::Display for ForExpr {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
"RECORD_LIT",
"RECORD_FIELD_LIST",
"RECORD_FIELD",
+ "TRY_BLOCK_EXPR",
"BOX_EXPR",
// postfix
"CALL_EXPR",
}
struct IfExpr: AttrsOwner { T![if], Condition }
struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] }
+ struct TryBlockExpr: AttrsOwner { T![try], body: BlockExpr }
struct ForExpr: AttrsOwner, LoopBodyOwner {
T![for],
Pat,
struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] }
struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr }
struct Label { T![lifetime] }
- struct BlockExpr: AttrsOwner { Label, T![unsafe], T![async], Block }
+ struct BlockExpr: AttrsOwner { Label, T![unsafe], T![async], Block }
struct ReturnExpr: AttrsOwner { Expr }
struct CallExpr: ArgListOwner { Expr }
struct MethodCallExpr: AttrsOwner, ArgListOwner {
FieldExpr,
AwaitExpr,
TryExpr,
+ TryBlockExpr,
CastExpr,
RefExpr,
PrefixExpr,