Skip to content

Commit 894791a

Browse files
committed
Fix parser and add more tests
Undoes: - Drop InlineIf and InlineMatch (reverted from commit 8ae9d6a)
1 parent c2a1738 commit 894791a

File tree

12 files changed

+258
-38
lines changed

12 files changed

+258
-38
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,8 +1215,11 @@ object Parsers {
12151215
if (isIdent(nme.INLINEkw)) {
12161216
val start = in.skipToken()
12171217
val t = postfixExpr()
1218-
accept(MATCH)
1219-
matchExpr(t, start, MatchKind.Inline)
1218+
if (in.token == MATCH) matchExpr(t, start, MatchKind.Inline)
1219+
else {
1220+
syntaxErrorOrIncomplete(i"`match` expected but ${in.token} found")
1221+
t
1222+
}
12201223
}
12211224
else expr1Rest(postfixExpr(), location)
12221225
}

library/src-scala3/scala/Tuple.scala

Lines changed: 233 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,118 @@ import typelevel._
44

55
sealed trait Tuple extends Any {
66
import Tuple._
7-
import StagedTuple._
87

98
inline def toArray: Array[Object] =
10-
~toArrayStaged('(this), constValueOpt[BoundedSize[this.type]])
9+
if (specialize)
10+
inline constValueOpt[BoundedSize[this.type]] match {
11+
case Some(0) =>
12+
$emptyArray
13+
case Some(1) =>
14+
val t = asInstanceOf[Tuple1[Object]]
15+
Array(t._1)
16+
case Some(2) =>
17+
val t = asInstanceOf[Tuple2[Object, Object]]
18+
Array(t._1, t._2)
19+
case Some(3) =>
20+
val t = asInstanceOf[Tuple3[Object, Object, Object]]
21+
Array(t._1, t._2, t._3)
22+
case Some(4) =>
23+
val t = asInstanceOf[Tuple4[Object, Object, Object, Object]]
24+
Array(t._1, t._2, t._3, t._4)
25+
case Some(n) if n <= $MaxSpecialized =>
26+
$toArray(this, n)
27+
case Some(n) =>
28+
asInstanceOf[TupleXXL].elems
29+
case None =>
30+
dynamicToArray(this)
31+
}
32+
else dynamicToArray(this)
1133

1234
inline def *: [H] (x: H): H *: this.type =
13-
~stagedCons('(this), '(x), constValueOpt[BoundedSize[this.type]])
35+
if (specialize) {
36+
type Result = H *: this.type
37+
inline constValueOpt[BoundedSize[this.type]] match {
38+
case Some(0) =>
39+
Tuple1(x).asInstanceOf[Result]
40+
case Some(1) =>
41+
Tuple2(x, asInstanceOf[Tuple1[_]]._1).asInstanceOf[Result]
42+
case Some(2) =>
43+
val t = asInstanceOf[Tuple2[_, _]]
44+
Tuple3(x, t._1, t._2).asInstanceOf[Result]
45+
case Some(3) =>
46+
val t = asInstanceOf[Tuple3[_, _, _]]
47+
Tuple4(x, t._1, t._2, t._3).asInstanceOf[Result]
48+
case Some(4) =>
49+
val t = asInstanceOf[Tuple4[_, _, _, _]]
50+
Tuple5(x, t._1, t._2, t._3, t._4).asInstanceOf[Result]
51+
case Some(n) =>
52+
fromArray[Result]($consArray(x, toArray))
53+
case _ =>
54+
dynamic_*:[this.type, H](this, x)
55+
}
56+
}
57+
else dynamic_*:[this.type, H](this, x)
1458

1559
inline def ++(that: Tuple): Concat[this.type, that.type] =
16-
~stagedConcat('(this), constValueOpt[BoundedSize[this.type]], '(that), constValueOpt[BoundedSize[that.type]])
60+
if (specialize) {
61+
type Result = Concat[this.type, that.type]
62+
inline constValueOpt[BoundedSize[this.type]] match {
63+
case Some(0) =>
64+
that.asInstanceOf[Result]
65+
case Some(1) =>
66+
if (constValue[BoundedSize[that.type]] == 0) this.asInstanceOf[Result]
67+
else (asInstanceOf[Tuple1[_]]._1 *: that).asInstanceOf[Result]
68+
case Some(2) =>
69+
val t = asInstanceOf[Tuple2[_, _]]
70+
inline constValue[BoundedSize[that.type]] match {
71+
case 0 => this.asInstanceOf[Result]
72+
case 1 =>
73+
val u = that.asInstanceOf[Tuple1[_]]
74+
Tuple3(t._1, t._2, u._1).asInstanceOf[Result]
75+
case 2 =>
76+
val u = that.asInstanceOf[Tuple2[_, _]]
77+
Tuple4(t._1, t._2, u._1, u._2).asInstanceOf[Result]
78+
case _ =>
79+
genericConcat[Result](this, that).asInstanceOf[Result]
80+
}
81+
case Some(3) =>
82+
val t = asInstanceOf[Tuple3[_, _, _]]
83+
inline constValue[BoundedSize[that.type]] match {
84+
case 0 => this.asInstanceOf[Result]
85+
case 1 =>
86+
val u = that.asInstanceOf[Tuple1[_]]
87+
Tuple4(t._1, t._2, t._3, u._1).asInstanceOf[Result]
88+
case _ =>
89+
genericConcat[Result](this, that).asInstanceOf[Result]
90+
}
91+
case Some(_) =>
92+
if (constValue[BoundedSize[that.type]] == 0) this.asInstanceOf[Result]
93+
else genericConcat[Result](this, that).asInstanceOf[Result]
94+
case None =>
95+
dynamic_++[this.type, that.type](this, that)
96+
}
97+
}
98+
else dynamic_++[this.type, that.type](this, that)
1799

18-
inline def size: Size[this.type] =
19-
~sizeStaged[Size[this.type]]('(this), constValueOpt[BoundedSize[this.type]])
100+
inline def genericConcat[T <: Tuple](xs: Tuple, ys: Tuple): Tuple =
101+
fromArray[T](xs.toArray ++ ys.toArray)
20102

103+
inline def size: Size[this.type] =
104+
if (specialize) {
105+
type Result = Size[this.type]
106+
inline constValueOpt[BoundedSize[this.type]] match {
107+
case Some(n) => n.asInstanceOf[Result]
108+
case _ => dynamicSize(this)
109+
}
110+
}
111+
else dynamicSize(this)
21112
}
22113

23114
object Tuple {
24-
import StagedTuple._
25-
26115
inline val $MaxSpecialized = 22
27116
inline private val XXL = $MaxSpecialized + 1
28117

29-
final val specialize = true
118+
final val specialize = false
30119

31120
type Head[+X <: NonEmptyTuple] = X match {
32121
case x *: _ => x
@@ -86,7 +175,34 @@ object Tuple {
86175
}
87176

88177
inline def fromArray[T <: Tuple](xs: Array[Object]): T =
89-
~fromArrayStaged[T]('(xs), constValueOpt[BoundedSize[this.type]])
178+
if (specialize)
179+
inline constValue[BoundedSize[T]] match {
180+
case 0 => ().asInstanceOf[T]
181+
case 1 => Tuple1(xs(0)).asInstanceOf[T]
182+
case 2 => Tuple2(xs(0), xs(1)).asInstanceOf[T]
183+
case 3 => Tuple3(xs(0), xs(1), xs(2)).asInstanceOf[T]
184+
case 4 => Tuple4(xs(0), xs(1), xs(2), xs(3)).asInstanceOf[T]
185+
case 5 => Tuple5(xs(0), xs(1), xs(2), xs(3), xs(4)).asInstanceOf[T]
186+
case 6 => Tuple6(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5)).asInstanceOf[T]
187+
case 7 => Tuple7(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6)).asInstanceOf[T]
188+
case 8 => Tuple8(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7)).asInstanceOf[T]
189+
case 9 => Tuple9(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8)).asInstanceOf[T]
190+
case 10 => Tuple10(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9)).asInstanceOf[T]
191+
case 11 => Tuple11(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10)).asInstanceOf[T]
192+
case 12 => Tuple12(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11)).asInstanceOf[T]
193+
case 13 => Tuple13(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)).asInstanceOf[T]
194+
case 14 => Tuple14(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)).asInstanceOf[T]
195+
case 15 => Tuple15(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)).asInstanceOf[T]
196+
case 16 => Tuple16(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)).asInstanceOf[T]
197+
case 17 => Tuple17(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)).asInstanceOf[T]
198+
case 18 => Tuple18(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)).asInstanceOf[T]
199+
case 19 => Tuple19(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)).asInstanceOf[T]
200+
case 20 => Tuple20(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)).asInstanceOf[T]
201+
case 21 => Tuple21(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)).asInstanceOf[T]
202+
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]
203+
case _ => TupleXXL(xs).asInstanceOf[T]
204+
}
205+
else dynamicFromArray[T](xs)
90206

91207
def dynamicFromArray[T <: Tuple](xs: Array[Object]): T = xs.length match {
92208
case 0 => ().asInstanceOf[T]
@@ -179,17 +295,117 @@ object Tuple {
179295
abstract sealed class NonEmptyTuple extends Tuple {
180296
import Tuple._
181297
import NonEmptyTuple._
182-
import StagedTuple._
183298

184299
inline def head: Head[this.type] =
185-
~headStaged[this.type]('(this), constValueOpt[BoundedSize[this.type]])
300+
if (specialize) {
301+
type Result = Head[this.type]
302+
val resVal = inline constValueOpt[BoundedSize[this.type]] match {
303+
case Some(1) =>
304+
val t = asInstanceOf[Tuple1[_]]
305+
t._1
306+
case Some(2) =>
307+
val t = asInstanceOf[Tuple2[_, _]]
308+
t._1
309+
case Some(3) =>
310+
val t = asInstanceOf[Tuple3[_, _, _]]
311+
t._1
312+
case Some(4) =>
313+
val t = asInstanceOf[Tuple4[_, _, _, _]]
314+
t._1
315+
case Some(n) if n > 4 && n <= $MaxSpecialized =>
316+
asInstanceOf[Product].productElement(0)
317+
case Some(n) if n > $MaxSpecialized =>
318+
val t = asInstanceOf[TupleXXL]
319+
t.elems(0)
320+
case None =>
321+
dynamicHead[this.type](this)
322+
}
323+
resVal.asInstanceOf[Result]
324+
}
325+
else dynamicHead[this.type](this)
186326

187327
inline def tail: Tail[this.type] =
188-
~tailStaged[this.type]('(this), constValueOpt[BoundedSize[this.type]])
328+
if (specialize) {
329+
type Result = Tail[this.type]
330+
inline constValueOpt[BoundedSize[this.type]] match {
331+
case Some(1) =>
332+
().asInstanceOf[Result]
333+
case Some(2) =>
334+
val t = asInstanceOf[Tuple2[_, _]]
335+
Tuple1(t._2).asInstanceOf[Result]
336+
case Some(3) =>
337+
val t = asInstanceOf[Tuple3[_, _, _]]
338+
Tuple2(t._2, t._3).asInstanceOf[Result]
339+
case Some(4) =>
340+
val t = asInstanceOf[Tuple4[_, _, _, _]]
341+
Tuple3(t._2, t._3, t._4).asInstanceOf[Result]
342+
case Some(5) =>
343+
val t = asInstanceOf[Tuple5[_, _, _, _, _]]
344+
Tuple4(t._2, t._3, t._4, t._5).asInstanceOf[Result]
345+
case Some(n) if n > 5 =>
346+
fromArray[Result](toArray.tail)
347+
case None =>
348+
dynamicTail[this.type](this)
349+
}
350+
}
351+
else dynamicTail[this.type](this)
189352

190-
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])
353+
inline def fallbackApply(n: Int) =
354+
inline constValueOpt[n.type] match {
355+
case Some(n: Int) => error("index out of bounds: ", n)
356+
case None => dynamicApply[this.type](this, n)
357+
}
192358

359+
inline def apply(n: Int): Elem[this.type, n.type] =
360+
if (specialize) {
361+
type Result = Elem[this.type, n.type]
362+
inline constValueOpt[Size[this.type]] match {
363+
case Some(1) =>
364+
val t = asInstanceOf[Tuple1[_]]
365+
inline constValueOpt[n.type] match {
366+
case Some(0) => t._1.asInstanceOf[Result]
367+
case _ => fallbackApply(n).asInstanceOf[Result]
368+
}
369+
case Some(2) =>
370+
val t = asInstanceOf[Tuple2[_, _]]
371+
inline constValueOpt[n.type] match {
372+
case Some(0) => t._1.asInstanceOf[Result]
373+
case Some(1) => t._2.asInstanceOf[Result]
374+
case _ => fallbackApply(n).asInstanceOf[Result]
375+
}
376+
case Some(3) =>
377+
val t = asInstanceOf[Tuple3[_, _, _]]
378+
inline constValueOpt[n.type] match {
379+
case Some(0) => t._1.asInstanceOf[Result]
380+
case Some(1) => t._2.asInstanceOf[Result]
381+
case Some(2) => t._3.asInstanceOf[Result]
382+
case _ => fallbackApply(n).asInstanceOf[Result]
383+
}
384+
case Some(4) =>
385+
val t = asInstanceOf[Tuple4[_, _, _, _]]
386+
inline constValueOpt[n.type] match {
387+
case Some(0) => t._1.asInstanceOf[Result]
388+
case Some(1) => t._2.asInstanceOf[Result]
389+
case Some(2) => t._3.asInstanceOf[Result]
390+
case Some(3) => t._4.asInstanceOf[Result]
391+
case _ => fallbackApply(n).asInstanceOf[Result]
392+
}
393+
case Some(s) if s > 4 && s <= $MaxSpecialized =>
394+
val t = asInstanceOf[Product]
395+
inline constValueOpt[n.type] match {
396+
case Some(n) if n >= 0 && n < s => t.productElement(n).asInstanceOf[Result]
397+
case _ => fallbackApply(n).asInstanceOf[Result]
398+
}
399+
case Some(s) if s > $MaxSpecialized =>
400+
val t = asInstanceOf[TupleXXL]
401+
inline constValueOpt[n.type] match {
402+
case Some(n) if n >= 0 && n < s => t.elems(n).asInstanceOf[Result]
403+
case _ => fallbackApply(n).asInstanceOf[Result]
404+
}
405+
case _ => fallbackApply(n).asInstanceOf[Result]
406+
}
407+
}
408+
else dynamicApply[this.type](this, n)
193409
}
194410

195411
object NonEmptyTuple {
@@ -234,6 +450,6 @@ object NonEmptyTuple {
234450
sealed class *:[+H, +T <: Tuple] extends NonEmptyTuple
235451

236452
object *: {
237-
def unapply[H, T <: Tuple](x: H *: T): (H, T) =
238-
(NonEmptyTuple.dynamicHead(x), NonEmptyTuple.dynamicTail(x))
453+
// TODO: make inline
454+
def unapply[H, T <: Tuple](x: H *: T) = (x.head, x.tail)
239455
}

tests/neg/inlinevals.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ object Test {
99

1010
inline inline val twice = 30 // error: `match' expected // error: not found: inline
1111

12-
class C(inline x: Int, private inline val y: Int) { // error: `{` expected // error // error
12+
class C(inline x: Int, private inline val y: Int) { // error // error
1313
inline val foo: Int // error: abstract member may not be inline
1414
inline def bar: Int // error: abstract member may not be inline
1515
}
@@ -33,4 +33,3 @@ object Test {
3333
inline def byname(inline f: => String): Int = ??? // ok
3434

3535
}
36-
// error: `}` expected

tests/neg/nested-rewrites.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ object Test {
1515
object Test0 {
1616

1717
def f(x: Int) = {
18-
inline def g(x: Int) = x match {
18+
inline def g(x: Int) = inline x match {
1919
case 0 => 0
2020
}
2121
g(0)
2222
inline val Y = 0
2323
g(Y)
2424

25-
inline def h(x: Int) = x match {
25+
inline def h(x: Int) = inline x match {
2626
case Y => 0
2727
}
2828
h(0)
@@ -35,14 +35,14 @@ object Test0 {
3535
object Test1 {
3636

3737
erased inline def f(x: Int) = {
38-
erased inline def g(x: Int) = x match { // error: implementation restriction: nested inline methods are not supported
38+
erased inline def g(x: Int) = inline x match { // error: implementation restriction: nested inline methods are not supported
3939
case 0 => 0
4040
}
4141
g(0)
4242
inline val Y = 0
4343
g(Y)
4444

45-
inline def h(x: Int) = x match { // error: implementation restriction: nested inline methods are not supported
45+
inline def h(x: Int) = inline x match { // error: implementation restriction: nested inline methods are not supported
4646
case Y => 0
4747
}
4848
h(0)

tests/neg/transparent-override/B_2.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class B extends A {
2-
inline def f(x: Int): Int = x match { // error
2+
inline def f(x: Int): Int = inline x match { // error
33
case 0 => 1
44
case _ => x
55
}

tests/neg/typelevel-noeta.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
object Test {
33
def anyValue[T]: T = ???
44

5-
inline def test(x: Int) = x match {
5+
inline def test(x: Int) = inline x match {
66
case _: Byte =>
77
case _: Char =>
88
}
99

10-
inline def test2() = 1 match {
10+
inline def test2() = inline 1 match {
1111
case _: Byte =>
1212
case _: Char =>
1313
}

tests/pos-deep-subtype/tuples23.check

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
2+
276

0 commit comments

Comments
 (0)