Skip to content

Commit f1e2890

Browse files
committed
More blacklisting and test fixing
1 parent f33b078 commit f1e2890

File tree

3 files changed

+118
-104
lines changed

3 files changed

+118
-104
lines changed

compiler/test/dotc/run-from-tasty.blacklist

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ puzzle.scala
88
implicitMatch.scala
99
typeclass-derivation1.scala
1010
typeclass-derivation2.scala
11+
typeclass-derivation3.scala
1112

tests/neg/typeclass-derivation2.scala

+92-84
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,88 @@
11
import scala.collection.mutable
22
import scala.annotation.tailrec
33

4-
trait Deriving {
5-
import Deriving._
6-
7-
/** A mirror of case with ordinal number `ordinal` and elements as given by `Product` */
8-
def mirror(ordinal: Int, product: Product): Mirror =
9-
new Mirror(this, ordinal, product)
10-
11-
/** A mirror with elements given as an array */
12-
def mirror(ordinal: Int, elems: Array[AnyRef]): Mirror =
13-
mirror(ordinal, new ArrayProduct(elems))
14-
15-
/** A mirror with an initial empty array of `numElems` elements, to be filled in. */
16-
def mirror(ordinal: Int, numElems: Int): Mirror =
17-
mirror(ordinal, new Array[AnyRef](numElems))
18-
19-
/** A mirror of a case with no elements */
20-
def mirror(ordinal: Int): Mirror =
21-
mirror(ordinal, EmptyProduct)
22-
23-
/** The case and element labels of the described ADT as encoded strings. */
24-
protected def caseLabels: Array[String]
25-
26-
private final val separator = '\000'
27-
28-
private def label(ordinal: Int, idx: Int): String = {
29-
val labels = caseLabels(ordinal)
30-
@tailrec def separatorPos(from: Int): Int =
31-
if (from == labels.length || labels(from) == separator) from
32-
else separatorPos(from + 1)
33-
@tailrec def findLabel(count: Int, idx: Int): String =
34-
if (idx == labels.length) ""
35-
else if (count == 0) labels.substring(idx, separatorPos(idx))
36-
else findLabel(if (labels(idx) == separator) count - 1 else count, idx + 1)
37-
findLabel(idx, 0)
4+
object TypeLevel {
5+
/** @param caseLabels The case and element labels of the described ADT as encoded strings.
6+
*/
7+
class ReflectedClass(labelsStr: String) {
8+
import ReflectedClass._
9+
10+
/** A mirror of case with ordinal number `ordinal` and elements as given by `Product` */
11+
def mirror(ordinal: Int, product: Product): Mirror =
12+
new Mirror(this, ordinal, product)
13+
14+
/** A mirror with elements given as an array */
15+
def mirror(ordinal: Int, elems: Array[AnyRef]): Mirror =
16+
mirror(ordinal, new ArrayProduct(elems))
17+
18+
/** A mirror with an initial empty array of `numElems` elements, to be filled in. */
19+
def mirror(ordinal: Int, numElems: Int): Mirror =
20+
mirror(ordinal, new Array[AnyRef](numElems))
21+
22+
/** A mirror of a case with no elements */
23+
def mirror(ordinal: Int): Mirror =
24+
mirror(ordinal, EmptyProduct)
25+
26+
val label: Array[Array[String]] =
27+
initLabels(0, 0, new mutable.ArrayBuffer[String], new mutable.ArrayBuffer[Array[String]])
28+
29+
private final val elemSeparator = '\000'
30+
private final val caseSeparator = '\001'
31+
32+
private def initLabels(start: Int, cur: Int,
33+
elems: mutable.ArrayBuffer[String],
34+
cases: mutable.ArrayBuffer[Array[String]]): Array[Array[String]] = {
35+
def addElem = elems += labelsStr.substring(start, cur)
36+
def addCase = cases += addElem.toArray
37+
if (cur == labelsStr.length)
38+
addCase.toArray
39+
else if (labelsStr(cur) == caseSeparator)
40+
initLabels(cur + 1, cur + 1, new mutable.ArrayBuffer, addCase)
41+
else if (labelsStr(cur) == elemSeparator)
42+
initLabels(cur + 1, cur + 1, addElem, cases)
43+
else
44+
initLabels(start, cur + 1, elems, cases)
45+
}
3846
}
39-
}
4047

41-
// Generic deriving infrastructure
42-
object Deriving {
48+
object ReflectedClass {
49+
/** Helper class to turn arrays into products */
50+
private class ArrayProduct(val elems: Array[AnyRef]) extends Product {
51+
def canEqual(that: Any): Boolean = true
52+
def productElement(n: Int) = elems(n)
53+
def productArity = elems.length
54+
override def productIterator: Iterator[Any] = elems.iterator
55+
def update(n: Int, x: Any) = elems(n) = x.asInstanceOf[AnyRef]
56+
}
57+
58+
/** Helper object */
59+
private object EmptyProduct extends Product {
60+
def canEqual(that: Any): Boolean = true
61+
def productElement(n: Int) = throw new IndexOutOfBoundsException
62+
def productArity = 0
63+
}
64+
}
4365

4466
/** A generic representation of a case in an ADT
45-
* @param deriving The companion object of the ADT
46-
* @param ordinal The ordinal value of the case in the list of the ADT's cases
47-
* @param elems The elements of the case
48-
*/
49-
class Mirror(val deriving: Deriving, val ordinal: Int, val elems: Product) {
67+
* @param deriving The companion object of the ADT
68+
* @param ordinal The ordinal value of the case in the list of the ADT's cases
69+
* @param elems The elements of the case
70+
*/
71+
class Mirror(val reflected: ReflectedClass, val ordinal: Int, val elems: Product) {
5072

5173
/** The `n`'th element of this generic case */
5274
def apply(n: Int): Any = elems.productElement(n)
5375

5476
/** The name of the constructor of the case reflected by this mirror */
55-
def caseLabel: String = deriving.label(ordinal, 0)
77+
def caseLabel: String = reflected.label(ordinal)(0)
5678

5779
/** The label of the `n`'th element of the case reflected by this mirror */
58-
def elementLabel(n: Int) = deriving.label(ordinal, n + 1)
80+
def elementLabel(n: Int) = reflected.label(ordinal)(n + 1)
5981
}
6082

6183
/** A class for mapping between an ADT value and
62-
* the case mirror that represents the value.
63-
*/
84+
* the case mirror that represents the value.
85+
*/
6486
abstract class Reflected[T] {
6587

6688
/** The case mirror corresponding to ADT instance `x` */
@@ -70,7 +92,7 @@ object Deriving {
7092
def reify(mirror: Mirror): T
7193

7294
/** The companion object of the ADT */
73-
def deriving: Deriving
95+
def common: ReflectedClass
7496
}
7597

7698
/** The shape of an ADT.
@@ -89,22 +111,6 @@ object Deriving {
89111
* It informs that type `T` has shape `S` and also implements runtime reflection on `T`.
90112
*/
91113
abstract class Shaped[T, S <: Shape] extends Reflected[T]
92-
93-
/** Helper class to turn arrays into products */
94-
private class ArrayProduct(val elems: Array[AnyRef]) extends Product {
95-
def canEqual(that: Any): Boolean = true
96-
def productElement(n: Int) = elems(n)
97-
def productArity = elems.length
98-
override def productIterator: Iterator[Any] = elems.iterator
99-
def update(n: Int, x: Any) = elems(n) = x.asInstanceOf[AnyRef]
100-
}
101-
102-
/** Helper object */
103-
private object EmptyProduct extends Product {
104-
def canEqual(that: Any): Boolean = true
105-
def productElement(n: Int) = throw new IndexOutOfBoundsException
106-
def productArity = 0
107-
}
108114
}
109115

110116
// An algebraic datatype
@@ -113,15 +119,18 @@ enum Lst[+T] {
113119
case Nil
114120
}
115121

116-
object Lst extends Deriving {
122+
object Lst {
117123
// common compiler-generated infrastructure
118-
import Deriving._
124+
import TypeLevel._
119125

120126
type Shape[T] = Shape.Cases[(
121127
Shape.Case[Cons[T], (T, Lst[T])],
122128
Shape.Case[Nil.type, Unit]
123129
)]
124130

131+
val reflectedClass = new ReflectedClass("Cons\000hd\000tl\001Nil")
132+
import reflectedClass.mirror
133+
125134
val NilMirror = mirror(1)
126135

127136
implicit def lstShape[T]: Shaped[Lst[T], Shape[T]] = new {
@@ -133,47 +142,49 @@ object Lst extends Deriving {
133142
case 0 => Cons[T](c(0).asInstanceOf, c(1).asInstanceOf)
134143
case 1 => Nil
135144
}
136-
def deriving = Lst
145+
def common = reflectedClass
137146
}
138147

139-
protected val caseLabels = Array("Cons\000hd\000tl", "Nil")
140-
141148
// three clauses that could be generated from a `derives` clause
142149
implicit def LstShow[T: Show]: Show[Lst[T]] = Show.derived
143150
}
144151

145152
// A simple product type
146-
case class Pair[T](x: T, y: T)
153+
case class Pair[T](x: T, y: T) // derives Eq, Pickler, Show
147154

148-
object Pair extends Deriving {
155+
object Pair {
149156
// common compiler-generated infrastructure
150-
import Deriving._
157+
import TypeLevel._
151158

152159
type Shape[T] = Shape.Case[Pair[T], (T, T)]
153160

161+
val reflectedClass = new ReflectedClass("Pair\000x\000y")
162+
import reflectedClass.mirror
163+
154164
implicit def pairShape[T]: Shaped[Pair[T], Shape[T]] = new {
155165
def reflect(xy: Pair[T]) =
156166
mirror(0, xy)
157167
def reify(c: Mirror): Pair[T] =
158168
Pair(c(0).asInstanceOf, c(1).asInstanceOf)
159-
def deriving = Pair
169+
def common = reflectedClass
160170
}
161-
162-
protected val caseLabels = Array("Pair\000x\000y")
163171
}
164172

165-
sealed trait Either[+L, +R] extends Product
173+
sealed trait Either[+L, +R] extends Product // derives Eq, Pickler, Show
166174
case class Left[L](x: L) extends Either[L, Nothing]
167175
case class Right[R](x: R) extends Either[Nothing, R]
168176

169-
object Either extends Deriving {
170-
import Deriving._
177+
object Either {
178+
import TypeLevel._
171179

172180
type Shape[L, R] = Shape.Cases[(
173181
Shape.Case[Left[L], L *: Unit],
174182
Shape.Case[Right[R], R *: Unit]
175183
)]
176184

185+
val reflectedClass = new ReflectedClass("Left\000x\001Right\000x")
186+
import reflectedClass.mirror
187+
177188
implicit def eitherShape[L, R]: Shaped[Either[L, R], Shape[L, R]] = new {
178189
def reflect(e: Either[L, R]): Mirror = e match {
179190
case e: Left[L] => mirror(0, e)
@@ -183,20 +194,17 @@ object Either extends Deriving {
183194
case 0 => Left[L](c(0).asInstanceOf)
184195
case 1 => Right[R](c(0).asInstanceOf)
185196
}
186-
def deriving = Either
197+
def common = reflectedClass
187198
}
188-
189-
protected val caseLabels = Array("Left\000x", "Right\000x")
190-
191199
implicit def EitherShow[L: Show, R: Show]: Show[Either[L, R]] = Show.derived
192200
}
193201

194202
trait Show[T] {
195203
def show(x: T): String
196204
}
197205
object Show {
198-
import scala.typelevel._
199-
import Deriving._
206+
import scala.typelevel.erasedValue
207+
import TypeLevel._
200208

201209
inline def tryShow[T](x: T): String = implicit match {
202210
case s: Show[T] => s.show(x)
@@ -245,7 +253,7 @@ object Show {
245253

246254
// Tests
247255
object Test extends App {
248-
import Deriving._
256+
import TypeLevel._
249257

250258
def showPrintln[T: Show](x: T): Unit =
251259
println(implicitly[Show[T]].show(x))

tests/run/typeclass-derivation2.scala

+25-20
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import scala.annotation.tailrec
44
object TypeLevel {
55
/** @param caseLabels The case and element labels of the described ADT as encoded strings.
66
*/
7-
class ReflectedClass(caseLabels: Array[String]) {
7+
class ReflectedClass(labelsStr: String) {
88
import ReflectedClass._
99

1010
/** A mirror of case with ordinal number `ordinal` and elements as given by `Product` */
@@ -23,18 +23,25 @@ object TypeLevel {
2323
def mirror(ordinal: Int): Mirror =
2424
mirror(ordinal, EmptyProduct)
2525

26-
private final val separator = '\000'
27-
28-
private[TypeLevel] def label(ordinal: Int, idx: Int): String = {
29-
val labels = caseLabels(ordinal)
30-
@tailrec def separatorPos(from: Int): Int =
31-
if (from == labels.length || labels(from) == separator) from
32-
else separatorPos(from + 1)
33-
@tailrec def findLabel(count: Int, idx: Int): String =
34-
if (idx == labels.length) ""
35-
else if (count == 0) labels.substring(idx, separatorPos(idx))
36-
else findLabel(if (labels(idx) == separator) count - 1 else count, idx + 1)
37-
findLabel(idx, 0)
26+
val label: Array[Array[String]] =
27+
initLabels(0, 0, new mutable.ArrayBuffer[String], new mutable.ArrayBuffer[Array[String]])
28+
29+
private final val elemSeparator = '\000'
30+
private final val caseSeparator = '\001'
31+
32+
private def initLabels(start: Int, cur: Int,
33+
elems: mutable.ArrayBuffer[String],
34+
cases: mutable.ArrayBuffer[Array[String]]): Array[Array[String]] = {
35+
def addElem = elems += labelsStr.substring(start, cur)
36+
def addCase = cases += addElem.toArray
37+
if (cur == labelsStr.length)
38+
addCase.toArray
39+
else if (labelsStr(cur) == caseSeparator)
40+
initLabels(cur + 1, cur + 1, new mutable.ArrayBuffer, addCase)
41+
else if (labelsStr(cur) == elemSeparator)
42+
initLabels(cur + 1, cur + 1, addElem, cases)
43+
else
44+
initLabels(start, cur + 1, elems, cases)
3845
}
3946
}
4047

@@ -67,10 +74,10 @@ object TypeLevel {
6774
def apply(n: Int): Any = elems.productElement(n)
6875

6976
/** The name of the constructor of the case reflected by this mirror */
70-
def caseLabel: String = reflected.label(ordinal, 0)
77+
def caseLabel: String = reflected.label(ordinal)(0)
7178

7279
/** The label of the `n`'th element of the case reflected by this mirror */
73-
def elementLabel(n: Int) = reflected.label(ordinal, n + 1)
80+
def elementLabel(n: Int) = reflected.label(ordinal)(n + 1)
7481
}
7582

7683
/** A class for mapping between an ADT value and
@@ -121,7 +128,7 @@ object Lst {
121128
Shape.Case[Nil.type, Unit]
122129
)]
123130

124-
val reflectedClass = new ReflectedClass(Array("Cons\000hd\000tl", "Nil"))
131+
val reflectedClass = new ReflectedClass("Cons\000hd\000tl\001Nil")
125132
import reflectedClass.mirror
126133

127134
val NilMirror = mirror(1)
@@ -138,8 +145,6 @@ object Lst {
138145
def common = reflectedClass
139146
}
140147

141-
protected val caseLabels = Array("Cons\000hd\000tl", "Nil")
142-
143148
// three clauses that could be generated from a `derives` clause
144149
implicit def LstEq[T: Eq]: Eq[Lst[T]] = Eq.derived
145150
implicit def LstPickler[T: Pickler]: Pickler[Lst[T]] = Pickler.derived
@@ -155,7 +160,7 @@ object Pair {
155160

156161
type Shape[T] = Shape.Case[Pair[T], (T, T)]
157162

158-
val reflectedClass = new ReflectedClass(Array("Pair\000x\000y"))
163+
val reflectedClass = new ReflectedClass("Pair\000x\000y")
159164
import reflectedClass.mirror
160165

161166
implicit def pairShape[T]: Shaped[Pair[T], Shape[T]] = new {
@@ -184,7 +189,7 @@ object Either {
184189
Shape.Case[Right[R], R *: Unit]
185190
)]
186191

187-
val reflectedClass = new ReflectedClass(Array("Left\000x", "Right\000x"))
192+
val reflectedClass = new ReflectedClass("Left\000x\001Right\000x")
188193
import reflectedClass.mirror
189194

190195
implicit def eitherShape[L, R]: Shaped[Either[L, R], Shape[L, R]] = new {

0 commit comments

Comments
 (0)