diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index bd0e27cbd7ce..c84b7b199052 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -884,7 +884,7 @@ object messages { val msg = hl"""|match may not be exhaustive. | - |It would fail on: $uncovered""" + |It would fail on pattern case: $uncovered""" val explanation = diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index da4f0feb2f8a..cb4ec1d9a9bb 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -400,21 +400,21 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { val sig = if (isSyntheticScala2Unapply(unappSym) && caseAccessors.length == argLen) - caseAccessors.map(_.info.asSeenFrom(mt.paramInfos.head, caseClass).widen) + caseAccessors.map(_.info.asSeenFrom(mt.paramInfos.head, caseClass).widenExpr) else if (mt.finalResultType.isRef(defn.BooleanClass)) List() else { val isUnapplySeq = unappSym.name == nme.unapplySeq if (isProductMatch(mt.finalResultType, argLen) && !isUnapplySeq) { productSelectors(mt.finalResultType).take(argLen) - .map(_.info.asSeenFrom(mt.finalResultType, mt.resultType.classSymbol).widen) + .map(_.info.asSeenFrom(mt.finalResultType, mt.resultType.classSymbol).widenExpr) } else { val resTp = mt.finalResultType.select(nme.get).finalResultType.widen if (isUnapplySeq) scalaListType.appliedTo(resTp.argTypes.head) :: Nil else if (argLen == 0) Nil else if (isProductMatch(resTp, argLen)) - productSelectors(resTp).map(_.info.asSeenFrom(resTp, resTp.classSymbol).widen) + productSelectors(resTp).map(_.info.asSeenFrom(resTp, resTp.classSymbol).widenExpr) else resTp :: Nil } } @@ -443,6 +443,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { Typ(ConstantType(Constant(true)), true), Typ(ConstantType(Constant(false)), true) ) + case tp if tp.isRef(defn.UnitClass) => + Typ(ConstantType(Constant(())), true) :: Nil case tp if tp.classSymbol.is(Enum) => children.map(sym => Typ(sym.termRef, true)) case tp => @@ -708,6 +710,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { canDecompose(and.tp1) || canDecompose(and.tp2) }) || tp.isRef(defn.BooleanClass) || + tp.isRef(defn.UnitClass) || tp.classSymbol.is(allOf(Enum, Sealed)) // Enum value doesn't have Sealed flag debug.println(s"decomposable: ${tp.show} = $res") diff --git a/tests/patmat/i4227.scala b/tests/patmat/i4227.scala new file mode 100644 index 000000000000..efb69bdb3636 --- /dev/null +++ b/tests/patmat/i4227.scala @@ -0,0 +1,6 @@ + object Test { + def foo(x: Option[1]) = x match { + case Some(1) => + case None => + } +} diff --git a/tests/patmat/i4227b.scala b/tests/patmat/i4227b.scala new file mode 100644 index 000000000000..b72971d3d37b --- /dev/null +++ b/tests/patmat/i4227b.scala @@ -0,0 +1,16 @@ +sealed abstract class Maybe[A] +final case class Just[A](a: A) extends Maybe[A] +class Empty[A] extends Maybe[A] +object Empty { + def apply[A](): Maybe[A] = new Empty[A] + def unapply[A](e: Empty[A]): Some[Unit] = Some(()) +} + +object Test { + val a: Maybe[Int] = Just(2) + def main(args: Array[String]): Unit = a match { + case Just(_) => + // case Empty(_) => // ok + case Empty(()) => // match may not be exhaustive. It would fail on: Empty(_) + } +}