Skip to content

Commit db7e183

Browse files
committed
Fix tuple match types
Removed all use of match types inside the implementation of the staged tuples. Pass the expansion of match types as type parameters instead.
1 parent da0c249 commit db7e183

File tree

5 files changed

+140
-120
lines changed

5 files changed

+140
-120
lines changed

compiler/src/dotty/tools/dotc/CompilationUnit.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package dotc
33

44
import util.SourceFile
55
import ast.{tpd, untpd}
6-
import tpd.{ Tree, TreeTraverser }
6+
import dotty.tools.dotc.ast.Trees
7+
import tpd.{Tree, TreeTraverser}
78
import typer.PrepareInlineable.InlineAccessors
89
import dotty.tools.dotc.core.Contexts.Context
910
import dotty.tools.dotc.core.SymDenotations.ClassDenotation
1011
import dotty.tools.dotc.core.Symbols._
1112
import dotty.tools.dotc.transform.SymUtils._
13+
import dotty.tools.dotc.typer.Inliner
1214

1315
class CompilationUnit(val source: SourceFile) {
1416

@@ -57,6 +59,11 @@ object CompilationUnit {
5759
def traverse(tree: Tree)(implicit ctx: Context): Unit = {
5860
if (tree.symbol.isQuote)
5961
containsQuotes = true
62+
tree match {
63+
case _: tpd.RefTree | _: Trees.GenericApply[_] if Inliner.isInlineable(tree) =>
64+
containsQuotes = true // May inline a quote
65+
case _ =>
66+
}
6067
traverseChildren(tree)
6168
}
6269
}

library/src-scala3/scala/StagedTuple.scala

Lines changed: 118 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -72,59 +72,61 @@ object StagedTuple {
7272
res.as[Res]
7373
}
7474

75-
def headStaged[Tup <: NonEmptyTuple : Type](tup: Expr[Tup], size: Option[Int]): Expr[Head[Tup]] = {
76-
if (!specialize) '(dynamicHead(~tup))
77-
else {
78-
val resVal = size match {
79-
case Some(1) =>
80-
'((~tup.as[Tuple1[_]])._1)
81-
case Some(2) =>
82-
'((~tup.as[Tuple2[_, _]])._1)
83-
case Some(3) =>
84-
'((~tup.as[Tuple3[_, _, _]])._1)
85-
case Some(4) =>
86-
'((~tup.as[Tuple4[_, _, _, _]])._1)
87-
case Some(n) if n > 4 && n <= $MaxSpecialized =>
88-
'((~tup.as[Product]).productElement(0))
89-
case Some(n) if n > $MaxSpecialized =>
90-
'((~tup.as[TupleXXL]).elems(0))
91-
case None =>
92-
'(dynamicHead(~tup))
75+
def headStaged[Head : Type](tup: Expr[NonEmptyTuple], size: Option[Int]): Expr[Head] = {
76+
val res=
77+
if (!specialize) '(dynamicHead(~tup))
78+
else {
79+
size match {
80+
case Some(1) =>
81+
'((~tup.as[Tuple1[_]])._1)
82+
case Some(2) =>
83+
'((~tup.as[Tuple2[_, _]])._1)
84+
case Some(3) =>
85+
'((~tup.as[Tuple3[_, _, _]])._1)
86+
case Some(4) =>
87+
'((~tup.as[Tuple4[_, _, _, _]])._1)
88+
case Some(n) if n > 4 && n <= $MaxSpecialized =>
89+
'((~tup.as[Product]).productElement(0))
90+
case Some(n) if n > $MaxSpecialized =>
91+
'((~tup.as[TupleXXL]).elems(0))
92+
case None =>
93+
'(dynamicHead(~tup))
94+
}
9395
}
94-
resVal.as[Head[Tup]]
95-
}
96+
res.as[Head]
9697
}
9798

98-
def tailStaged[Tup <: NonEmptyTuple : Type](tup: Expr[Tup], size: Option[Int]): Expr[Tail[Tup]] = {
99-
if (!specialize) '(dynamicTail[Tup](~tup))
100-
else {
101-
val res = size match {
102-
case Some(1) =>
103-
'()
104-
case Some(2) =>
105-
tup.as[Tuple2[_, _]].bind(t => '(Tuple1((~t)._2)))
106-
case Some(3) =>
107-
tup.as[Tuple3[_, _, _]].bind(t => '(Tuple2((~t)._2, (~t)._3)))
108-
case Some(4) =>
109-
tup.as[Tuple4[_, _, _, _]].bind(t => '(Tuple3((~t)._2, (~t)._3, (~t)._4)))
110-
case Some(5) =>
111-
tup.as[Tuple5[_, _, _, _, _]].bind(t => '(Tuple4((~t)._2, (~t)._3, (~t)._4, (~t)._5)))
112-
case Some(n) if n > 5 =>
113-
val arr = toArrayStaged(tup, size)
114-
fromArrayStaged('((~arr).tail) , Some(n - 1))
115-
case None =>
116-
'(dynamicTail(~tup))
99+
def tailStaged[Tail <: Tuple : Type](tup: Expr[NonEmptyTuple], size: Option[Int]): Expr[Tail] = {
100+
val res =
101+
if (!specialize) '(dynamicTail(~tup))
102+
else {
103+
size match {
104+
case Some(1) =>
105+
'()
106+
case Some(2) =>
107+
tup.as[Tuple2[_, _]].bind(t => '(Tuple1((~t)._2)))
108+
case Some(3) =>
109+
tup.as[Tuple3[_, _, _]].bind(t => '(Tuple2((~t)._2, (~t)._3)))
110+
case Some(4) =>
111+
tup.as[Tuple4[_, _, _, _]].bind(t => '(Tuple3((~t)._2, (~t)._3, (~t)._4)))
112+
case Some(5) =>
113+
tup.as[Tuple5[_, _, _, _, _]].bind(t => '(Tuple4((~t)._2, (~t)._3, (~t)._4, (~t)._5)))
114+
case Some(n) if n > 5 =>
115+
val arr = toArrayStaged(tup, size)
116+
fromArrayStaged('((~arr).tail) , Some(n - 1))
117+
case None =>
118+
'(dynamicTail(~tup))
119+
}
117120
}
118-
res.as[Tail[Tup]]
119-
}
121+
res.as[Tail]
120122
}
121123

122-
def applyStaged[Tup <: NonEmptyTuple : Type, N <: Int : Type](tup: Expr[Tup], size: Option[Int], n: Expr[N], nValue: Option[Int]): Expr[Elem[Tup, N]] = {
123-
if (!specialize) '(dynamicApply(~tup, ~n))
124+
def applyStaged[Elem : Type](tup: Expr[NonEmptyTuple], size: Option[Int], n: Expr[Int], nValue: Option[Int]): Expr[Elem] = {
125+
if (!specialize) ('(dynamicApply(~tup, ~n))).as[Elem]
124126
else {
125-
def fallbackApply(): Expr[Elem[Tup, N]] = nValue match {
127+
def fallbackApply(): Expr[Elem] = nValue match {
126128
case Some(n) => quoted.QuoteError("index out of bounds: " + n)
127-
case None => '(dynamicApply(~tup, ~n))
129+
case None => ('(dynamicApply(~tup, ~n))).as[Elem]
128130
}
129131
val res = size match {
130132
case Some(1) =>
@@ -171,89 +173,91 @@ object StagedTuple {
171173
}
172174
case _ => fallbackApply()
173175
}
174-
res.as[Elem[Tup, N]]
176+
res.as[Elem]
175177
}
176178
}
177179

178-
def stagedCons[T <: Tuple & Singleton : Type, H : Type](self: Expr[T], x: Expr[H], tailSize: Option[Int]): Expr[H *: T] =
179-
if (!specialize) '(dynamic_*:[T, H](~self, ~x))
180-
else {
181-
val res = tailSize match {
182-
case Some(0) =>
183-
'(Tuple1(~x))
184-
case Some(1) =>
185-
self.as[Tuple1[_]].bind(t => '(Tuple2(~x, (~t)._1)))
186-
case Some(2) =>
187-
self.as[Tuple2[_, _]].bind(t => '(Tuple3(~x, (~t)._1, (~t)._2)))
188-
case Some(3) =>
189-
self.as[Tuple3[_, _, _]].bind(t => '(Tuple4(~x, (~t)._1, (~t)._2, (~t)._3)))
190-
case Some(4) =>
191-
self.as[Tuple4[_, _, _, _]].bind(t => '(Tuple5(~x, (~t)._1, (~t)._2, (~t)._3, (~t)._4)))
192-
case Some(n) =>
193-
fromArrayStaged('($consArray(~x, ~toArrayStaged(self, tailSize))), Some(n + 1))
194-
case _ =>
195-
'(dynamic_*:[T, H](~self, ~x))
196-
}
197-
res.as[H *: T]
180+
def stagedCons[Res <: NonEmptyTuple : Type, H : Type](self: Expr[Tuple], x: Expr[H], tailSize: Option[Int]): Expr[Res] = {
181+
val res =
182+
if (!specialize) '(dynamic_*:(~self, ~x))
183+
else {
184+
tailSize match {
185+
case Some(0) =>
186+
'(Tuple1(~x))
187+
case Some(1) =>
188+
self.as[Tuple1[_]].bind(t => '(Tuple2(~x, (~t)._1)))
189+
case Some(2) =>
190+
self.as[Tuple2[_, _]].bind(t => '(Tuple3(~x, (~t)._1, (~t)._2)))
191+
case Some(3) =>
192+
self.as[Tuple3[_, _, _]].bind(t => '(Tuple4(~x, (~t)._1, (~t)._2, (~t)._3)))
193+
case Some(4) =>
194+
self.as[Tuple4[_, _, _, _]].bind(t => '(Tuple5(~x, (~t)._1, (~t)._2, (~t)._3, (~t)._4)))
195+
case Some(n) =>
196+
fromArrayStaged('($consArray(~x, ~toArrayStaged(self, tailSize))), Some(n + 1))
197+
case _ =>
198+
'(dynamic_*:(~self, ~x))
199+
}
200+
}
201+
res.as[Res]
198202
}
199203

200-
def stagedConcat[Self <: Tuple & Singleton : Type, That <: Tuple & Singleton : Type](self: Expr[Self], selfSize: Option[Int], that: Expr[That], thatSize: Option[Int]): Expr[Concat[Self, That]] = {
201-
if (!specialize) '(dynamic_++[Self, That](~self, ~that))
202-
else {
203-
def genericConcat(xs: Expr[Tuple], ys: Expr[Tuple]): Expr[Tuple] =
204-
fromArrayStaged[Tuple]('((~toArrayStaged(xs, None)) ++ (~toArrayStaged(ys, None))), None)
205-
206-
val res = selfSize match {
207-
case Some(0) =>
208-
that
209-
case Some(1) =>
210-
if (thatSize.contains(0)) self
211-
else stagedCons(that, self.as[Tuple1[_]], thatSize)
212-
case Some(2) =>
213-
val self2 = self.as[Tuple2[_, _]]
214-
thatSize match {
215-
case Some(0) => self
216-
case Some(1) =>
217-
self2.bind { t =>
218-
that.as[Tuple1[_]].bind(u => '(Tuple3((~t)._1, (~t)._2, (~u)._1)))
219-
}
220-
case Some(2) =>
221-
self2.bind { t =>
222-
that.as[Tuple2[_, _]].bind(u => '(Tuple4((~t)._1, (~t)._2, (~u)._1, (~u)._2)))
223-
}
224-
case _ =>
225-
genericConcat(self, that)
226-
}
227-
case Some(3) =>
228-
val self2 = self.as[Tuple3[_, _, _]]
229-
thatSize match {
230-
case Some(0) => self
231-
case Some(1) =>
232-
self2.bind { t =>
233-
that.as[Tuple1[_]].bind(u => '(Tuple4((~t)._1, (~t)._2, (~t)._3, (~u)._1)))
234-
}
235-
case _ =>
236-
genericConcat(self, that)
237-
}
238-
case Some(_) =>
239-
if (thatSize.contains(0)) self
240-
else genericConcat(self, that)
241-
case None =>
242-
'(dynamic_++(~self, ~that))
204+
def stagedConcat[Concat <: Tuple : Type](self: Expr[Tuple], selfSize: Option[Int], that: Expr[Tuple], thatSize: Option[Int]): Expr[Concat] = {
205+
val res =
206+
if (!specialize) '(dynamic_++(~self, ~that))
207+
else {
208+
def genericConcat(xs: Expr[Tuple], ys: Expr[Tuple]): Expr[Tuple] =
209+
fromArrayStaged[Tuple]('((~toArrayStaged(xs, None)) ++ (~toArrayStaged(ys, None))), None)
210+
selfSize match {
211+
case Some(0) =>
212+
that
213+
case Some(1) =>
214+
if (thatSize.contains(0)) self
215+
else stagedCons(that, self.as[Tuple1[_]], thatSize)
216+
case Some(2) =>
217+
val self2 = self.as[Tuple2[_, _]]
218+
thatSize match {
219+
case Some(0) => self
220+
case Some(1) =>
221+
self2.bind { t =>
222+
that.as[Tuple1[_]].bind(u => '(Tuple3((~t)._1, (~t)._2, (~u)._1)))
223+
}
224+
case Some(2) =>
225+
self2.bind { t =>
226+
that.as[Tuple2[_, _]].bind(u => '(Tuple4((~t)._1, (~t)._2, (~u)._1, (~u)._2)))
227+
}
228+
case _ =>
229+
genericConcat(self, that)
230+
}
231+
case Some(3) =>
232+
val self2 = self.as[Tuple3[_, _, _]]
233+
thatSize match {
234+
case Some(0) => self
235+
case Some(1) =>
236+
self2.bind { t =>
237+
that.as[Tuple1[_]].bind(u => '(Tuple4((~t)._1, (~t)._2, (~t)._3, (~u)._1)))
238+
}
239+
case _ =>
240+
genericConcat(self, that)
241+
}
242+
case Some(_) =>
243+
if (thatSize.contains(0)) self
244+
else genericConcat(self, that)
245+
case None =>
246+
'(dynamic_++(~self, ~that))
247+
}
243248
}
244-
res.as[Concat[Self, That]]
245-
}
249+
res.as[Concat]
246250
}
247251

248-
private implicit class ExprOps[U: Type](expr: Expr[U]) {
249-
252+
private implicit class ExprOps[U](expr: Expr[U]) {
250253
def as[T: Type]: Expr[T] = '{ (~expr).asInstanceOf[T] }
254+
}
251255

256+
private implicit class ExprTypedOps[U: Type](expr: Expr[U]) {
252257
def bind[T](in: Expr[U] => Expr[T]): Expr[T] = '{
253258
val t: U = (~expr)
254259
~(in('(t)))
255260
}
256-
257261
}
258262

259263
}

library/src-scala3/scala/Tuple.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ sealed trait Tuple extends Any {
1010
~toArrayStaged('(this), constValueOpt[BoundedSize[this.type]])
1111

1212
inline def *: [H] (x: H): H *: this.type =
13-
~stagedCons('(this), '(x), constValueOpt[BoundedSize[this.type]])
13+
~stagedCons[H *: this.type, H]('(this), '(x), constValueOpt[BoundedSize[this.type]])
1414

1515
inline def ++(that: Tuple): Concat[this.type, that.type] =
16-
~stagedConcat('(this), constValueOpt[BoundedSize[this.type]], '(that), constValueOpt[BoundedSize[that.type]])
16+
~stagedConcat[Concat[this.type, that.type]]('(this), constValueOpt[BoundedSize[this.type]], '(that), constValueOpt[BoundedSize[that.type]])
1717

1818
inline def size: Size[this.type] =
1919
~sizeStaged[Size[this.type]]('(this), constValueOpt[BoundedSize[this.type]])
@@ -182,13 +182,13 @@ abstract sealed class NonEmptyTuple extends Tuple {
182182
import StagedTuple._
183183

184184
inline def head: Head[this.type] =
185-
~headStaged[this.type]('(this), constValueOpt[BoundedSize[this.type]])
185+
~headStaged[Head[this.type]]('(this), constValueOpt[BoundedSize[this.type]])
186186

187187
inline def tail: Tail[this.type] =
188-
~tailStaged[this.type]('(this), constValueOpt[BoundedSize[this.type]])
188+
~tailStaged[Tail[this.type]]('(this), constValueOpt[BoundedSize[this.type]])
189189

190190
inline def apply(n: Int): Elem[this.type, n.type] =
191-
~applyStaged[this.type, n.type]('(this), constValueOpt[Size[this.type]], '(n), constValueOpt[n.type])
191+
~applyStaged[Elem[this.type, n.type]]('(this), constValueOpt[Size[this.type]], '(n), constValueOpt[n.type])
192192

193193
}
194194

File renamed without changes.

tests/run/tuples1a.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object Test extends App {
2+
val t7 = '5' *: 4 *: "C" *: ()
3+
4+
val t7a = t7.tail
5+
val t7b = t7a.tail
6+
val t7c: Unit = (t7.tail: (Int, String)).tail
7+
val t7d: Unit = (t7.tail: Int *: String *: Unit).tail
8+
val t7e: Unit = t7.tail.tail
9+
}

0 commit comments

Comments
 (0)