Structural type refinement and type equality
Asked Answered
B

1

6

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?

Blabber answered 7/2, 2014 at 13:59 Comment(2)
typeOf[T1] <:< typeOf[T2] and conversely are also true.Cubicle
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 thoughAudi
G
4

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 :)

Gleich answered 7/2, 2014 at 17:9 Comment(2)
+1 for pointing me to related bug(s). But I am not sure this is the bug I'm experiencing. SI-8177 is about dependent types and invalid handling of type prefixes. The only way I can think this affects my above code snippet is because my type aliases have different prefixes. This is indeed the case in the REPL, but I tried wrapping all the definitions in the same object (=> same prefix) and I still get the same error. It is possible though that fixing SI-8177 will fix my problem as a side effect. I'll try with 2.11.0-RC1 when it's out, and if fixed I'll validate your answer.Audi
OK, scala 2.11.0-RC1 has just been released, so I tried against it (seeing as SI-8177 is marked as fixed in scala 2.11.0-RC1). The bug is definitly still there, so as I suspected SI-8177 does not cover my described problem. Maybe it's time to open a ticket.Audi

© 2022 - 2024 — McMap. All rights reserved.