Skip to content

Commit a74cc99

Browse files
authored
Merge pull request #4233 from dotty-staging/fix-4227
Fix #4227: handle singleton types in exhaustivity check
2 parents dd03912 + 9b99ef8 commit a74cc99

File tree

4 files changed

+29
-4
lines changed

4 files changed

+29
-4
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ object messages {
884884
val msg =
885885
hl"""|match may not be exhaustive.
886886
|
887-
|It would fail on: $uncovered"""
887+
|It would fail on pattern case: $uncovered"""
888888

889889

890890
val explanation =

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,21 +400,21 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
400400

401401
val sig =
402402
if (isSyntheticScala2Unapply(unappSym) && caseAccessors.length == argLen)
403-
caseAccessors.map(_.info.asSeenFrom(mt.paramInfos.head, caseClass).widen)
403+
caseAccessors.map(_.info.asSeenFrom(mt.paramInfos.head, caseClass).widenExpr)
404404
else if (mt.finalResultType.isRef(defn.BooleanClass))
405405
List()
406406
else {
407407
val isUnapplySeq = unappSym.name == nme.unapplySeq
408408
if (isProductMatch(mt.finalResultType, argLen) && !isUnapplySeq) {
409409
productSelectors(mt.finalResultType).take(argLen)
410-
.map(_.info.asSeenFrom(mt.finalResultType, mt.resultType.classSymbol).widen)
410+
.map(_.info.asSeenFrom(mt.finalResultType, mt.resultType.classSymbol).widenExpr)
411411
}
412412
else {
413413
val resTp = mt.finalResultType.select(nme.get).finalResultType.widen
414414
if (isUnapplySeq) scalaListType.appliedTo(resTp.argTypes.head) :: Nil
415415
else if (argLen == 0) Nil
416416
else if (isProductMatch(resTp, argLen))
417-
productSelectors(resTp).map(_.info.asSeenFrom(resTp, resTp.classSymbol).widen)
417+
productSelectors(resTp).map(_.info.asSeenFrom(resTp, resTp.classSymbol).widenExpr)
418418
else resTp :: Nil
419419
}
420420
}
@@ -443,6 +443,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
443443
Typ(ConstantType(Constant(true)), true),
444444
Typ(ConstantType(Constant(false)), true)
445445
)
446+
case tp if tp.isRef(defn.UnitClass) =>
447+
Typ(ConstantType(Constant(())), true) :: Nil
446448
case tp if tp.classSymbol.is(Enum) =>
447449
children.map(sym => Typ(sym.termRef, true))
448450
case tp =>
@@ -708,6 +710,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
708710
canDecompose(and.tp1) || canDecompose(and.tp2)
709711
}) ||
710712
tp.isRef(defn.BooleanClass) ||
713+
tp.isRef(defn.UnitClass) ||
711714
tp.classSymbol.is(allOf(Enum, Sealed)) // Enum value doesn't have Sealed flag
712715

713716
debug.println(s"decomposable: ${tp.show} = $res")

tests/patmat/i4227.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object Test {
2+
def foo(x: Option[1]) = x match {
3+
case Some(1) =>
4+
case None =>
5+
}
6+
}

tests/patmat/i4227b.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sealed abstract class Maybe[A]
2+
final case class Just[A](a: A) extends Maybe[A]
3+
class Empty[A] extends Maybe[A]
4+
object Empty {
5+
def apply[A](): Maybe[A] = new Empty[A]
6+
def unapply[A](e: Empty[A]): Some[Unit] = Some(())
7+
}
8+
9+
object Test {
10+
val a: Maybe[Int] = Just(2)
11+
def main(args: Array[String]): Unit = a match {
12+
case Just(_) =>
13+
// case Empty(_) => // ok
14+
case Empty(()) => // match may not be exhaustive. It would fail on: Empty(_)
15+
}
16+
}

0 commit comments

Comments
 (0)