Skip to content

Commit 48dffca

Browse files
noti0na1tgodzik
authored andcommitted
Don't peoject nested wildcard pattern to nullable
1 parent 69d6716 commit 48dffca

File tree

6 files changed

+55
-5
lines changed

6 files changed

+55
-5
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ object SpaceEngine {
113113
def isSubspace(a: Space, b: Space)(using Context): Boolean = a.isSubspace(b)
114114
def canDecompose(typ: Typ)(using Context): Boolean = typ.canDecompose
115115
def decompose(typ: Typ)(using Context): List[Typ] = typ.decompose
116+
def nullSpace(using Context): Space = Typ(ConstantType(Constant(null)), decomposed = false)
116117

117118
/** Simplify space such that a space equal to `Empty` becomes `Empty` */
118119
def computeSimplify(space: Space)(using Context): Space = trace(i"simplify($space)")(space match {
@@ -690,7 +691,6 @@ object SpaceEngine {
690691
else NoType
691692
}.filter(_.exists)
692693
parts
693-
694694
case _ => ListOfNoType
695695
end rec
696696

@@ -904,6 +904,10 @@ object SpaceEngine {
904904
then project(OrType(selTyp, ConstantType(Constant(null)), soft = false))
905905
else project(selTyp)
906906
)
907+
def projectPat(pat: Tree): Space =
908+
// Project toplevel wildcard pattern to nullable
909+
if isNullable && isWildcardArg(pat) then Or(project(pat) :: nullSpace :: Nil)
910+
else project(pat)
907911

908912
var i = 0
909913
val len = cases.length
@@ -913,7 +917,7 @@ object SpaceEngine {
913917
while (i < len) {
914918
val CaseDef(pat, guard, _) = cases(i)
915919

916-
val curr = trace(i"project($pat)")(project(pat))
920+
val curr = trace(i"project($pat)")(projectPat(pat))
917921

918922
val covered = trace("covered")(simplify(intersect(curr, targetSpace)))
919923

tests/warn/i15503d.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ val a = Sum(S(S(Z)),Z) match {
1616
case Sum(a@S(b@S(_)), Z) => a // warn
1717
case Sum(a@S(b@(S(_))), Z) => Sum(a,b) // warn unreachable
1818
case Sum(_,_) => Z // OK
19-
case _ => Z // warn unreachable
19+
case _ => Z
2020
}
2121

2222
// todo : This should pass in the future

tests/warn/i20121.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
sealed trait T_A[A, B]
2+
type X = T_A[Byte, Byte]
3+
4+
case class CC_B[A](a: A) extends T_A[A, X]
5+
6+
val v_a: T_A[X, X] = CC_B(null)
7+
val v_b = v_a match
8+
case CC_B(_) => 0 // warn: unreachable
9+
case _ => 1
10+
// for CC_B[A] to match T_A[X, X]
11+
// A := X
12+
// so require X, aka T_A[Byte, Byte]
13+
// which isn't instantiable, outside of null

tests/warn/i20122.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
sealed trait T_B[C, D]
2+
3+
case class CC_A()
4+
case class CC_B[A, C](a: A) extends T_B[C, CC_A]
5+
case class CC_C[C, D](a: T_B[C, D]) extends T_B[Int, CC_A]
6+
case class CC_E(a: CC_C[Char, Byte])
7+
8+
val v_a: T_B[Int, CC_A] = CC_B(CC_E(CC_C(null)))
9+
val v_b = v_a match
10+
case CC_B(CC_E(CC_C(_))) => 0 // warn: unreachable
11+
case _ => 1
12+
// for CC_B[A, C] to match T_B[C, CC_A]
13+
// C <: Int, ok
14+
// A <: CC_E, ok
15+
// but you need a CC_C[Char, Byte]
16+
// which requires a T_B[Char, Byte]
17+
// which isn't instantiable, outside of null

tests/warn/i20123.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sealed trait T_A[A, B]
2+
sealed trait T_B[C]
3+
4+
case class CC_D[A, C]() extends T_A[A, C]
5+
case class CC_E() extends T_B[Nothing]
6+
case class CC_G[A, C](c: C) extends T_A[A, C]
7+
8+
val v_a: T_A[Boolean, T_B[Boolean]] = CC_G(null)
9+
val v_b = v_a match {
10+
case CC_D() => 0
11+
case CC_G(_) => 1 // warn: unreachable
12+
// for CC_G[A, C] to match T_A[Boolean, T_B[Boolean]]
13+
// A := Boolean, which is ok
14+
// C := T_B[Boolean],
15+
// which isn't instantiable, outside of null
16+
}

tests/warn/t2755.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ object Test {
1919
case x: Array[String] => x.size
2020
case x: Array[AnyRef] => 5
2121
case x: Array[?] => 6
22-
case _ => 7 // warn: only null is matched
22+
case _ => 7
2323
}
2424
def f3[T](a: Array[T]) = a match {
2525
case x: Array[Int] => x(0)
@@ -28,7 +28,7 @@ object Test {
2828
case x: Array[String] => x.size
2929
case x: Array[AnyRef] => 5
3030
case x: Array[?] => 6
31-
case _ => 7 // warn: only null is matched
31+
case _ => 7
3232
}
3333

3434

0 commit comments

Comments
 (0)