diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 7410d617c4a0..1ee402deded0 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -337,13 +337,6 @@ object SpaceEngine { case pat: Ident if isBackquoted(pat) => Typ(pat.tpe, decomposed = false) - case Ident(nme.WILDCARD) => - val tp = pat.tpe.stripAnnots.widenSkolem - val isNullable = tp.isInstanceOf[FlexibleType] || tp.classSymbol.isNullableClass - val tpSpace = Typ(erase(tp, isValue = true), decomposed = false) - if isNullable then Or(tpSpace :: nullSpace :: Nil) - else tpSpace - case Ident(_) | Select(_, _) => Typ(erase(pat.tpe.stripAnnots.widenSkolem, isValue = true), decomposed = false) @@ -716,7 +709,6 @@ object SpaceEngine { else NoType }.filter(_.exists) parts - case tp: FlexibleType => List(tp.underlying, ConstantType(Constant(null))) case _ => ListOfNoType end rec @@ -939,11 +931,15 @@ object SpaceEngine { then project(OrType(selTyp, ConstantType(Constant(null)), soft = false)) else project(selTyp) var hadNullOnly = false + def projectPat(pat: Tree): Space = + // Project toplevel wildcard pattern to nullable + if isNullable && isWildcardArg(pat) then Or(project(pat) :: nullSpace :: Nil) + else project(pat) @tailrec def recur(cases: List[CaseDef], prevs: List[Space], deferred: List[Tree]): Unit = cases match case Nil => case CaseDef(pat, guard, _) :: rest => - val curr = trace(i"project($pat)")(project(pat)) + val curr = trace(i"project($pat)")(projectPat(pat)) val covered = trace("covered")(simplify(intersect(curr, targetSpace))) val prev = trace("prev")(simplify(Or(prevs))) if prev == Empty && covered == Empty then // defer until a case is reachable diff --git a/tests/patmat/i12530.check b/tests/patmat/i12530.check index b0605bcd95e5..636347516cbc 100644 --- a/tests/patmat/i12530.check +++ b/tests/patmat/i12530.check @@ -1 +1,2 @@ 6: Match case Unreachable +14: Match case Unreachable diff --git a/tests/patmat/null.check b/tests/patmat/null.check index da081e6b56c0..3b860ddfd850 100644 --- a/tests/patmat/null.check +++ b/tests/patmat/null.check @@ -1,4 +1,4 @@ 6: Match case Unreachable 13: Pattern Match -18: Match case Unreachable 20: Pattern Match +21: Match case Unreachable diff --git a/tests/patmat/null.scala b/tests/patmat/null.scala index b918109c0cc5..9cff29a5c4e8 100644 --- a/tests/patmat/null.scala +++ b/tests/patmat/null.scala @@ -18,5 +18,6 @@ class Test { case Some(null) => case None => case y => + case _ => } } \ No newline at end of file diff --git a/tests/warn/i20121.scala b/tests/warn/i20121.scala index b8402fa808ac..ce8e3e4d74f6 100644 --- a/tests/warn/i20121.scala +++ b/tests/warn/i20121.scala @@ -5,8 +5,8 @@ case class CC_B[A](a: A) extends T_A[A, X] val v_a: T_A[X, X] = CC_B(null) val v_b = v_a match - case CC_B(_) => 0 - case _ => 1 // warn: null only + case CC_B(_) => 0 // warn: unreachable + case _ => 1 // for CC_B[A] to match T_A[X, X] // A := X // so require X, aka T_A[Byte, Byte] diff --git a/tests/warn/i20122.scala b/tests/warn/i20122.scala index d035a18d3b09..50da42a5926c 100644 --- a/tests/warn/i20122.scala +++ b/tests/warn/i20122.scala @@ -7,7 +7,7 @@ case class CC_E(a: CC_C[Char, Byte]) val v_a: T_B[Int, CC_A] = CC_B(CC_E(CC_C(null))) val v_b = v_a match - case CC_B(CC_E(CC_C(_))) => 0 + case CC_B(CC_E(CC_C(_))) => 0 // warn: unreachable case _ => 1 // for CC_B[A, C] to match T_B[C, CC_A] // C <: Int, ok diff --git a/tests/warn/i20123.scala b/tests/warn/i20123.scala index 0af7aba5a3a5..32de903210b2 100644 --- a/tests/warn/i20123.scala +++ b/tests/warn/i20123.scala @@ -8,7 +8,7 @@ case class CC_G[A, C](c: C) extends T_A[A, C] val v_a: T_A[Boolean, T_B[Boolean]] = CC_G(null) val v_b = v_a match { case CC_D() => 0 - case CC_G(_) => 1 + case CC_G(_) => 1 // warn: unreachable // for CC_G[A, C] to match T_A[Boolean, T_B[Boolean]] // A := Boolean, which is ok // C := T_B[Boolean],