diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 27c1dead4482..c96436bccc1d 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2607,12 +2607,19 @@ object Parsers { }) } - /** TypeCaseClause ::= ‘case’ InfixType ‘=>’ Type [semi] + /** TypeCaseClause ::= ‘case’ (InfixType | ‘_’) ‘=>’ Type [semi] */ def typeCaseClause(): CaseDef = atSpan(in.offset) { val pat = inSepRegion(InCase) { accept(CASE) - infixType() + in.token match { + case USCORE if in.lookahead.isArrow => + val start = in.skipToken() + typeBounds().withSpan(Span(start, in.lastOffset, start)) + + case _ => + infixType() + } } CaseDef(pat, EmptyTree, atSpan(accept(ARROW)) { val t = typ() diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md index 9e6b234fb6ba..af70245e62ca 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -289,7 +289,7 @@ CaseClauses ::= CaseClause { CaseClause } CaseClause ::= ‘case’ Pattern [Guard] ‘=>’ Block CaseDef(pat, guard?, block) // block starts at => ExprCaseClause ::= ‘case’ Pattern [Guard] ‘=>’ Expr TypeCaseClauses ::= TypeCaseClause { TypeCaseClause } -TypeCaseClause ::= ‘case’ InfixType ‘=>’ Type [semi] +TypeCaseClause ::= ‘case’ (InfixType | ‘_’) ‘=>’ Type [semi] Pattern ::= Pattern1 { ‘|’ Pattern1 } Alternative(pats) Pattern1 ::= Pattern2 [‘:’ RefinedType] Bind(name, Typed(Ident(wildcard), tpe)) diff --git a/tests/pos/unify-wildcard-patterns.scala b/tests/pos/unify-wildcard-patterns.scala new file mode 100644 index 000000000000..af88f4c80067 --- /dev/null +++ b/tests/pos/unify-wildcard-patterns.scala @@ -0,0 +1,13 @@ +// `case _ => expr` in a match expression should be equivalant to +// `case _: Any => expr`. Likewise, in a match type, `case _ => T` +// should be equivalant to `case Any => T`. + +object Test0 { + type M[X] = X match { case String => Int case Any => String } + def m[X](x: X): M[X] = x match { case _: String => 1 case _: Any => "s" } +} + +object Test2 { + type M[X] = X match { case String => Int case _ => String } + def m[X](x: X): M[X] = x match { case _: String => 1 case _: Any => "s" } +}