import scala.annotation.unchecked.uncheckedVariance
import scala.collection.immutable.Queue
import scala.collection.mutable.ListBuffer
abstract class Exp[+T:Manifest] { // constants/symbols (atomic)
def tp: Manifest[T @uncheckedVariance] = manifest[T] //invariant position! but hey...
}
case class Sym[+T:Manifest](val id: Int) extends Exp[T] {
}
abstract class Def[+T] { // operations (composite)
override final lazy val hashCode = scala.runtime.ScalaRunTime._hashCode(this.asInstanceOf[Product])
}
abstract class Stm
case class TP[+T](sym: Sym[T], rhs: Def[T]) extends Stm
abstract class Trial{
}
class M1() extends Trial{}
class M2() extends Trial{}
class N1() extends Def[M1]{}
class N2() extends Def[M2]{}
TP(Sym[M1]{4},new N1())
This gives the following error:
scala> TP(Sym[M1]{4},new N1()) java.lang.ClassCastException: class N1 cannot be cast to class scala.Product (N1 is in unnamed module of loader scala.tools.nsc.interpreter.IMain$TranslatingClassLoader @2098d37d; scala.Product is in unnamed module of loader 'bootstrap')
at Def.hashCode$lzycompute(:13) at Def.hashCode(:13) at java.base/java.lang.Object.toString(Object.java:246) at java.base/java.lang.String.valueOf(String.java:2951) at java.base/java.lang.StringBuilder.append(StringBuilder.java:168) at scala.collection.IterableOnceOps.addString(IterableOnce.scala:1194)
at scala.collection.IterableOnceOps.addString$(IterableOnce.scala:1186)
at scala.collection.AbstractIterator.addString(Iterator.scala:1279)
at scala.collection.IterableOnceOps.mkString(IterableOnce.scala:1136) at scala.collection.IterableOnceOps.mkString$(IterableOnce.scala:1134) at scala.collection.AbstractIterator.mkString(Iterator.scala:1279)
at scala.runtime.ScalaRunTime$._toString(ScalaRunTime.scala:159) at TP.toString(:18) at scala.runtime.ScalaRunTime$.inner$1(ScalaRunTime.scala:261) at scala.runtime.ScalaRunTime$.stringOf(ScalaRunTime.scala:266) at scala.runtime.ScalaRunTime$.replStringOf(ScalaRunTime.scala:274) at .lzycompute(:8) ... 28 elided
I was expecting an object of type TP[Trial], what happened? Since Sym and Def are covariant types. Am I missing something?
Thanks
At Scastie it isn't reprodusible as https://scastie.scala-lang.org/tCD4HahgTqO4WTnlGcfWqQ but is reprodusible as https://scastie.scala-lang.org/L46PWLF2S5i4d1IGoT6UuQ
Locally I can reproduce
ClassCastException
only if I removelazy
forDef#hashCode
.Covariance is irrelevant.
In
this.asInstanceOf[Product]
you're trying to castDef
'sthis
toProduct
. When you createnew N1()
it is currentDef
'sthis
.new N1()
as a value of classN1
cannot be cast toProduct
becauseN1
doesn't extendProduct
.In Scala by default classes do not extend
Product
, case classes do.To fix
ClassCastException
it's enough to makeN1
a case class.