diff --git a/library/src-bootstrapped/scala/Tuple.scala b/library/src-bootstrapped/scala/Tuple.scala index 622656ab8259..389a47adb4e1 100644 --- a/library/src-bootstrapped/scala/Tuple.scala +++ b/library/src-bootstrapped/scala/Tuple.scala @@ -7,8 +7,7 @@ sealed trait Tuple extends Any { import Tuple._ inline def toArray: Array[Object] = - if (stageIt) toArrayStaged - else inline constValueOpt[BoundedSize[this.type]] match { + inline constValueOpt[BoundedSize[this.type]] match { case Some(0) => scala.runtime.DynamicTuple.empty$Array case Some(1) => @@ -31,101 +30,82 @@ sealed trait Tuple extends Any { runtime.DynamicTuple.dynamicToArray(this) } - inline def toArrayStaged: Array[Object] = - ${ StagedTuple.toArrayStaged('this, constValueOpt[BoundedSize[this.type]]) } - - inline def *: [H, This >: this.type <: Tuple] (x: H): H *: This = - if (stageIt) consStaged[H](x) - else { - type Result = H *: This - inline constValueOpt[BoundedSize[this.type]] match { - case Some(0) => - Tuple1(x).asInstanceOf[Result] - case Some(1) => - Tuple2(x, asInstanceOf[Tuple1[_]]._1).asInstanceOf[Result] - case Some(2) => - val t = asInstanceOf[Tuple2[_, _]] - Tuple3(x, t._1, t._2).asInstanceOf[Result] - case Some(3) => - val t = asInstanceOf[Tuple3[_, _, _]] - Tuple4(x, t._1, t._2, t._3).asInstanceOf[Result] - case Some(4) => - val t = asInstanceOf[Tuple4[_, _, _, _]] - Tuple5(x, t._1, t._2, t._3, t._4).asInstanceOf[Result] - case Some(n) => - fromArray[H *: this.type](cons$Array(x, toArray)) - case _ => - runtime.DynamicTuple.dynamic_*:[This, H](this, x) - } + inline def *: [H, This >: this.type <: Tuple] (x: H): H *: This = { + type Result = H *: This + inline constValueOpt[BoundedSize[this.type]] match { + case Some(0) => + Tuple1(x).asInstanceOf[Result] + case Some(1) => + Tuple2(x, asInstanceOf[Tuple1[_]]._1).asInstanceOf[Result] + case Some(2) => + val t = asInstanceOf[Tuple2[_, _]] + Tuple3(x, t._1, t._2).asInstanceOf[Result] + case Some(3) => + val t = asInstanceOf[Tuple3[_, _, _]] + Tuple4(x, t._1, t._2, t._3).asInstanceOf[Result] + case Some(4) => + val t = asInstanceOf[Tuple4[_, _, _, _]] + Tuple5(x, t._1, t._2, t._3, t._4).asInstanceOf[Result] + case Some(n) => + fromArray[H *: this.type](cons$Array(x, toArray)) + case _ => + runtime.DynamicTuple.dynamic_*:[This, H](this, x) } + } - inline def consStaged[H] (x: H): H *: this.type = - ${ StagedTuple.consStaged('this, 'x, constValueOpt[BoundedSize[this.type]]) } - - inline def ++ [This >: this.type <: Tuple](that: Tuple): Concat[This, that.type] = - if (stageIt) concatStaged(that).asInstanceOf - else { - type Result = Concat[This, that.type] - inline constValueOpt[BoundedSize[this.type]] match { - case Some(0) => - that.asInstanceOf[Result] - case Some(1) => - if (constValue[BoundedSize[that.type]] == 0) this.asInstanceOf[Result] - else (asInstanceOf[Tuple1[_]]._1 *: that).asInstanceOf[Result] - case Some(2) => - val t = asInstanceOf[Tuple2[_, _]] - inline constValue[BoundedSize[that.type]] match { - case 0 => this.asInstanceOf[Result] - case 1 => - val u = that.asInstanceOf[Tuple1[_]] - Tuple3(t._1, t._2, u._1).asInstanceOf[Result] - case 2 => - val u = that.asInstanceOf[Tuple2[_, _]] - Tuple4(t._1, t._2, u._1, u._2).asInstanceOf[Result] - case _ => - genericConcat[Result](this, that).asInstanceOf[Result] - } - case Some(3) => - val t = asInstanceOf[Tuple3[_, _, _]] - inline constValue[BoundedSize[that.type]] match { - case 0 => this.asInstanceOf[Result] - case 1 => - val u = that.asInstanceOf[Tuple1[_]] - Tuple4(t._1, t._2, t._3, u._1).asInstanceOf[Result] - case _ => - genericConcat[Result](this, that).asInstanceOf[Result] - } - case Some(_) => - if (constValue[BoundedSize[that.type]] == 0) this.asInstanceOf[Result] - else genericConcat[Result](this, that).asInstanceOf[Result] - case None => - runtime.DynamicTuple.dynamic_++[This, that.type](this, that) - } + inline def ++ [This >: this.type <: Tuple](that: Tuple): Concat[This, that.type] = { + type Result = Concat[This, that.type] + inline constValueOpt[BoundedSize[this.type]] match { + case Some(0) => + that.asInstanceOf[Result] + case Some(1) => + if (constValue[BoundedSize[that.type]] == 0) this.asInstanceOf[Result] + else (asInstanceOf[Tuple1[_]]._1 *: that).asInstanceOf[Result] + case Some(2) => + val t = asInstanceOf[Tuple2[_, _]] + inline constValue[BoundedSize[that.type]] match { + case 0 => this.asInstanceOf[Result] + case 1 => + val u = that.asInstanceOf[Tuple1[_]] + Tuple3(t._1, t._2, u._1).asInstanceOf[Result] + case 2 => + val u = that.asInstanceOf[Tuple2[_, _]] + Tuple4(t._1, t._2, u._1, u._2).asInstanceOf[Result] + case _ => + genericConcat[Result](this, that).asInstanceOf[Result] + } + case Some(3) => + val t = asInstanceOf[Tuple3[_, _, _]] + inline constValue[BoundedSize[that.type]] match { + case 0 => this.asInstanceOf[Result] + case 1 => + val u = that.asInstanceOf[Tuple1[_]] + Tuple4(t._1, t._2, t._3, u._1).asInstanceOf[Result] + case _ => + genericConcat[Result](this, that).asInstanceOf[Result] + } + case Some(_) => + if (constValue[BoundedSize[that.type]] == 0) this.asInstanceOf[Result] + else genericConcat[Result](this, that).asInstanceOf[Result] + case None => + runtime.DynamicTuple.dynamic_++[This, that.type](this, that) } - - inline def concatStaged(that: Tuple): Concat[this.type, that.type] = - ${ StagedTuple.concatStaged('this, constValueOpt[BoundedSize[this.type]], - 'that, constValueOpt[BoundedSize[that.type]]) } + } inline def genericConcat[T <: Tuple](xs: Tuple, ys: Tuple): Tuple = fromArray[T](xs.toArray ++ ys.toArray) - inline def size[This >: this.type <: Tuple]: Size[This] = - if (stageIt) sizeStaged.asInstanceOf - else { - type Result = Size[This] - inline constValueOpt[BoundedSize[this.type]] match { - case Some(n) => n.asInstanceOf[Result] - case _ => runtime.DynamicTuple.dynamicSize(this) - } + inline def size[This >: this.type <: Tuple]: Size[This] = { + type Result = Size[This] + inline constValueOpt[BoundedSize[this.type]] match { + case Some(n) => n.asInstanceOf[Result] + case _ => runtime.DynamicTuple.dynamicSize(this) } + } - inline def sizeStaged: Size[this.type] = - ${ StagedTuple.sizeStaged[Size[this.type]]('this, constValueOpt[BoundedSize[this.type]]) } } object Tuple { - final val stageIt = false type Head[X <: NonEmptyTuple] = X match { case x *: _ => x @@ -185,8 +165,7 @@ object Tuple { } inline def fromArray[T <: Tuple](xs: Array[Object]): T = - if (stageIt) fromArrayStaged[T](xs) - else inline constValue[BoundedSize[T]] match { + inline constValue[BoundedSize[T]] match { case 0 => ().asInstanceOf[T] case 1 => Tuple1(xs(0)).asInstanceOf[T] case 2 => Tuple2(xs(0), xs(1)).asInstanceOf[T] @@ -212,73 +191,60 @@ object Tuple { case 22 => Tuple22(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17), xs(18), xs(19), xs(20), xs(21)).asInstanceOf[T] case _ => TupleXXL(xs).asInstanceOf[T] } - - inline def fromArrayStaged[T <: Tuple](xs: Array[Object]): T = - ${StagedTuple.fromArrayStaged[T]('xs, constValueOpt[BoundedSize[this.type]])} } sealed trait NonEmptyTuple extends Tuple { import Tuple._ - inline def head[This >: this.type <: NonEmptyTuple]: Head[This] = - if (stageIt) headStaged.asInstanceOf - else { - type Result = Head[This] - val resVal = inline constValueOpt[BoundedSize[this.type]] match { - case Some(1) => - val t = asInstanceOf[Tuple1[_]] - t._1 - case Some(2) => - val t = asInstanceOf[Tuple2[_, _]] - t._1 - case Some(3) => - val t = asInstanceOf[Tuple3[_, _, _]] - t._1 - case Some(4) => - val t = asInstanceOf[Tuple4[_, _, _, _]] - t._1 - case Some(n) if n > 4 && n <= scala.runtime.DynamicTuple.MaxSpecialized => - asInstanceOf[Product].productElement(0) - case Some(n) if n > scala.runtime.DynamicTuple.MaxSpecialized => - val t = asInstanceOf[TupleXXL] - t.elems(0) - case None => - scala.runtime.DynamicTuple.dynamicHead[this.type](this) - } - resVal.asInstanceOf[Result] + inline def head[This >: this.type <: NonEmptyTuple]: Head[This] = { + type Result = Head[This] + val resVal = inline constValueOpt[BoundedSize[this.type]] match { + case Some(1) => + val t = asInstanceOf[Tuple1[_]] + t._1 + case Some(2) => + val t = asInstanceOf[Tuple2[_, _]] + t._1 + case Some(3) => + val t = asInstanceOf[Tuple3[_, _, _]] + t._1 + case Some(4) => + val t = asInstanceOf[Tuple4[_, _, _, _]] + t._1 + case Some(n) if n > 4 && n <= scala.runtime.DynamicTuple.MaxSpecialized => + asInstanceOf[Product].productElement(0) + case Some(n) if n > scala.runtime.DynamicTuple.MaxSpecialized => + val t = asInstanceOf[TupleXXL] + t.elems(0) + case None => + scala.runtime.DynamicTuple.dynamicHead[this.type](this) } + resVal.asInstanceOf[Result] + } - inline def headStaged: Head[this.type] = - ${ StagedTuple.headStaged[this.type]('this, constValueOpt[BoundedSize[this.type]]) } - - inline def tail[This >: this.type <: NonEmptyTuple]: Tail[This] = - if (stageIt) tailStaged.asInstanceOf - else { - type Result = Tail[This] - inline constValueOpt[BoundedSize[this.type]] match { - case Some(1) => - ().asInstanceOf[Result] - case Some(2) => - val t = asInstanceOf[Tuple2[_, _]] - Tuple1(t._2).asInstanceOf[Result] - case Some(3) => - val t = asInstanceOf[Tuple3[_, _, _]] - Tuple2(t._2, t._3).asInstanceOf[Result] - case Some(4) => - val t = asInstanceOf[Tuple4[_, _, _, _]] - Tuple3(t._2, t._3, t._4).asInstanceOf[Result] - case Some(5) => - val t = asInstanceOf[Tuple5[_, _, _, _, _]] - Tuple4(t._2, t._3, t._4, t._5).asInstanceOf[Result] - case Some(n) if n > 5 => - fromArray[Result](toArray.tail) - case None => - runtime.DynamicTuple.dynamicTail[This](this) - } + inline def tail[This >: this.type <: NonEmptyTuple]: Tail[This] = { + type Result = Tail[This] + inline constValueOpt[BoundedSize[this.type]] match { + case Some(1) => + ().asInstanceOf[Result] + case Some(2) => + val t = asInstanceOf[Tuple2[_, _]] + Tuple1(t._2).asInstanceOf[Result] + case Some(3) => + val t = asInstanceOf[Tuple3[_, _, _]] + Tuple2(t._2, t._3).asInstanceOf[Result] + case Some(4) => + val t = asInstanceOf[Tuple4[_, _, _, _]] + Tuple3(t._2, t._3, t._4).asInstanceOf[Result] + case Some(5) => + val t = asInstanceOf[Tuple5[_, _, _, _, _]] + Tuple4(t._2, t._3, t._4, t._5).asInstanceOf[Result] + case Some(n) if n > 5 => + fromArray[Result](toArray.tail) + case None => + runtime.DynamicTuple.dynamicTail[This](this) } - - inline def tailStaged: Tail[this.type] = - ${ StagedTuple.tailStaged[this.type]('this, constValueOpt[BoundedSize[this.type]]) } + } inline def fallbackApply(n: Int) = inline constValueOpt[n.type] match { @@ -286,68 +252,60 @@ sealed trait NonEmptyTuple extends Tuple { case None => runtime.DynamicTuple.dynamicApply[this.type, n.type](this, n) } - inline def apply[This >: this.type <: NonEmptyTuple](n: Int): Elem[This, n.type] = - if (stageIt) applyStaged(n).asInstanceOf - else { - type Result = Elem[This, n.type] - inline constValueOpt[Size[this.type]] match { - case Some(1) => - val t = asInstanceOf[Tuple1[_]] - inline constValueOpt[n.type] match { - case Some(0) => t._1.asInstanceOf[Result] - case _ => fallbackApply(n).asInstanceOf[Result] - } - case Some(2) => - val t = asInstanceOf[Tuple2[_, _]] - inline constValueOpt[n.type] match { - case Some(0) => t._1.asInstanceOf[Result] - case Some(1) => t._2.asInstanceOf[Result] - case _ => fallbackApply(n).asInstanceOf[Result] - } - case Some(3) => - val t = asInstanceOf[Tuple3[_, _, _]] - inline constValueOpt[n.type] match { - case Some(0) => t._1.asInstanceOf[Result] - case Some(1) => t._2.asInstanceOf[Result] - case Some(2) => t._3.asInstanceOf[Result] - case _ => fallbackApply(n).asInstanceOf[Result] - } - case Some(4) => - val t = asInstanceOf[Tuple4[_, _, _, _]] - inline constValueOpt[n.type] match { - case Some(0) => t._1.asInstanceOf[Result] - case Some(1) => t._2.asInstanceOf[Result] - case Some(2) => t._3.asInstanceOf[Result] - case Some(3) => t._4.asInstanceOf[Result] - case _ => fallbackApply(n).asInstanceOf[Result] - } - case Some(s) if s > 4 && s <= scala.runtime.DynamicTuple.MaxSpecialized => - val t = asInstanceOf[Product] - inline constValueOpt[n.type] match { - case Some(n) if n >= 0 && n < s => t.productElement(n).asInstanceOf[Result] - case _ => fallbackApply(n).asInstanceOf[Result] - } - case Some(s) if s > scala.runtime.DynamicTuple.MaxSpecialized => - val t = asInstanceOf[TupleXXL] - inline constValueOpt[n.type] match { - case Some(n) if n >= 0 && n < s => t.elems(n).asInstanceOf[Result] - case _ => fallbackApply(n).asInstanceOf[Result] - } - case _ => fallbackApply(n).asInstanceOf[Result] - } + inline def apply[This >: this.type <: NonEmptyTuple](n: Int): Elem[This, n.type] = { + type Result = Elem[This, n.type] + inline constValueOpt[Size[this.type]] match { + case Some(1) => + val t = asInstanceOf[Tuple1[_]] + inline constValueOpt[n.type] match { + case Some(0) => t._1.asInstanceOf[Result] + case _ => fallbackApply(n).asInstanceOf[Result] + } + case Some(2) => + val t = asInstanceOf[Tuple2[_, _]] + inline constValueOpt[n.type] match { + case Some(0) => t._1.asInstanceOf[Result] + case Some(1) => t._2.asInstanceOf[Result] + case _ => fallbackApply(n).asInstanceOf[Result] + } + case Some(3) => + val t = asInstanceOf[Tuple3[_, _, _]] + inline constValueOpt[n.type] match { + case Some(0) => t._1.asInstanceOf[Result] + case Some(1) => t._2.asInstanceOf[Result] + case Some(2) => t._3.asInstanceOf[Result] + case _ => fallbackApply(n).asInstanceOf[Result] + } + case Some(4) => + val t = asInstanceOf[Tuple4[_, _, _, _]] + inline constValueOpt[n.type] match { + case Some(0) => t._1.asInstanceOf[Result] + case Some(1) => t._2.asInstanceOf[Result] + case Some(2) => t._3.asInstanceOf[Result] + case Some(3) => t._4.asInstanceOf[Result] + case _ => fallbackApply(n).asInstanceOf[Result] + } + case Some(s) if s > 4 && s <= scala.runtime.DynamicTuple.MaxSpecialized => + val t = asInstanceOf[Product] + inline constValueOpt[n.type] match { + case Some(n) if n >= 0 && n < s => t.productElement(n).asInstanceOf[Result] + case _ => fallbackApply(n).asInstanceOf[Result] + } + case Some(s) if s > scala.runtime.DynamicTuple.MaxSpecialized => + val t = asInstanceOf[TupleXXL] + inline constValueOpt[n.type] match { + case Some(n) if n >= 0 && n < s => t.elems(n).asInstanceOf[Result] + case _ => fallbackApply(n).asInstanceOf[Result] + } + case _ => fallbackApply(n).asInstanceOf[Result] } + } - inline def applyStaged(n: Int): Elem[this.type, n.type] = - ${StagedTuple.applyStaged[this.type, n.type]( - 'this, constValueOpt[Size[this.type]], 'n, constValueOpt[n.type])} } @showAsInfix sealed class *:[+H, +T <: Tuple] extends NonEmptyTuple object *: { - inline def unapply[H, T <: Tuple](x: H *: T) = - // With stageIt on we cannot expand x.head in the same run and fails - if (Tuple.stageIt) (scala.runtime.DynamicTuple.dynamicHead(x), scala.runtime.DynamicTuple.dynamicTail(x)) - else (x.head, x.tail) + inline def unapply[H, T <: Tuple](x: H *: T) = (x.head, x.tail) } diff --git a/library/src-bootstrapped/scala/internal/StagedTuple.scala b/tests/run-with-compiler/staged-tuples/StagedTuple.scala similarity index 100% rename from library/src-bootstrapped/scala/internal/StagedTuple.scala rename to tests/run-with-compiler/staged-tuples/StagedTuple.scala diff --git a/tests/run-with-compiler/staged-tuples/Test.scala b/tests/run-with-compiler/staged-tuples/Test.scala new file mode 100644 index 000000000000..c9b3f031628d --- /dev/null +++ b/tests/run-with-compiler/staged-tuples/Test.scala @@ -0,0 +1,26 @@ +import scala.internal.StagedTuple._ + +object Test { + + def main(args: Array[String]): Unit = { + implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make(getClass.getClassLoader) + + assert(fromArrayStaged('{ Array.empty[Object] }, Some(0)).run.==(())) + assert(fromArrayStaged[Tuple1[String]]('{ Array[Object]("a") }, Some(1)).run == Tuple1("a")) + assert(fromArrayStaged[(String, String)]('{ Array[Object]("a", "b") }, Some(2)).run == ("a", "b")) + assert(fromArrayStaged[(String, String, String)]('{ Array[Object]("a", "b", "c") }, Some(3)).run == ("a", "b", "c")) + + assert(headStaged[Tuple1[String]]('{ Tuple1("a") }, Some(1)).run == "a") + assert(headStaged[(String, String)]('{ ("a", "b") }, Some(2)).run == "a") + assert(headStaged[(String, String, String)]('{ ("a", "b", "c") }, Some(3)).run == "a") + + assert(tailStaged[Tuple1[String]]('{ Tuple1("a") }, Some(1)).run == (())) + assert(tailStaged[(String, String)]('{ ("a", "b") }, Some(2)).run == Tuple1("b")) + assert(tailStaged[(String, String, String)]('{ ("a", "b", "c") }, Some(3)).run == ("b", "c")) + + assert(headStaged[(String, String, String)]('{ ("a", "b", "c") }, Some(3)).run == "a") + assert(headStaged[(String, String, String)]('{ ("a", "b", "c") }, Some(3)).run == "a") + assert(headStaged[(String, String, String)]('{ ("a", "b", "c") }, Some(3)).run == "a") + + } +}