Skip to content

Commit

Permalink
Teach SpaceEngine that generic tuples are irrefutable
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand authored and Kordyjan committed Dec 22, 2022
1 parent 0d79780 commit 99ba2a3
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 0 deletions.
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ object SpaceEngine {
val isEmptyTp = extractorMemberType(unappResult, nme.isEmpty, NoSourcePosition)
isEmptyTp <:< ConstantType(Constant(false))
}
|| unappResult.derivesFrom(defn.NonEmptyTupleClass)
}

/** Is the unapply or unapplySeq irrefutable?
Expand Down
20 changes: 20 additions & 0 deletions tests/neg/i15991.abstract.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
object Foo:
def unapply[T <: Tuple](tup: T): String *: String *: T =
"a" *: "b" *: tup

// like {pos,neg}/i15991, but with an abstract tuple tail
class Test:
val tup2: String *: String *: EmptyTuple = ("c", "d")

def test3 =
val Foo(x, y, z) = tup2 // error: Wrong number of argument patterns for Foo; expected: (String, String, String, String)
x + y + z

def test3a =
val x1x = tup2 match
case Foo(x, y, z) => // error: Wrong number of argument patterns for Foo; expected: (String, String, String, String)
(x, y, z)
val x = x1x._1
val y = x1x._2
val z = x1x._3
x + y + z
7 changes: 7 additions & 0 deletions tests/neg/i15991.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
object Foo:
def unapply(x: Any): String *: String *: EmptyTuple = ("a", "b")

class Test:
def test =
val Foo(x, y, z) = 1 // error: Wrong number of argument patterns for Foo; expected: (String, String)
x + y + z
20 changes: 20 additions & 0 deletions tests/pos/i15991.abstract.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
object Foo:
def unapply[T <: Tuple](tup: T): String *: String *: T =
"a" *: "b" *: tup

// like {pos,neg}/i15991, but with an abstract tuple tail
class Test:
val tup2: String *: String *: EmptyTuple = ("c", "d")

def test2 =
val Foo(x, y, _, _) = tup2
x + y

// like test2, but as the desugaring of what PatternDef's become
def test2b =
val x1x = tup2 match
case Foo(x, y, _, _) =>
(x, y)
val x = x1x._1
val y = x1x._2
x + y
9 changes: 9 additions & 0 deletions tests/pos/i15991.orig.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Foo

object Foo:
// def unapply(f: Foo): (Int, Int) = ??? // does not raise a warning
def unapply(f: Foo): Int *: Int *: EmptyTuple = ???

@main def example =
val Foo(x, y) = new Foo
println(x)
8 changes: 8 additions & 0 deletions tests/pos/i15991.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
object Foo:
def unapply(x: Any): String *: String *: EmptyTuple =
("a", "b")

class Test:
def test =
val Foo(x, y) = 1
x + y

0 comments on commit 99ba2a3

Please sign in to comment.