diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 0e984154c0cb..4516cdaa48c1 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1863,6 +1863,7 @@ object Parsers { * Ascription ::= `:' InfixType * | `:' Annotation {Annotation} * | `:' `_' `*' + * Catches ::= ‘catch’ (Expr | ExprCaseClause) */ val exprInParens: () => Tree = () => expr(Location.InParens) @@ -1946,7 +1947,7 @@ object Parsers { if in.token == CATCH then val span = in.offset in.nextToken() - (if in.token == CASE then Match(EmptyTree, caseClause() :: Nil) + (if in.token == CASE then Match(EmptyTree, caseClause(exprOnly = true) :: Nil) else subExpr(), span) else (EmptyTree, -1) @@ -2072,7 +2073,7 @@ object Parsers { def matchClause(t: Tree): Match = in.endMarkerScope(MATCH) { atSpan(t.span.start, in.skipToken()) { - Match(t, inBracesOrIndented(caseClauses(caseClause))) + Match(t, inBracesOrIndented(caseClauses(() => caseClause()))) } } @@ -2366,7 +2367,7 @@ object Parsers { def blockExpr(): Tree = atSpan(in.offset) { val simplify = in.token == INDENT inDefScopeBraces { - if (in.token == CASE) Match(EmptyTree, caseClauses(caseClause)) + if (in.token == CASE) Match(EmptyTree, caseClauses(() => caseClause())) else block(simplify) } } @@ -2537,18 +2538,21 @@ object Parsers { } /** CaseClause ::= ‘case’ Pattern [Guard] `=>' Block + * ExprCaseClause ::= ‘case’ Pattern [Guard] ‘=>’ Expr */ - val caseClause: () => CaseDef = () => atSpan(in.offset) { + def caseClause(exprOnly: Boolean = false): CaseDef = atSpan(in.offset) { val (pat, grd) = inSepRegion(LPAREN, RPAREN) { accept(CASE) (pattern(), guard()) } - CaseDef(pat, grd, atSpan(accept(ARROW)) { block() }) + CaseDef(pat, grd, atSpan(accept(ARROW)) { + if exprOnly then expr() else block() + }) } /** TypeCaseClause ::= ‘case’ InfixType ‘=>’ Type [nl] */ - val typeCaseClause: () => CaseDef = () => atSpan(in.offset) { + def typeCaseClause(): CaseDef = atSpan(in.offset) { val pat = inSepRegion(LPAREN, RPAREN) { accept(CASE) infixType() diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md index d0e5d9a313cc..cabdc7c89e4d 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -203,7 +203,7 @@ Expr1 ::= [‘inline’] ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[ | ‘inline’ InfixExpr MatchClause Ascription ::= ‘:’ InfixType Typed(expr, tp) | ‘:’ Annotation {Annotation} Typed(expr, Annotated(EmptyTree, annot)*) -Catches ::= ‘catch’ (Expr | CaseClause) +Catches ::= ‘catch’ (Expr | ExprCaseClause) PostfixExpr ::= InfixExpr [id] PostfixOp(expr, op) InfixExpr ::= PrefixExpr | InfixExpr id [nl] InfixExpr InfixOp(expr, op, expr) @@ -256,7 +256,8 @@ Generator ::= [‘case’] Pattern1 ‘<-’ Expr Guard ::= ‘if’ PostfixExpr CaseClauses ::= CaseClause { CaseClause } Match(EmptyTree, cases) -CaseClause ::= ‘case’ (Pattern [Guard] ‘=>’ Block | INT) CaseDef(pat, guard?, block) // block starts at => +CaseClause ::= ‘case’ Pattern [Guard] ‘=>’ Block CaseDef(pat, guard?, block) // block starts at => +ExprCaseClause ::= ‘case’ Pattern [Guard] ‘=>’ Expr ImplicitCaseClauses ::= ImplicitCaseClause { ImplicitCaseClause } ImplicitCaseClause ::= ‘case’ PatVar [‘:’ RefinedType] [Guard] ‘=>’ Block TypeCaseClauses ::= TypeCaseClause { TypeCaseClause } diff --git a/tests/run/i8096.scala b/tests/run/i8096.scala new file mode 100644 index 000000000000..bb1ed6627e9c --- /dev/null +++ b/tests/run/i8096.scala @@ -0,0 +1,10 @@ +def k: String = + try + "WUT" + catch case t => + println(s"Caught a case of $t") + "OK" + +@main def Test = + assert(k == "OK") +