Skip to content

Commit ac1a641

Browse files
committed
Teach SpaceEngine that generic tuples are irrefutable
1 parent 684ae79 commit ac1a641

File tree

6 files changed

+65
-0
lines changed

6 files changed

+65
-0
lines changed

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

+1
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

+20
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

+7
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/i15991.abstract.scala

+20
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

+9
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

+8
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)