Search code examples
scalatypespath-dependent-type

relationship between path-dependent inner types in Scala


Warning: I'm cross-posting from #scala

The book Programming in Scala states that path-dependent types are different depending on the exact instance of the path in question. If so, I don't understand why all the following predicates return true:

class Outer {
  val in = new Inner
  class Inner
}

val o1 = new Outer
val o2 = new Outer

o1.in.isInstanceOf[Outer#Inner] //makes perfect sense
o1.in.isInstanceOf[o1.Inner]    //still makes sense, the path-dependent type is o1's own
o1.in.isInstanceOf[o2.Inner]    //why is this true? PiS p.423 says the path-dependent types are different, they only share a common supertype Outer#Inner

Solution

  • o1.Inner and o2.Inner are different types, but their erasures are the same:

    scala> class Outer {
         |   val in = new Inner
         |   class Inner
         | }
    defined class Outer
    
    scala> val o1 = new Outer
    o1: Outer = Outer@1d16ecf
    
    scala> val m1 = implicitly[Manifest[o1.Inner]]
    m1: Manifest[o1.Inner] = Outer@1d16ecf.type#Outer$Inner
    
    scala> m1.erasure
    res0: java.lang.Class[_] = class Outer$Inner
    
    scala> val o2 = new Outer
    o2: Outer = Outer@138ef1d
    
    scala> val m2 = implicitly[Manifest[o2.Inner]]
    m2: Manifest[o2.Inner] = Outer@138ef1d.type#Outer$Inner
    
    scala> m2.erasure
    res1: java.lang.Class[_] = class Outer$Inner
    

    and o1.in.isInstanceOf[o2.Inner] can only check that o1.in is an instance of the erasure of o2.Inner.