Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type equality in the Scala 2.10 Reflection API

I'm running into a weird issue with reflection in Scala 2.10.0 Milestone 4 that I can't wrap my head around. First for the stuff that works the way I'd expect:

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> trait A[X]; trait B[Y] extends A[Y]
defined trait A
defined trait B

scala> typeOf[B[String]].parents
res0: List[reflect.runtime.universe.Type] = List(java.lang.Object, A[String])

scala> typeOf[B[String]].parents contains typeOf[A[String]]
res1: Boolean = true

Similarly (in the same session):

scala> trait D; trait E extends A[D]
defined trait D
defined trait E

scala> typeOf[E].parents
res2: List[reflect.runtime.universe.Type] = List(java.lang.Object, A[D])

scala> typeOf[E].parents contains typeOf[A[D]]
res3: Boolean = true

No surprises here: I can ask for a type's parents and get exactly what I expect. Now I essentially combine the two examples above:

scala> trait F extends A[String]
defined trait F

scala> typeOf[F].parents
res4: List[reflect.runtime.universe.Type] = List(java.lang.Object, A[String])

scala> typeOf[F].parents contains typeOf[A[String]]
res5: Boolean = false

I don't understand how this could be false. The same thing happens if I have F extend A[Seq[D]], A[Int], etc. What's the generalization I'm missing that would make this behavior make sense?

like image 698
Travis Brown Avatar asked Jun 29 '12 01:06

Travis Brown


2 Answers

That's a bug. Right this morning I was going to investigate and fix it.

Edit. this appears to be an implementation detail of Scala reflection API leaking to the userland. It's not easy to fix, so for now we leave it as it is, but will look into the possibilities to improve.

In the meanwhile, to get correct results, one should always use =:= to compare types, not ==.

like image 78
Eugene Burmako Avatar answered Oct 08 '22 21:10

Eugene Burmako


Another illustration of the strangeness:

scala> val atype = typeOf[A[String]]
atype: reflect.runtime.universe.Type = A[String]

scala> val atype2 = typeOf[F].parents(1)
atype2: reflect.runtime.universe.Type = A[String]

scala> typeOf[F].parents contains atype
res39: Boolean = false

scala> typeOf[F].parents contains atype2
res40: Boolean = true

I think you're seeing a bug similar to this one: https://issues.scala-lang.org/browse/SI-5959 (although I've confirmed that this oddness occurs outside of the REPL too).

like image 32
brandon Avatar answered Oct 08 '22 23:10

brandon