From a913f7792bf821936f22cc8df9a53e489565ea6e Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Tue, 23 Jan 2018 09:22:26 +0100 Subject: [PATCH 1/4] refactor inhabited in exhaustivness check --- .../tools/dotc/transform/patmat/Space.scala | 185 +++++++++--------- 1 file changed, 93 insertions(+), 92 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 81b00c4572e7..f20296986e6a 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -278,21 +278,8 @@ trait SpaceLogic { } } -object SpaceEngine { - private sealed trait Implementability { - def show(implicit ctx: Context) = this match { - case SubclassOf(classSyms) => s"SubclassOf(${classSyms.map(_.show)})" - case other => other.toString - } - } - private case object ClassOrTrait extends Implementability - private case class SubclassOf(classSyms: List[Symbol]) extends Implementability - private case object Unimplementable extends Implementability -} - /** Scala implementation of space logic */ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { - import SpaceEngine._ import tpd._ private val scalaSomeClass = ctx.requiredClass("scala.Some") @@ -301,77 +288,15 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { private val scalaNilType = ctx.requiredModuleRef("scala.collection.immutable.Nil") private val scalaConsType = ctx.requiredClassRef("scala.collection.immutable.::") - /** Checks if it's possible to create a trait/class which is a subtype of `tp`. - * - * - doesn't handle member collisions (will not declare a type unimplementable because of one) - * - expects that neither Any nor Object reach it - * (this is currently true due to both isSubType and and/or type simplification) - * - * See [[intersectUnrelatedAtomicTypes]]. - */ - private def implementability(tp: Type): Implementability = tp.dealias match { - case AndType(tp1, tp2) => - (implementability(tp1), implementability(tp2)) match { - case (Unimplementable, _) | (_, Unimplementable) => Unimplementable - case (SubclassOf(classSyms1), SubclassOf(classSyms2)) => - (for { - sym1 <- classSyms1 - sym2 <- classSyms2 - result <- - if (sym1 isSubClass sym2) List(sym1) - else if (sym2 isSubClass sym1) List(sym2) - else Nil - } yield result) match { - case Nil => Unimplementable - case lst => SubclassOf(lst) - } - case (ClassOrTrait, ClassOrTrait) => ClassOrTrait - case (SubclassOf(clss), _) => SubclassOf(clss) - case (_, SubclassOf(clss)) => SubclassOf(clss) - } - case OrType(tp1, tp2) => - (implementability(tp1), implementability(tp2)) match { - case (ClassOrTrait, _) | (_, ClassOrTrait) => ClassOrTrait - case (SubclassOf(classSyms1), SubclassOf(classSyms2)) => - SubclassOf(classSyms1 ::: classSyms2) - case (SubclassOf(classSyms), _) => SubclassOf(classSyms) - case (_, SubclassOf(classSyms)) => SubclassOf(classSyms) - case _ => Unimplementable - } - case _: SingletonType => - // singleton types have no instantiable subtypes - Unimplementable - case tp: RefinedType => - // refinement itself is not considered - it would at most make - // a type unimplementable because of a member collision - implementability(tp.parent) - case other => - val classSym = other.classSymbol - if (classSym.exists) { - if (classSym is Final) Unimplementable - else if (classSym is Trait) ClassOrTrait - else SubclassOf(List(classSym)) - } else { - // if no class symbol exists, conservatively say that anything - // can implement `tp` - ClassOrTrait - } - } - override def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type) = { val and = AndType(tp1, tp2) // Precondition: !(tp1 <:< tp2) && !(tp2 <:< tp1) // Then, no leaf of the and-type tree `and` is a subtype of `and`. - // Then, to create a value of type `and` you must instantiate a trait (class/module) - // which is a subtype of all the leaves of `and`. - val imp = implementability(and) + val res = inhabited(and) - debug.println(s"atomic intersection: ${and.show} ~ ${imp.show}") + debug.println(s"atomic intersection: ${and.show} = ${res}") - imp match { - case Unimplementable => Empty - case _ => Typ(and, true) - } + if (res) Typ(and, true) else Empty } /* Whether the extractor is irrefutable */ @@ -574,21 +499,97 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { /** Can this type be inhabited by a value? * - * Intersection between singleton types and other types is always empty - * the singleton type is not a subtype of the other type. - * See patmat/i3573.scala for an example. + * Check is based on the following facts: + * + * - single inheritance of classes + * - final class cannot be extended + * - intersection of a singleton type with another irrelevant type (patmat/i3574.scala) + * */ - def inhabited(tpe: Type)(implicit ctx: Context): Boolean = { - val emptySingletonIntersection = new ExistsAccumulator({ - case AndType(s: SingletonType, t) => - !(s <:< t) - case AndType(t, s: SingletonType) => - !(s <:< t) - case x => - false - }) - - !emptySingletonIntersection(false, tpe) + def inhabited(tp: Type)(implicit ctx: Context): Boolean = { + // convert top-level type shape into "conjunctive normal form" + def cnf(tp: Type): Type = tp match { + case AndType(OrType(l, r), tp) => + val tp1 = cnf(tp) + val l1 = cnf(l) + val r1 = cnf(r) + OrType(cnf(AndType(l1, tp1)), cnf(AndType(r1, tp1))) + case AndType(tp, o: OrType) => + cnf(AndType(o, tp)) + case AndType(l, r) => + val l1 = cnf(l) + val r1 = cnf(r) + if (l1.ne(l) || r1.ne(r)) cnf(AndType(l1, r1)) + else AndType(l1, r1) + case OrType(l, r) => + OrType(cnf(l), cnf(r)) + case tp @ RefinedType(OrType(tp1, tp2), _, _) => + OrType( + cnf(tp.derivedRefinedType(tp1, refinedName = tp.refinedName, refinedInfo = tp.refinedInfo)), + cnf(tp.derivedRefinedType(tp2, refinedName = tp.refinedName, refinedInfo = tp.refinedInfo)) + ) + case tp: RefinedType => + val parent1 = cnf(tp.parent) + val tp1 = tp.derivedRefinedType(parent1, refinedName = tp.refinedName, refinedInfo = tp.refinedInfo) + + if (parent1.ne(tp.parent)) cnf(tp1) else tp1 + case tp: TypeAlias => + cnf(tp.alias) + case _ => + tp + } + + def isSingleton(tp: Type): Boolean = tp.dealias match { + case AndType(l, r) => isSingleton(l) || isSingleton(r) + case OrType(l, r) => isSingleton(l) && isSingleton(r) + case tp => tp.isSingleton + } + + def superType(tp: Type): Type = tp match { + case tp: TypeProxy => tp.superType + case OrType(tp1, tp2) => OrType(superType(tp1), superType(tp2)) + case AndType(tp1, tp2) => AndType(superType(tp1), superType(tp2)) + case _ => tp + } + + def recur(tp: Type): Boolean = tp.dealias match { + case AndType(tp1, tp2) => + recur(tp1) && recur(tp2) && { + val bases1 = tp1.widenDealias.classSymbols + val bases2 = tp2.widenDealias.classSymbols + + debug.println(s"bases of ${tp1.show}: " + bases1) + debug.println(s"bases of ${tp2.show}: " + bases2) + + val noClassConflict = + bases1.forall(sym1 => sym1.is(Trait) || bases2.forall(sym2 => sym2.is(Trait) || sym1.isSubClass(sym2))) || + bases1.forall(sym1 => sym1.is(Trait) || bases2.forall(sym2 => sym2.is(Trait) || sym2.isSubClass(sym1))) + + debug.println(s"class conflict for ${tp.show}? " + !noClassConflict) + + noClassConflict && + (!isSingleton(tp1) || tp1 <:< tp2) && + (!isSingleton(tp2) || tp2 <:< tp1) && + (!bases1.exists(_ is Final) || tp1 <:< superType(tp2)) && + (!bases2.exists(_ is Final) || tp2 <:< superType(tp1)) + } + case OrType(tp1, tp2) => + recur(tp1) || recur(tp2) + case tp: RefinedType => + recur(tp.parent) + case tp: TypeRef => + recur(tp.prefix) && + !(tp.classSymbol.is(Sealed) && tp.classSymbol.is(AbstractOrTrait) && tp.classSymbol.children.isEmpty) && + !(tp.classSymbol.is(AbstractFinal)) + case _ => + true + } + + val res = recur(cnf(tp)) + + debug.println(s"${tp.show} inhabited? " + res) + + res } /** Instantiate type `tp1` to be a subtype of `tp2` From 7799da66e1f91f19f220609e665acaa9e94aa9e7 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Fri, 26 Jan 2018 21:15:26 +0100 Subject: [PATCH 2/4] address review: simplify CNF conversion --- .../src/dotty/tools/dotc/transform/patmat/Space.scala | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index f20296986e6a..778020242966 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -510,10 +510,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { // convert top-level type shape into "conjunctive normal form" def cnf(tp: Type): Type = tp match { case AndType(OrType(l, r), tp) => - val tp1 = cnf(tp) - val l1 = cnf(l) - val r1 = cnf(r) - OrType(cnf(AndType(l1, tp1)), cnf(AndType(r1, tp1))) + OrType(cnf(AndType(l, tp)), cnf(AndType(r, tp))) case AndType(tp, o: OrType) => cnf(AndType(o, tp)) case AndType(l, r) => @@ -533,9 +530,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { val tp1 = tp.derivedRefinedType(parent1, refinedName = tp.refinedName, refinedInfo = tp.refinedInfo) if (parent1.ne(tp.parent)) cnf(tp1) else tp1 - case tp: TypeAlias => + case tp: TypeAlias => cnf(tp.alias) - case _ => + case _ => tp } From d38ce6b60978d2595f4f30a27dd153ea4440e17e Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Tue, 23 Jan 2018 14:27:44 +0100 Subject: [PATCH 3/4] Fix #3144: more agressively check unreachability --- .../tools/dotc/transform/patmat/Space.scala | 21 ++++++++++--------- tests/patmat/3144.check | 1 + tests/patmat/3144c.check | 1 + tests/patmat/3144c.scala | 9 ++++++++ .../patmat/andtype-opentype-interaction.check | 1 + .../andtype-refinedtype-interaction.check | 3 +++ tests/patmat/i2253.check | 6 ++++-- tests/patmat/i2253.scala | 1 + tests/patmat/t6450.scala | 2 +- .../virtpatmat_reach_sealed_unsealed.check | 1 + 10 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 tests/patmat/3144.check create mode 100644 tests/patmat/3144c.check create mode 100644 tests/patmat/3144c.scala diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 778020242966..a4f49f6c27fd 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -903,24 +903,25 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { def checkRedundancy(_match: Match): Unit = { val Match(sel, cases) = _match // ignore selector type for now - // val selTyp = sel.tpe.widen.dealias - - if (cases.length == 1) return + val selTyp = sel.tpe.widen.dealias - // starts from the second, the first can't be redundant - (1 until cases.length).foreach { i => + (0 until cases.length).foreach { i => // in redundancy check, take guard as false in order to soundly approximate - val prevs = cases.take(i).map { x => - if (x.guard.isEmpty) project(x.pat) - else Empty - }.reduce((a, b) => Or(List(a, b))) + val prevs = + if (i == 0) + Empty + else + cases.take(i).map { x => + if (x.guard.isEmpty) project(x.pat) + else Empty + }.reduce((a, b) => Or(List(a, b))) val curr = project(cases(i).pat) debug.println(s"---------------reachable? ${show(curr)}") debug.println(s"prev: ${show(prevs)}") - if (isSubspace(curr, prevs)) { + if (isSubspace(intersect(curr, Typ(selTyp, false)), prevs)) { ctx.warning(MatchCaseUnreachable(), cases(i).body.pos) } } diff --git a/tests/patmat/3144.check b/tests/patmat/3144.check new file mode 100644 index 000000000000..55a7e2436f0b --- /dev/null +++ b/tests/patmat/3144.check @@ -0,0 +1 @@ +7: Match case Unreachable diff --git a/tests/patmat/3144c.check b/tests/patmat/3144c.check new file mode 100644 index 000000000000..55a7e2436f0b --- /dev/null +++ b/tests/patmat/3144c.check @@ -0,0 +1 @@ +7: Match case Unreachable diff --git a/tests/patmat/3144c.scala b/tests/patmat/3144c.scala new file mode 100644 index 000000000000..b92c231af25b --- /dev/null +++ b/tests/patmat/3144c.scala @@ -0,0 +1,9 @@ +sealed trait Foo +case class Bar(s: String) + +object Test { + def shouldError(foo: Foo): String = + foo match { + case bar: Bar => bar.s + } +} \ No newline at end of file diff --git a/tests/patmat/andtype-opentype-interaction.check b/tests/patmat/andtype-opentype-interaction.check index 4ef4731d64bd..d8ceeee3c80d 100644 --- a/tests/patmat/andtype-opentype-interaction.check +++ b/tests/patmat/andtype-opentype-interaction.check @@ -2,5 +2,6 @@ 27: Pattern Match Exhaustivity: _: SealedClass & OpenTrait & OpenTrait2, _: AbstractClass & OpenTrait & OpenTrait2, _: Clazz & OpenTrait & OpenTrait2, _: Trait & OpenTrait & OpenTrait2 31: Pattern Match Exhaustivity: _: Trait & OpenClass 35: Pattern Match Exhaustivity: _: Trait & OpenTrait & OpenClass +40: Match case Unreachable 43: Pattern Match Exhaustivity: _: Trait & OpenAbstractClass 47: Pattern Match Exhaustivity: _: Trait & OpenClass & OpenTrait & OpenClassSubclass diff --git a/tests/patmat/andtype-refinedtype-interaction.check b/tests/patmat/andtype-refinedtype-interaction.check index 2f8687a868e5..ce6d6e51b2d1 100644 --- a/tests/patmat/andtype-refinedtype-interaction.check +++ b/tests/patmat/andtype-refinedtype-interaction.check @@ -1,6 +1,9 @@ 32: Pattern Match Exhaustivity: _: Trait & C1{x: Int} +37: Match case Unreachable +43: Match case Unreachable 48: Pattern Match Exhaustivity: _: Clazz & (C1 | C2 | T1){x: Int} & (C3 | C4 | T2){x: Int}, _: Trait & (C1 | C2 | T1){x: Int} & (C3 | C4 | T2){x: Int} 54: Pattern Match Exhaustivity: _: Trait & (C1 | C2 | T1){x: Int} & C3{x: Int} +60: Match case Unreachable 65: Pattern Match Exhaustivity: _: Trait & (C1 | C2){x: Int} & (C3 | SubC1){x: Int} 72: Pattern Match Exhaustivity: _: Trait & (T1 & (C1 | SubC2)){x: Int} & (T2 & (C2 | C3 | SubC1)){x: Int} & SubSubC1{x: Int} diff --git a/tests/patmat/i2253.check b/tests/patmat/i2253.check index 5c86a1ef824b..d43092db6263 100644 --- a/tests/patmat/i2253.check +++ b/tests/patmat/i2253.check @@ -1,3 +1,5 @@ -27: Pattern Match Exhaustivity: HasIntXIntM, HasIntXStringM -28: Pattern Match Exhaustivity: HasIntXIntM +28: Pattern Match Exhaustivity: HasIntXIntM, HasIntXStringM 29: Pattern Match Exhaustivity: HasIntXIntM +29: Match case Unreachable +30: Pattern Match Exhaustivity: HasIntXIntM +30: Match case Unreachable diff --git a/tests/patmat/i2253.scala b/tests/patmat/i2253.scala index 0344a6a5d2f1..33e4e0e87ec5 100644 --- a/tests/patmat/i2253.scala +++ b/tests/patmat/i2253.scala @@ -22,6 +22,7 @@ object HasIntXIntM extends S { } trait T +case class TA(val x: Int) extends T with S class Test { def onlyIntX(s: S { val x: Int }) = s match { case _: T => ; } diff --git a/tests/patmat/t6450.scala b/tests/patmat/t6450.scala index 157f1ce8124e..92194c2e48ab 100644 --- a/tests/patmat/t6450.scala +++ b/tests/patmat/t6450.scala @@ -1,5 +1,5 @@ sealed abstract class FoundNode[T] -// case class A[T](x: T) extends FoundNode[T] +case class A[T](x: T) extends FoundNode[T] object Foo { val v: (Some[_], FoundNode[_]) = (???, ???) diff --git a/tests/patmat/virtpatmat_reach_sealed_unsealed.check b/tests/patmat/virtpatmat_reach_sealed_unsealed.check index 6b0ea7f8e1e6..3d9eff70f640 100644 --- a/tests/patmat/virtpatmat_reach_sealed_unsealed.check +++ b/tests/patmat/virtpatmat_reach_sealed_unsealed.check @@ -1,3 +1,4 @@ 16: Pattern Match Exhaustivity: false 18: Match case Unreachable 19: Match case Unreachable +20: Match case Unreachable From 26f384b085eace23810fa239954f46cb47183f47 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Tue, 23 Jan 2018 15:47:39 +0100 Subject: [PATCH 4/4] Fix #3145: treat sealed classes and traits as inhabited Sealed classes and traits are effectively inhabited in practice. By treating them as inhabited by default, we avoid spurious warnings that ignore anonymous classes. When we have a mechanism to track anonymous children or disallow anonymous children for sealed classes, we could revert this change to make the check stronger. --- .../tools/dotc/transform/patmat/Space.scala | 10 ++--- tests/patmat/3144.check | 2 +- tests/patmat/3144c.check | 2 +- tests/patmat/3145.scala | 43 +++++++++++++++++++ .../patmat/andtype-opentype-interaction.check | 12 +++--- tests/patmat/patmatexhaust.check | 1 + tests/patmat/patmatexhaust.scala | 2 +- tests/patmat/t8511.check | 2 +- tests/patmat/t9677.check | 1 - 9 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 tests/patmat/3145.scala delete mode 100644 tests/patmat/t9677.check diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index a4f49f6c27fd..081af65a3403 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -575,9 +575,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { case tp: RefinedType => recur(tp.parent) case tp: TypeRef => - recur(tp.prefix) && - !(tp.classSymbol.is(Sealed) && tp.classSymbol.is(AbstractOrTrait) && tp.classSymbol.children.isEmpty) && - !(tp.classSymbol.is(AbstractFinal)) + recur(tp.prefix) && !(tp.classSymbol.is(AbstractFinal)) case _ => true } @@ -706,8 +704,10 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { /** Abstract sealed types, or-types, Boolean and Java enums can be decomposed */ def canDecompose(tp: Type): Boolean = { val dealiasedTp = tp.dealias - val res = tp.classSymbol.is(allOf(Abstract, Sealed)) || - tp.classSymbol.is(allOf(Trait, Sealed)) || + val res = + (tp.classSymbol.is(Sealed) && + tp.classSymbol.is(AbstractOrTrait) && + tp.classSymbol.children.nonEmpty ) || dealiasedTp.isInstanceOf[OrType] || (dealiasedTp.isInstanceOf[AndType] && { val and = dealiasedTp.asInstanceOf[AndType] diff --git a/tests/patmat/3144.check b/tests/patmat/3144.check index 55a7e2436f0b..78d2e4638a32 100644 --- a/tests/patmat/3144.check +++ b/tests/patmat/3144.check @@ -1 +1 @@ -7: Match case Unreachable +6: Pattern Match Exhaustivity: _: Foo diff --git a/tests/patmat/3144c.check b/tests/patmat/3144c.check index 55a7e2436f0b..78d2e4638a32 100644 --- a/tests/patmat/3144c.check +++ b/tests/patmat/3144c.check @@ -1 +1 @@ -7: Match case Unreachable +6: Pattern Match Exhaustivity: _: Foo diff --git a/tests/patmat/3145.scala b/tests/patmat/3145.scala new file mode 100644 index 000000000000..b8fc5d9b135e --- /dev/null +++ b/tests/patmat/3145.scala @@ -0,0 +1,43 @@ +object Test { + sealed trait Foo + class Bar(val s: String) extends Foo + sealed abstract class Baz(val s: String) extends Foo + + val f: Foo => String = { + case bar: Bar => bar.s + case baz: Baz => baz.s + } +} + +object Test2 { + sealed trait Foo + class Bar extends Foo + sealed trait Baz extends Foo + + def f(x: Foo) = x match { + case bar: Bar => 1 + case baz: Baz => 2 + } +} + +object Test3 { + sealed trait Foo + class Bar extends Foo + sealed trait Baz extends Foo + + def foo = { + val x: Foo = new Baz {} + x match { + case bar: Bar => 1 + case baz: Baz => 2 + } + } + + def bar = { + val x: Baz = new Baz {} + x match { + case bar: Bar => 1 + case baz: Baz => 2 + } + } +} \ No newline at end of file diff --git a/tests/patmat/andtype-opentype-interaction.check b/tests/patmat/andtype-opentype-interaction.check index d8ceeee3c80d..cf7ea560f42d 100644 --- a/tests/patmat/andtype-opentype-interaction.check +++ b/tests/patmat/andtype-opentype-interaction.check @@ -1,7 +1,7 @@ -23: Pattern Match Exhaustivity: _: SealedClass & OpenTrait, _: AbstractClass & OpenTrait, _: Clazz & OpenTrait, _: Trait & OpenTrait -27: Pattern Match Exhaustivity: _: SealedClass & OpenTrait & OpenTrait2, _: AbstractClass & OpenTrait & OpenTrait2, _: Clazz & OpenTrait & OpenTrait2, _: Trait & OpenTrait & OpenTrait2 -31: Pattern Match Exhaustivity: _: Trait & OpenClass -35: Pattern Match Exhaustivity: _: Trait & OpenTrait & OpenClass +23: Pattern Match Exhaustivity: _: SealedAbstractClass & OpenTrait, _: SealedClass & OpenTrait, _: SealedTrait & OpenTrait, _: AbstractClass & OpenTrait, _: Clazz & OpenTrait, _: Trait & OpenTrait +27: Pattern Match Exhaustivity: _: SealedAbstractClass & OpenTrait & OpenTrait2, _: SealedClass & OpenTrait & OpenTrait2, _: SealedTrait & OpenTrait & OpenTrait2, _: AbstractClass & OpenTrait & OpenTrait2, _: Clazz & OpenTrait & OpenTrait2, _: Trait & OpenTrait & OpenTrait2 +31: Pattern Match Exhaustivity: _: SealedTrait & OpenClass, _: Trait & OpenClass +35: Pattern Match Exhaustivity: _: SealedTrait & OpenTrait & OpenClass, _: Trait & OpenTrait & OpenClass 40: Match case Unreachable -43: Pattern Match Exhaustivity: _: Trait & OpenAbstractClass -47: Pattern Match Exhaustivity: _: Trait & OpenClass & OpenTrait & OpenClassSubclass +43: Pattern Match Exhaustivity: _: SealedTrait & OpenAbstractClass, _: Trait & OpenAbstractClass +47: Pattern Match Exhaustivity: _: SealedTrait & OpenClass & OpenTrait & OpenClassSubclass, _: Trait & OpenClass & OpenTrait & OpenClassSubclass diff --git a/tests/patmat/patmatexhaust.check b/tests/patmat/patmatexhaust.check index e5e7ac397383..28927e2fedeb 100644 --- a/tests/patmat/patmatexhaust.check +++ b/tests/patmat/patmatexhaust.check @@ -4,6 +4,7 @@ 49: Pattern Match Exhaustivity: _: Gp 59: Pattern Match Exhaustivity: Nil 75: Pattern Match Exhaustivity: _: B +87: Pattern Match Exhaustivity: _: C1 100: Pattern Match Exhaustivity: _: C1 114: Pattern Match Exhaustivity: D2(), D1 126: Pattern Match Exhaustivity: _: C1 diff --git a/tests/patmat/patmatexhaust.scala b/tests/patmat/patmatexhaust.scala index 26f0c12a919c..0649620d31ef 100644 --- a/tests/patmat/patmatexhaust.scala +++ b/tests/patmat/patmatexhaust.scala @@ -84,7 +84,7 @@ class TestSealedExhaustive { // compile only case class C3() extends C case object C4 extends C - def ma10(x: C) = x match { // exhaustive: abstract sealed C1 is dead end. + def ma10(x: C) = x match { // treat abstract sealed C1 is as inhabited. case C3() => true case C2 | C4 => true } diff --git a/tests/patmat/t8511.check b/tests/patmat/t8511.check index 6f63f1040f5b..121e0ab874e0 100644 --- a/tests/patmat/t8511.check +++ b/tests/patmat/t8511.check @@ -1 +1 @@ -18: Pattern Match Exhaustivity: Baz(), Bar(_) +18: Pattern Match Exhaustivity: EatsExhaustiveWarning(_), Baz(), Bar(_) diff --git a/tests/patmat/t9677.check b/tests/patmat/t9677.check deleted file mode 100644 index 3d9e1c4e2bbb..000000000000 --- a/tests/patmat/t9677.check +++ /dev/null @@ -1 +0,0 @@ -20: Match case Unreachable