From ca468b39222dfd44501ecc201d7b6abe4d86b770 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 1 Mar 2022 18:05:59 +0000 Subject: [PATCH 1/2] Ignore private/sealed abstract class/traits --- .../src/dotty/tools/dotc/transform/patmat/Space.scala | 8 +++++++- tests/patmat/i14579.scala | 10 ++++++++++ tests/patmat/patmatexhaust.check | 1 - tests/patmat/patmatexhaust.scala | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 tests/patmat/i14579.scala diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index e69f563de149..391d1d8670fb 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -628,7 +628,13 @@ class SpaceEngine(using Context) extends SpaceLogic { case tp if tp.classSymbol.isAllOf(JavaEnumTrait) => tp.classSymbol.children.map(sym => Typ(sym.termRef, true)) case tp => - val children = tp.classSymbol.children + def getChildren(sym: Symbol): List[Symbol] = + sym.children.flatMap { child => + if child eq sym then Nil // i3145: sealed trait Baz, val x = new Baz {}, Baz.children returns Baz... + else if (child.is(Private) || child.is(Sealed)) && child.isOneOf(AbstractOrTrait) then getChildren(child) + else List(child) + } + val children = getChildren(tp.classSymbol) debug.println(s"candidates for ${tp.show} : [${children.map(_.show).mkString(", ")}]") val parts = children.map { sym => diff --git a/tests/patmat/i14579.scala b/tests/patmat/i14579.scala new file mode 100644 index 000000000000..f20ecde2292b --- /dev/null +++ b/tests/patmat/i14579.scala @@ -0,0 +1,10 @@ +trait A { + sealed abstract class X + private class X1 extends X with X2 { } + private trait X2 extends X + sealed trait X3 extends X + + def f(x: X) = x match { + case _: X1 => 0 + } +} \ No newline at end of file diff --git a/tests/patmat/patmatexhaust.check b/tests/patmat/patmatexhaust.check index 14fec2622f64..ee7187ee4b62 100644 --- a/tests/patmat/patmatexhaust.check +++ b/tests/patmat/patmatexhaust.check @@ -5,7 +5,6 @@ 53: 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: D1, D2() 126: Pattern Match Exhaustivity: _: C1 diff --git a/tests/patmat/patmatexhaust.scala b/tests/patmat/patmatexhaust.scala index 8e6b3196cd5f..40c8c139ee54 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 { // treat abstract sealed C1 is as inhabited. + def ma10(x: C) = x match { // exhaustive: abstract sealed C1 is dead end. case C3() => true case C2 | C4 => true } From 9e3f86aefbb7d709b624f06f4b36b5077db46c53 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 1 Mar 2022 22:19:08 +0000 Subject: [PATCH 2/2] Special-case Tuple/NonEmptyTuple because they're so, so special --- compiler/src/dotty/tools/dotc/transform/patmat/Space.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 391d1d8670fb..e957f11d009b 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -631,6 +631,8 @@ class SpaceEngine(using Context) extends SpaceLogic { def getChildren(sym: Symbol): List[Symbol] = sym.children.flatMap { child => if child eq sym then Nil // i3145: sealed trait Baz, val x = new Baz {}, Baz.children returns Baz... + else if tp.classSymbol == defn.TupleClass || tp.classSymbol == defn.NonEmptyTupleClass then + List(child) // TupleN and TupleXXL classes are used for Tuple, but they aren't Tuple's children else if (child.is(Private) || child.is(Sealed)) && child.isOneOf(AbstractOrTrait) then getChildren(child) else List(child) }