@@ -113,6 +113,13 @@ object TypeLevel {
113113 * It informs that type `T` has shape `S` and also implements runtime reflection on `T`.
114114 */
115115 abstract class Shaped [T , S <: Shape ] extends Reflected [T ]
116+
117+ // substitute for erasedValue that allows precise matching
118+ final abstract class Type [- A , + B ]
119+ type Subtype [t] = Type [_, t]
120+ type Supertype [t] = Type [t, _]
121+ type Exactly [t] = Type [t, t]
122+ erased def typeOf [T ]: Type [T , T ] = ???
116123}
117124
118125// An algebraic datatype
@@ -217,7 +224,7 @@ trait Eq[T] {
217224}
218225
219226object Eq {
220- import scala .compiletime .erasedValue
227+ import scala .compiletime .{ erasedValue , error }
221228 import TypeLevel ._
222229
223230 inline def tryEql [T ](x : T , y : T ) = implicit match {
@@ -239,8 +246,13 @@ object Eq {
239246 inline def eqlCases [T , Alts <: Tuple ](xm : Mirror , ym : Mirror , ordinal : Int , n : Int ): Boolean =
240247 inline erasedValue[Alts ] match {
241248 case _ : (Shape .Case [alt, elems] *: alts1) =>
242- if (n == ordinal) eqlElems[elems](xm, ym, 0 )
243- else eqlCases[T , alts1](xm, ym, ordinal, n + 1 )
249+ inline typeOf[alt] match {
250+ case _ : Subtype [T ] =>
251+ if (n == ordinal) eqlElems[elems](xm, ym, 0 )
252+ else eqlCases[T , alts1](xm, ym, ordinal, n + 1 )
253+ case _ =>
254+ error(" invalid call to eqlCases: one of Alts is not a subtype of T" )
255+ }
244256 case _ : Unit =>
245257 false
246258 }
@@ -271,7 +283,7 @@ trait Pickler[T] {
271283}
272284
273285object Pickler {
274- import scala .compiletime .{erasedValue , constValue }
286+ import scala .compiletime .{erasedValue , constValue , error }
275287 import TypeLevel ._
276288
277289 def nextInt (buf : mutable.ListBuffer [Int ]): Int = try buf.head finally buf.trimStart(1 )
@@ -294,12 +306,17 @@ object Pickler {
294306 inline def pickleCases [T , Alts <: Tuple ](r : Reflected [T ], buf : mutable.ListBuffer [Int ], x : T , n : Int ): Unit =
295307 inline erasedValue[Alts ] match {
296308 case _ : (Shape .Case [alt, elems] *: alts1) =>
297- x match {
298- case x : `alt` =>
299- buf += n
300- pickleCase[T , elems](r, buf, x)
309+ inline typeOf[alt] match {
310+ case _ : Subtype [T ] =>
311+ x match {
312+ case x : `alt` =>
313+ buf += n
314+ pickleCase[T , elems](r, buf, x)
315+ case _ =>
316+ pickleCases[T , alts1](r, buf, x, n + 1 )
317+ }
301318 case _ =>
302- pickleCases[ T , alts1](r, buf, x, n + 1 )
319+ error( " invalid pickleCases call: one of Alts is not a subtype of T " )
303320 }
304321 case _ : Unit =>
305322 }
@@ -362,7 +379,7 @@ trait Show[T] {
362379 def show (x : T ): String
363380}
364381object Show {
365- import scala .compiletime .erasedValue
382+ import scala .compiletime .{ erasedValue , error }
366383 import TypeLevel ._
367384
368385 inline def tryShow [T ](x : T ): String = implicit match {
@@ -388,9 +405,15 @@ object Show {
388405 inline def showCases [T , Alts <: Tuple ](r : Reflected [T ], x : T ): String =
389406 inline erasedValue[Alts ] match {
390407 case _ : (Shape .Case [alt, elems] *: alts1) =>
391- x match {
392- case x : `alt` => showCase[T , elems](r, x)
393- case _ => showCases[T , alts1](r, x)
408+ inline typeOf[alt] match {
409+ case _ : Subtype [T ] =>
410+ x match {
411+ case x : `alt` =>
412+ showCase[T , elems](r, x)
413+ case _ => showCases[T , alts1](r, x)
414+ }
415+ case _ =>
416+ error(" invalid call to showCases: one of Alts is not a subtype of T" )
394417 }
395418 case _ : Unit =>
396419 throw new MatchError (x)
@@ -486,4 +509,4 @@ object Test extends App {
486509 val zs1 = copy(zs)
487510 showPrintln(zs1)
488511 assert(eql(zs, zs1))
489- }
512+ }
0 commit comments