Closed
Description
Compiler version
3.3.0, also tested with the latest nightly 3.3.2-RC1-bin-20230606-5d2812a-NIGHTLY
Minimized code
I'm splitting this into two snippets because for some reason the code to actually reproduce the error doesn't compile when it's compiled at the same time as the setup code
Setup code
Save this to a file and load a REPL with it
package test
import types._
object types {
opaque type ->>[K, V] = V
extension [K <: Singleton](k: K) def ->>[V](v: V): K ->> V = v.asInstanceOf[K ->> V]
}
type FindField[T <: Tuple, K] = FindField0[T, K, 0]
type FindField0[T <: Tuple, K, I <: Int] <: (Any, Int) = T match {
case (K ->> f) *: _ => (f, I)
case _ *: t => FindField0[t, K, compiletime.ops.int.S[I]]
}
trait Selector[T, Key] {
type Out
def apply(t: T): Out
}
object Selector {
type Aux[T, K, O] = Selector[T, K] { type Out = O }
inline def apply[T, K](using s: Selector[T, K]): Aux[T, K, s.Out] = s
inline given selectorInst[T <: Tuple, K](
using idx: ValueOf[Tuple.Elem[FindField[T, K], 1]],
): Selector.Aux[T, K, Tuple.Head[FindField[T, K]]] =
new Selector[T, K] {
type Out = Tuple.Head[FindField[T, K]]
def apply(t: T): Out = t.productElement(idx.value).asInstanceOf[Out]
}
}
Error code
Run this code in the REPL
import test._
import test.types._
val t = ("s" ->> "foo") *: ("i" ->> 3) *: EmptyTuple
val s = Selector[("s" ->> String) *: ("i" ->> Int) *: EmptyTuple, "i"]
s(t)
Output
scala> s(t)
java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
at rs$line$4$$anon$1.apply(rs$line$4:1)
at rs$line$4$$anon$1.apply(rs$line$4:1)
... 66 elided
Expectation
The code should run without error and return an Int
. Interestingly, if you make a small change to the definition of opaque type ->>
, then the error goes away:
diff --git a/Selector.scala b/Selector.scala
index 69bd8a3..314e219 100644
--- a/Selector.scala
+++ b/Selector.scala
@@ -3,7 +3,8 @@ package test
import types._
object types {
- opaque type ->>[K, V] = V
+ type Tag[A]
+ opaque type ->>[K, V] = V & Tag[K]
extension [K <: Singleton](k: K) def ->>[V](v: V): K ->> V = v.asInstanceOf[K ->> V]
}