Skip to content

Commit d05e600

Browse files
committed
Don't peoject nested wildcard pattern to nullable
1 parent 896965c commit d05e600

File tree

4 files changed

+9
-13
lines changed

4 files changed

+9
-13
lines changed

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

+5-9
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,6 @@ object SpaceEngine {
337337
case pat: Ident if isBackquoted(pat) =>
338338
Typ(pat.tpe, decomposed = false)
339339

340-
case Ident(nme.WILDCARD) =>
341-
val tp = pat.tpe.stripAnnots.widenSkolem
342-
val isNullable = tp.isInstanceOf[FlexibleType] || tp.classSymbol.isNullableClass
343-
val tpSpace = Typ(erase(tp, isValue = true), decomposed = false)
344-
if isNullable then Or(tpSpace :: nullSpace :: Nil)
345-
else tpSpace
346-
347340
case Ident(_) | Select(_, _) =>
348341
Typ(erase(pat.tpe.stripAnnots.widenSkolem, isValue = true), decomposed = false)
349342

@@ -716,7 +709,6 @@ object SpaceEngine {
716709
else NoType
717710
}.filter(_.exists)
718711
parts
719-
case tp: FlexibleType => List(tp.underlying, ConstantType(Constant(null)))
720712
case _ => ListOfNoType
721713
end rec
722714

@@ -939,11 +931,15 @@ object SpaceEngine {
939931
then project(OrType(selTyp, ConstantType(Constant(null)), soft = false))
940932
else project(selTyp)
941933
var hadNullOnly = false
934+
def projectPat(pat: Tree): Space =
935+
// Project toplevel wildcard pattern to nullable
936+
if isNullable && isWildcardArg(pat) then Or(project(pat) :: nullSpace :: Nil)
937+
else project(pat)
942938
@tailrec def recur(cases: List[CaseDef], prevs: List[Space], deferred: List[Tree]): Unit =
943939
cases match
944940
case Nil =>
945941
case CaseDef(pat, guard, _) :: rest =>
946-
val curr = trace(i"project($pat)")(project(pat))
942+
val curr = trace(i"project($pat)")(projectPat(pat))
947943
val covered = trace("covered")(simplify(intersect(curr, targetSpace)))
948944
val prev = trace("prev")(simplify(Or(prevs)))
949945
if prev == Empty && covered == Empty then // defer until a case is reachable

tests/warn/i20121.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ case class CC_B[A](a: A) extends T_A[A, X]
55

66
val v_a: T_A[X, X] = CC_B(null)
77
val v_b = v_a match
8-
case CC_B(_) => 0
9-
case _ => 1 // warn: null only
8+
case CC_B(_) => 0 // warn: unreachable
9+
case _ => 1
1010
// for CC_B[A] to match T_A[X, X]
1111
// A := X
1212
// so require X, aka T_A[Byte, Byte]

tests/warn/i20122.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ case class CC_E(a: CC_C[Char, Byte])
77

88
val v_a: T_B[Int, CC_A] = CC_B(CC_E(CC_C(null)))
99
val v_b = v_a match
10-
case CC_B(CC_E(CC_C(_))) => 0
10+
case CC_B(CC_E(CC_C(_))) => 0 // warn: unreachable
1111
case _ => 1
1212
// for CC_B[A, C] to match T_B[C, CC_A]
1313
// C <: Int, ok

tests/warn/i20123.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ case class CC_G[A, C](c: C) extends T_A[A, C]
88
val v_a: T_A[Boolean, T_B[Boolean]] = CC_G(null)
99
val v_b = v_a match {
1010
case CC_D() => 0
11-
case CC_G(_) => 1
11+
case CC_G(_) => 1 // warn: unreachable
1212
// for CC_G[A, C] to match T_A[Boolean, T_B[Boolean]]
1313
// A := Boolean, which is ok
1414
// C := T_B[Boolean],

0 commit comments

Comments
 (0)