Skip to content

Commit 62ffcd5

Browse files
committed
Fix Tuples to work with non-variant match types
The run-test-picklin.blacklist got a new entry where before and after pickling differ in whether a match type is reduced or not. It's currently not clear how to write pickling tests that are independent of this detail.
1 parent 16e21d9 commit 62ffcd5

File tree

5 files changed

+31
-30
lines changed

5 files changed

+31
-30
lines changed

compiler/test-resources/repl/i5218

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
scala> val tuple = (1, "2", 3L)
22
val tuple: (Int, String, Long) = (1,2,3)
33
scala> 0.0 *: tuple
4-
val res0: Double *: (Int, String, Long)(tuple) = (0.0,1,2,3)
4+
val res0: (Double, Int, String, Long) = (0.0,1,2,3)
55
scala> tuple ++ tuple
66
val res1: Int *: String *: Long *:
77
scala.Tuple.Concat[Unit, (Int, String, Long)(tuple)] = (1,2,3,1,2,3)

compiler/test/dotc/run-test-pickling.blacklist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ t3452g
55
t7374
66
tuples1.scala
77
tuples1a.scala
8+
typeclass-derivation1.scala
89
typeclass-derivation2.scala
910
typeclass-derivation2a.scala
1011
typeclass-derivation3.scala

library/src-bootstrapped/scala/StagedTuple.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ object StagedTuple {
122122
}
123123

124124
def applyStaged[Tup <: NonEmptyTuple : Type, N <: Int : Type](tup: Expr[Tup], size: Option[Int], n: Expr[N], nValue: Option[Int]): Expr[Elem[Tup, N]] = {
125-
if (!specialize) '{dynamicApply($tup, $n)}
125+
if (!specialize) '{dynamicApply($tup, $n)}.asInstanceOf // TODO: check that variance is OK here
126126
else {
127127
def fallbackApply(): Expr[Elem[Tup, N]] = nValue match {
128128
case Some(n) => quoted.QuoteError("index out of bounds: " + n)
129-
case None => '{dynamicApply($tup, $n)}
129+
case None => '{dynamicApply($tup, $n)}.asInstanceOf // TODO: check that variance is OK here
130130
}
131131
val res = size match {
132132
case Some(1) =>

library/src-bootstrapped/scala/Tuple.scala

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ sealed trait Tuple extends Any {
3434
inline def stagedToArray: Array[Object] =
3535
${ StagedTuple.toArrayStaged('this, constValueOpt[BoundedSize[this.type]]) }
3636

37-
inline def *: [H] (x: H): H *: this.type =
37+
inline def *: [H, This >: this.type <: Tuple] (x: H): H *: This =
3838
if (stageIt) stagedCons[H](x)
3939
else {
40-
type Result = H *: this.type
40+
type Result = H *: This
4141
inline constValueOpt[BoundedSize[this.type]] match {
4242
case Some(0) =>
4343
Tuple1(x).asInstanceOf[Result]
@@ -53,19 +53,19 @@ sealed trait Tuple extends Any {
5353
val t = asInstanceOf[Tuple4[_, _, _, _]]
5454
Tuple5(x, t._1, t._2, t._3, t._4).asInstanceOf[Result]
5555
case Some(n) =>
56-
fromArray[Result](cons$Array(x, toArray))
56+
fromArray[H *: this.type](cons$Array(x, toArray))
5757
case _ =>
58-
dynamic_*:[this.type, H](this, x)
58+
dynamic_*:[This, H](this, x)
5959
}
6060
}
6161

6262
inline def stagedCons[H] (x: H): H *: this.type =
6363
${ StagedTuple.stagedCons('this, 'x, constValueOpt[BoundedSize[this.type]]) }
6464

65-
inline def ++(that: Tuple): Concat[this.type, that.type] =
66-
if (stageIt) stagedConcat(that)
65+
inline def ++ [This >: this.type <: Tuple](that: Tuple): Concat[This, that.type] =
66+
if (stageIt) stagedConcat(that).asInstanceOf
6767
else {
68-
type Result = Concat[this.type, that.type]
68+
type Result = Concat[This, that.type]
6969
inline constValueOpt[BoundedSize[this.type]] match {
7070
case Some(0) =>
7171
that.asInstanceOf[Result]
@@ -99,7 +99,7 @@ sealed trait Tuple extends Any {
9999
if (constValue[BoundedSize[that.type]] == 0) this.asInstanceOf[Result]
100100
else genericConcat[Result](this, that).asInstanceOf[Result]
101101
case None =>
102-
dynamic_++[this.type, that.type](this, that)
102+
dynamic_++[This, that.type](this, that)
103103
}
104104
}
105105

@@ -110,10 +110,10 @@ sealed trait Tuple extends Any {
110110
inline def genericConcat[T <: Tuple](xs: Tuple, ys: Tuple): Tuple =
111111
fromArray[T](xs.toArray ++ ys.toArray)
112112

113-
inline def size: Size[this.type] =
114-
if (stageIt) stagedSize
113+
inline def size[This >: this.type <: Tuple]: Size[This] =
114+
if (stageIt) stagedSize.asInstanceOf
115115
else {
116-
type Result = Size[this.type]
116+
type Result = Size[This]
117117
inline constValueOpt[BoundedSize[this.type]] match {
118118
case Some(n) => n.asInstanceOf[Result]
119119
case _ => dynamicSize(this)
@@ -130,28 +130,28 @@ object Tuple {
130130

131131
final val stageIt = false
132132

133-
type Head[+X <: NonEmptyTuple] = X match {
133+
type Head[X <: NonEmptyTuple] = X match {
134134
case x *: _ => x
135135
}
136136

137-
type Tail[+X <: NonEmptyTuple] <: Tuple = X match {
137+
type Tail[X <: NonEmptyTuple] <: Tuple = X match {
138138
case _ *: xs => xs
139139
}
140140

141-
type Concat[+X <: Tuple, +Y <: Tuple] <: Tuple = X match {
141+
type Concat[X <: Tuple, +Y <: Tuple] <: Tuple = X match {
142142
case Unit => Y
143143
case x1 *: xs1 => x1 *: Concat[xs1, Y]
144144
}
145145

146-
type Elem[+X <: Tuple, +N] = X match {
146+
type Elem[X <: Tuple, N] = X match {
147147
case x *: xs =>
148148
N match {
149149
case 0 => x
150150
case S[n1] => Elem[xs, n1]
151151
}
152152
}
153153

154-
type Size[+X] <: Int = X match {
154+
type Size[X] <: Int = X match {
155155
case Unit => 0
156156
case x *: xs => S[Size[xs]]
157157
}
@@ -311,10 +311,10 @@ sealed trait NonEmptyTuple extends Tuple {
311311
import Tuple._
312312
import NonEmptyTuple._
313313

314-
inline def head: Head[this.type] =
315-
if (stageIt) stagedHead
314+
inline def head[This >: this.type <: NonEmptyTuple]: Head[This] =
315+
if (stageIt) stagedHead.asInstanceOf
316316
else {
317-
type Result = Head[this.type]
317+
type Result = Head[This]
318318
val resVal = inline constValueOpt[BoundedSize[this.type]] match {
319319
case Some(1) =>
320320
val t = asInstanceOf[Tuple1[_]]
@@ -342,10 +342,10 @@ sealed trait NonEmptyTuple extends Tuple {
342342
inline def stagedHead: Head[this.type] =
343343
${ StagedTuple.headStaged[this.type]('this, constValueOpt[BoundedSize[this.type]]) }
344344

345-
inline def tail: Tail[this.type] =
346-
if (stageIt) stagedTail
345+
inline def tail[This >: this.type <: NonEmptyTuple]: Tail[This] =
346+
if (stageIt) stagedTail.asInstanceOf
347347
else {
348-
type Result = Tail[this.type]
348+
type Result = Tail[This]
349349
inline constValueOpt[BoundedSize[this.type]] match {
350350
case Some(1) =>
351351
().asInstanceOf[Result]
@@ -364,7 +364,7 @@ sealed trait NonEmptyTuple extends Tuple {
364364
case Some(n) if n > 5 =>
365365
fromArray[Result](toArray.tail)
366366
case None =>
367-
dynamicTail[this.type](this)
367+
dynamicTail[This](this)
368368
}
369369
}
370370

@@ -377,10 +377,10 @@ sealed trait NonEmptyTuple extends Tuple {
377377
case None => dynamicApply[this.type](this, n)
378378
}
379379

380-
inline def apply(n: Int): Elem[this.type, n.type] =
381-
if (stageIt) stagedApply(n)
380+
inline def apply[This >: this.type <: NonEmptyTuple](n: Int): Elem[This, n.type] =
381+
if (stageIt) stagedApply(n).asInstanceOf
382382
else {
383-
type Result = Elem[this.type, n.type]
383+
type Result = Elem[This, n.type]
384384
inline constValueOpt[Size[this.type]] match {
385385
case Some(1) =>
386386
val t = asInstanceOf[Tuple1[_]]

tests/pos/typelevel0.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ object Test extends App {
2828
val tl = xs.tail
2929
val tl2 = xs.tail.tail
3030

31-
type Concat[+Xs <: HList, +Ys <: HList] <: HList = Xs match {
31+
type Concat[Xs <: HList, Ys <: HList] <: HList = Xs match {
3232
case HNil => Ys
3333
case x1 :: xs1 => x1 :: Concat[xs1, Ys]
3434
}

0 commit comments

Comments
 (0)