diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 27ac53f5af34..bb875d389f52 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2574,12 +2574,18 @@ object Parsers { }) } - /** TypeCaseClause ::= ‘case’ InfixType ‘=>’ Type [nl] + /** TypeCaseClause ::= ‘case’ (InfixType | ‘_’) ‘=>’ Type [nl] */ def typeCaseClause(): CaseDef = atSpan(in.offset) { val pat = inSepRegion(InCase) { accept(CASE) - infixType() + in.token match { + case USCORE => + in.skipToken() + scalaAny + 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 e5aa1482fab6..ed9bb80d039f 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -285,7 +285,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 [nl] +TypeCaseClause ::= ‘case’ (InfixType | ‘_’) ‘=>’ Type [nl] 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" } +}