Skip to content

Commit 7fe6b8b

Browse files
authored
Backport recent exhaustivity fixes (#16578)
Backports #16051 and #16168
2 parents 6059da4 + 99ba2a3 commit 7fe6b8b

File tree

8 files changed

+79
-0
lines changed

8 files changed

+79
-0
lines changed

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,10 @@ object TypeOps:
869869
}
870870

871871
def instantiate(): Type = {
872+
// if there's a change in variance in type parameters (between subtype tp1 and supertype tp2)
873+
// then we don't want to maximise the type variables in the wrong direction.
874+
// For instance 15967, A[-Z] and B[Y] extends A[Y], we don't want to maximise Y to Any
875+
maximizeType(protoTp1.baseType(tp2.classSymbol), NoSpan)
872876
maximizeType(protoTp1, NoSpan)
873877
wildApprox(protoTp1)
874878
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ object SpaceEngine {
306306
val isEmptyTp = extractorMemberType(unappResult, nme.isEmpty, NoSourcePosition)
307307
isEmptyTp <:< ConstantType(Constant(false))
308308
}
309+
|| unappResult.derivesFrom(defn.NonEmptyTupleClass)
309310
}
310311

311312
/** Is the unapply or unapplySeq irrefutable?

tests/neg/i15991.abstract.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
object Foo:
2+
def unapply[T <: Tuple](tup: T): String *: String *: T =
3+
"a" *: "b" *: tup
4+
5+
// like {pos,neg}/i15991, but with an abstract tuple tail
6+
class Test:
7+
val tup2: String *: String *: EmptyTuple = ("c", "d")
8+
9+
def test3 =
10+
val Foo(x, y, z) = tup2 // error: Wrong number of argument patterns for Foo; expected: (String, String, String, String)
11+
x + y + z
12+
13+
def test3a =
14+
val x1x = tup2 match
15+
case Foo(x, y, z) => // error: Wrong number of argument patterns for Foo; expected: (String, String, String, String)
16+
(x, y, z)
17+
val x = x1x._1
18+
val y = x1x._2
19+
val z = x1x._3
20+
x + y + z

tests/neg/i15991.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object Foo:
2+
def unapply(x: Any): String *: String *: EmptyTuple = ("a", "b")
3+
4+
class Test:
5+
def test =
6+
val Foo(x, y, z) = 1 // error: Wrong number of argument patterns for Foo; expected: (String, String)
7+
x + y + z

tests/pos/i15967.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// scalac: -Werror
2+
sealed trait A[-Z]
3+
final case class B[Y]() extends A[Y]
4+
5+
class Test:
6+
def t1[X](a: A[X]) = a match // was inexhaustive
7+
case _: B[X] @unchecked =>
8+
9+
//def t2[X](a: A[X]) = a match // was inexhaustive
10+
// case _: B[X] => // expected unchecked warning

tests/pos/i15991.abstract.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
object Foo:
2+
def unapply[T <: Tuple](tup: T): String *: String *: T =
3+
"a" *: "b" *: tup
4+
5+
// like {pos,neg}/i15991, but with an abstract tuple tail
6+
class Test:
7+
val tup2: String *: String *: EmptyTuple = ("c", "d")
8+
9+
def test2 =
10+
val Foo(x, y, _, _) = tup2
11+
x + y
12+
13+
// like test2, but as the desugaring of what PatternDef's become
14+
def test2b =
15+
val x1x = tup2 match
16+
case Foo(x, y, _, _) =>
17+
(x, y)
18+
val x = x1x._1
19+
val y = x1x._2
20+
x + y

tests/pos/i15991.orig.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class Foo
2+
3+
object Foo:
4+
// def unapply(f: Foo): (Int, Int) = ??? // does not raise a warning
5+
def unapply(f: Foo): Int *: Int *: EmptyTuple = ???
6+
7+
@main def example =
8+
val Foo(x, y) = new Foo
9+
println(x)

tests/pos/i15991.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Foo:
2+
def unapply(x: Any): String *: String *: EmptyTuple =
3+
("a", "b")
4+
5+
class Test:
6+
def test =
7+
val Foo(x, y) = 1
8+
x + y

0 commit comments

Comments
 (0)