While experimenting with path dependent types, I experienced some unexpected results:
object Funny1 {
class X {
type Y = String
val y: Y = "y"
}
val x1 = new X
val x2 = new X
def foo(x: X)(y: x.Y): Unit = ()
def foo_diff(y1: x1.Y)(y2: x2.Y): Unit = () // 1.3
def foo_gen(y1: X#Y)(y2: X#Y) : Unit = ()
foo(x1)(x1.y)
foo(x1)(x2.y) // <-- 1.1 would expect this to fail
foo_diff(x1.y)(x2.y)
foo_diff(x2.y)(x2.y) // <-- 1.2 would expect this to fail
foo_gen(x1.y)(x2.y)
foo_gen(x2.y)(x2.y)
}
object Funny2 {
class X {
class Y {
}
}
val x1 = new X
val x2 = new X
val x1y = new x1.Y
val x2y = new x2.Y
def foo(x: X)(y: x.Y): Unit = ()
def foo_diff(y1: x1.Y)(y2: x2.Y): Unit = ()
def foo_gen(y1: X#Y)(y2: X#Y) : Unit = ()
foo(x1)(x1y)
// foo(x1)(x2y) // does not compile
foo_diff(x1y)(x2y)
// foo_diff(x2y)(x2y) // does not compile
foo_gen(x1y)(x2y)
foo_gen(x2y)(x2y)
}
object Funny3 {
trait X {
type Y
def y: Y
}
val x1 = new X {
override type Y = String
override def y: String = "y"
}
val x2 = new X {
override type Y = Int
override def y: Int = 3
}
def foo(x: X)(y: x.Y): Unit = ()
def foo_diff(y1: x1.Y)(y2: x2.Y): Unit = ()
def foo_gen(y1: X#Y)(y2: X#Y) : Unit = ()
foo(x1)(x1.y)
// foo(x1)(x2.y) // 3.1 fails as expected
foo_diff(x1.y)(x2.y)
// foo_diff(x2.y)(x2.y) // 3.2 fails as expected
foo_gen(x1.y)(x2.y)
foo_gen(x2.y)(x2.y)
}
object Funny3b {
trait X {
type Y
def y: Y
}
val x1 = new X {
override type Y = String
override def y: String = "y"
}
val x2 = new X {
override type Y = String
override def y: String = "y2"
}
def foo(x: X)(y: x.Y): Unit = ()
def foo_diff(y1: x1.Y)(y2: x2.Y): Unit = ()
def foo_gen(y1: X#Y)(y2: X#Y) : Unit = ()
foo(x1)(x1.y)
foo(x1)(x2.y) // 3b.1 does not fail
foo_diff(x1.y)(x2.y)
foo_diff(x2.y)(x2.y) // 3b.2 does not fail
foo_gen(x1.y)(x2.y)
foo_gen(x2.y)(x2.y)
}
Especially, I am interested in the answers to the questions:
- Why do the line marked 1.1 and 1.2) compile?
- Why is no reference to
xas first parameter required in 1.3foo_diff? - Why do the lines 3.1 and 3.2 not compile, but 3b.1 and 3b.2 compile? Especially as the path dependency seems to be "lost" in 3b, if underlying types can be resolved to be identical (here: String).
Thanks, Martin