diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala index 5986f68952ff..bf8c82239265 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala @@ -11,11 +11,7 @@ trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with TastyCoreImpl w } object CaseDef extends CaseDefExtractor { - def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] = x match { - case x: tpd.CaseDef => - Some(x.pat, optional(x.guard), x.body) - case _ => None - } + def unapply(x: CaseDef): Some[(Pattern, Option[Term], Term)] = Some(x.pat, optional(x.guard), x.body) } } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ConstantOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ConstantOpsImpl.scala index e7c5ed5c7d6a..179e40a53c79 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ConstantOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ConstantOpsImpl.scala @@ -13,17 +13,11 @@ trait ConstantOpsImpl extends scala.tasty.reflect.ConstantOps with TastyCoreImpl object Constant extends ConstantModule { object Unit extends UnitExtractor { - def unapply(x: Constant): Boolean = x match { - case x: Constants.Constant => x.tag == Constants.UnitTag - case _ => false - } + def unapply(x: Constant): Boolean = x.tag == Constants.UnitTag } object Null extends NullExtractor { - def unapply(x: Constant): Boolean = x match { - case x: Constants.Constant => x.tag == Constants.NullTag - case _ => false - } + def unapply(x: Constant): Boolean = x.tag == Constants.NullTag } object Boolean extends BooleanExtractor { diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 906642b95434..7c34df04ab05 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -293,8 +293,12 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { private val nullSpace = Typ(nullType) override def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type): Space = { + // Precondition: !isSubType(tp1, tp2) && !isSubType(tp2, tp1) + if (tp1 == nullType || tp2 == nullType) { + // Since projections of types don't include null, intersection with null is empty. + return Empty + } val and = AndType(tp1, tp2) - // Precondition: !(tp1 <:< tp2) && !(tp2 <:< tp1) // Then, no leaf of the and-type tree `and` is a subtype of `and`. val res = inhabited(and) diff --git a/tests/patmat/i4880a.check b/tests/patmat/i4880a.check new file mode 100644 index 000000000000..8a7020e0090c --- /dev/null +++ b/tests/patmat/i4880a.check @@ -0,0 +1 @@ +14: Match case Unreachable diff --git a/tests/patmat/t4661.check b/tests/patmat/t4661.check new file mode 100644 index 000000000000..53a5baa3ca76 --- /dev/null +++ b/tests/patmat/t4661.check @@ -0,0 +1,15 @@ +9: Match case Unreachable +10: Match case Unreachable +11: Match case Unreachable +26: Match case Unreachable +27: Match case Unreachable +28: Match case Unreachable +33: Match case Unreachable +36: Match case Unreachable +37: Match case Unreachable +38: Match case Unreachable +39: Match case Unreachable +40: Only null matched +46: Match case Unreachable +52: Match case Unreachable +59: Only null matched diff --git a/tests/patmat/t4661.scala b/tests/patmat/t4661.scala new file mode 100644 index 000000000000..e87490457ddf --- /dev/null +++ b/tests/patmat/t4661.scala @@ -0,0 +1,61 @@ +trait Foo +class One extends Foo +class Two extends Foo +class Three extends Foo + +object Test { + def test(f: Foo) = f match { + case f: Foo => + case f: One => // unreachable + case f: Two => // unreachable + case f: Three => // unreachable + } +} + +trait Prefix { + sealed trait Bar + class BarOne extends Bar + class BarTwo extends Bar + class BarThree extends Bar +} + +class TestPrefix(val p: Prefix) { + import p._ + def test(b: Bar) = b match { + case b: Bar => + case b: BarOne => // unreachable + case b: BarTwo => // unreachable + case b: BarThree => // unreachable + } + + def test2(b: Bar) = b match { + case b: Prefix#BarOne => + case b: BarOne => // unreachable + case b: Prefix#BarTwo => + case b: Prefix#BarThree => + case b: BarTwo => // unreachable + case b: BarThree => // unreachable + case b: Bar => // unreachable + case b: Prefix#Bar => // unreachable + case _ => // only null matches + } + + def test3(b: Prefix#Bar) = b match { + case b: Bar => + case b: Prefix#BarOne => + case b: BarOne => // unreachable + case _ => + } + + def test4(b: Bar) = b match { + case b: Bar => + case b:Prefix#Bar => // unreachable + } + + def test5(b: Bar) = b match { + case b: Prefix#BarOne => + case b: Prefix#BarTwo => + case b: Prefix#BarThree => + case _ => // only null matches + } +}