1
1
import scala .collection .mutable
2
2
import scala .annotation .tailrec
3
3
4
+ object _typelevel {
5
+ final abstract class Type [- A , + B ]
6
+ type Subtype [t] = Type [_, t]
7
+ type Supertype [t] = Type [t, _]
8
+ type Exactly [t] = Type [t, t]
9
+ erased def typeOf [T ]: Type [T , T ] = ???
10
+ }
11
+
4
12
trait Deriving {
5
13
import Deriving ._
6
14
@@ -177,6 +185,7 @@ trait Eq[T] {
177
185
object Eq {
178
186
import scala .typelevel ._
179
187
import Deriving ._
188
+ import _typelevel ._
180
189
181
190
inline def tryEql [T ](x : T , y : T ) = implicit match {
182
191
case eq : Eq [T ] => eq.eql(x, y)
@@ -197,14 +206,19 @@ object Eq {
197
206
inline def eqlCases [T , Alts <: Tuple ](r : Reflected [T ], x : T , y : T ): Boolean =
198
207
inline erasedValue[Alts ] match {
199
208
case _ : (Shape .Case [alt, elems] *: alts1) =>
200
- x match {
201
- case x : `alt` =>
202
- y match {
203
- case y : `alt` => eqlCase[T , elems](r, x, y)
204
- case _ => false
209
+ inline typeOf[alt] match {
210
+ case _ : Subtype [T ] =>
211
+ x match {
212
+ case x : `alt` =>
213
+ y match {
214
+ case y : `alt` => eqlCase[T , elems](r, x, y)
215
+ case _ => false
216
+ }
217
+ case _ => eqlCases[T , alts1](r, x, y)
205
218
}
206
- case _ => eqlCases[T , alts1](r, x, y)
207
- }
219
+ case _ =>
220
+ error(" invalid call to eqlCases: one of Alts is not a subtype of T" )
221
+ }
208
222
case _ : Unit =>
209
223
false
210
224
}
@@ -232,6 +246,7 @@ trait Pickler[T] {
232
246
object Pickler {
233
247
import scala .typelevel ._
234
248
import Deriving ._
249
+ import _typelevel ._
235
250
236
251
def nextInt (buf : mutable.ListBuffer [Int ]): Int = try buf.head finally buf.trimStart(1 )
237
252
@@ -253,12 +268,17 @@ object Pickler {
253
268
inline def pickleCases [T , Alts <: Tuple ](r : Reflected [T ], buf : mutable.ListBuffer [Int ], x : T , n : Int ): Unit =
254
269
inline erasedValue[Alts ] match {
255
270
case _ : (Shape .Case [alt, elems] *: alts1) =>
256
- x match {
257
- case x : `alt` =>
258
- buf += n
259
- pickleCase[T , elems](r, buf, x)
271
+ inline typeOf[alt] match {
272
+ case _ : Subtype [T ] =>
273
+ x match {
274
+ case x : `alt` =>
275
+ buf += n
276
+ pickleCase[T , elems](r, buf, x)
277
+ case _ =>
278
+ pickleCases[T , alts1](r, buf, x, n + 1 )
279
+ }
260
280
case _ =>
261
- pickleCases[ T , alts1](r, buf, x, n + 1 )
281
+ error( " invalid pickleCases call: one of Alts is not a subtype of T " )
262
282
}
263
283
case _ : Unit =>
264
284
}
@@ -323,6 +343,7 @@ trait Show[T] {
323
343
object Show {
324
344
import scala .typelevel ._
325
345
import Deriving ._
346
+ import _typelevel ._
326
347
327
348
inline def tryShow [T ](x : T ): String = implicit match {
328
349
case s : Show [T ] => s.show(x)
@@ -347,9 +368,14 @@ object Show {
347
368
inline def showCases [T , Alts <: Tuple ](r : Reflected [T ], x : T ): String =
348
369
inline erasedValue[Alts ] match {
349
370
case _ : (Shape .Case [alt, elems] *: alts1) =>
350
- x match {
351
- case x : `alt` => showCase[T , elems](r, x)
352
- case _ => showCases[T , alts1](r, x)
371
+ inline typeOf[alt] match {
372
+ case _ : Subtype [T ] =>
373
+ x match {
374
+ case x : `alt` => showCase[T , elems](r, x)
375
+ case _ => showCases[T , alts1](r, x)
376
+ }
377
+ case _ =>
378
+ error(" invalid call to showCases: one of Alts is not a subtype of T" )
353
379
}
354
380
case _ : Unit =>
355
381
throw new MatchError (x)
@@ -424,4 +450,4 @@ object Test extends App {
424
450
println(implicitly[Show [T ]].show(x))
425
451
showPrintln(xs)
426
452
showPrintln(xss)
427
- }
453
+ }
0 commit comments