Skip to content

Commit 2252d78

Browse files
committed
Make space intersection of two open types non-empty
1 parent 07285c0 commit 2252d78

File tree

5 files changed

+68
-0
lines changed

5 files changed

+68
-0
lines changed

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ trait SpaceLogic {
7474
/** Is `tp1` the same type as `tp2`? */
7575
def isEqualType(tp1: Type, tp2: Type): Boolean
7676

77+
/** Can `tp` be arbitrarily subtyped by any other open type? */
78+
def isOpen(tp: Type): Boolean
79+
80+
/** Construct a space which contains values from both `tp1` and `tp2`.
81+
*
82+
* Both types are expected to be open in the [[isOpen]] sense.
83+
*/
84+
def commonOpenTypeSpace(tp1: Type, tp2: Type): Space
85+
7786
/** Is the type `tp` decomposable? i.e. all values of the type can be covered
7887
* by its decomposed types.
7988
*
@@ -171,6 +180,7 @@ trait SpaceLogic {
171180
else if (isSubType(tp2, tp1)) b
172181
else if (canDecompose(tp1)) tryDecompose1(tp1)
173182
else if (canDecompose(tp2)) tryDecompose2(tp2)
183+
else if (isOpen(tp1) && isOpen(tp2)) commonOpenTypeSpace(tp1, tp2)
174184
else Empty
175185
case (Typ(tp1, _), Kon(tp2, ss)) =>
176186
if (isSubType(tp2, tp1)) b
@@ -243,6 +253,11 @@ trait SpaceLogic {
243253
class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
244254
import tpd._
245255

256+
override def isOpen(tp: Type) =
257+
!tp.classSymbol.is(Sealed | Final) && !tp.termSymbol.is(Module)
258+
259+
override def commonOpenTypeSpace(tp1: Type, tp2: Type) = Typ(AndType(tp1, tp2), true)
260+
246261
/** Return the space that represents the pattern `pat`
247262
*
248263
* If roundUp is true, approximate extractors to its type,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
19: Pattern Match Exhaustivity: _: AbstractClass & OpenTrait, _: Clazz & OpenTrait, _: Trait & OpenTrait
2+
23: Pattern Match Exhaustivity: _: AbstractClass & OpenClass, _: Clazz & OpenClass, _: Trait & OpenClass
3+
27: Pattern Match Exhaustivity: _: AbstractClass & OpenAbstractClass, _: Clazz & OpenAbstractClass, _: Trait & OpenAbstractClass
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
sealed trait T
2+
trait Trait extends T
3+
class Clazz extends T
4+
abstract class AbstractClass extends T
5+
// none of the below can be extended
6+
sealed trait SealedTrait extends T
7+
final class FinalClass extends T
8+
sealed class SealedClass extends T
9+
sealed abstract class SealedAbstractClass extends T
10+
object Obj extends T
11+
12+
trait OpenTrait
13+
class OpenClass
14+
abstract class OpenAbstractClass
15+
16+
trait Unrelated
17+
18+
object Test {
19+
def m1(s: T & OpenTrait) = s match {
20+
case _: Unrelated => ;
21+
}
22+
23+
def m2(s: T & OpenClass) = s match {
24+
case _: Unrelated => ;
25+
}
26+
27+
def m3(s: T & OpenAbstractClass) = s match {
28+
case _: Unrelated => ;
29+
}
30+
}

tests/patmat/nontrivial-andtype.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
16: Pattern Match Exhaustivity: D, _: C, B(), _: A

tests/patmat/nontrivial-andtype.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
object Test {
2+
sealed trait Marker
3+
trait M1 extends Marker
4+
sealed trait Marker2 extends Marker
5+
sealed trait M2 extends Marker2
6+
7+
sealed trait T
8+
trait A extends T with M2
9+
sealed trait T2 extends T
10+
case class B() extends T2 with Marker
11+
class C extends T2 with M1
12+
case object D extends T2 with Marker
13+
14+
trait Unrelated
15+
16+
def m1(s: T & Marker) = s match {
17+
case _: Unrelated => ;
18+
}
19+
}

0 commit comments

Comments
 (0)