Issue with casting

448 views Asked by At
    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

1

There are 1 answers

0
Dmytro Mitin On

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 remove lazy for Def#hashCode.

Covariance is irrelevant.

In this.asInstanceOf[Product] you're trying to cast Def's this to Product. When you create new N1() it is current Def's this.

new N1() as a value of class N1 cannot be cast to Product because N1 doesn't extend Product.

In Scala by default classes do not extend Product, case classes do.

To fix ClassCastException it's enough to make N1 a case class.