6
votes

I stumbled upon a puzzling behaviour of Type.=:= when applied on type refinments. Consider:

import reflect.runtime.universe._
type T1 = AnyRef {
  def apply( name: String ): Unit
  def foo: String
}

type Base = { def apply( name: String ): Unit }
type T2 = Base {
  def foo: String
}

Given that Base is an alias for a type refinement, I would expected that refining it further by adding the member foo would yield the same type as if I had defined foo right in Base.

Or in other words, I would expect that T1 and T2 denote entirely equivalent types.

For the most part, scalac seems to agree. By example I can pass an instance of T2 where an instance of T1 is expected:

def f( x: T1 ){}
f( null: T2 ) // scalac does not complain here

And conversely:

def g( x: T2 ){}
g( null: T1 ) // scalac is still happy

I can also ask for an evidence T1 =:= T2 and it compiles fine too:

implicitly[T1 =:= T2]

However, using scala reflection I get entirely different results:

scala> typeOf[T1] =:= typeOf[T2]
res2: Boolean = false

So is this a scala reflection bug (I would guess so) or is there a fundamental reason (technical of otherwise) why typeOf[T1] =:= typeOf[T2] would return false?

1
typeOf[T1] <:< typeOf[T2] and conversely are also true.som-snytt
That's a nice observation. At least there is some consistency then. The other great thing is that at the very least it provides me with a workaround: I can just test for (typeOf[T1] <:< typeOf[T2]) && (typeOf[T2] <:< typeOf[T1]). Obviously this still feels like a hack thoughRégis Jean-Gilles

1 Answers

4
votes

Sadly, it looks to be this bug: https://issues.scala-lang.org/browse/SI-8177

On the plus side... it looks like there's work actively underway to fix it :)