4

Sometimes in Scala I find that I get type mismatches related to path-dependent types, but I can easily reason that in fact the types coincide. Here's a simple example:

trait Foo { trait Bar }

object Main extends App {
  val foo1 = new Foo { }
  val foo2 = foo1

  def turkle(x: foo1.Bar) {}

  turkle(new foo2.Bar {})
}

which gives: "type mismatch; found : java.lang.Object with Main.foo2.Bar required: Main.foo1.Bar".

Now of course the paths Main.foo1.Bar and Main.foo2.Bar must coincide, since we wrote val foo2 = foo1. We can verify this, by changing the last line to

turkle((new foo2.Bar {}).asInstanceOf[foo1.Bar])

which both compiles and runs without an exception.

Can Scala automatically perform reasoning like this? If so, how can I make this happen?

(And if not, are there any prospects for extending the type system in this direction?)

I'll note that sometimes Scala does appear to perform this sort of reasoning. Supposing I change trait Foo to object Foo:

object Foo { trait Bar }

object Main extends App {
  val foo1 = Foo
  val foo2 = foo1

  def turkle(x: foo1.Bar) {}

  turkle(new foo2.Bar {})
}

Now everything compiles fine: somehow Scala has worked out that both Main.foo1.Bar and Main.foo2.Bar are really the same as Foo.Bar.

Scott Morrison
  • 3,090
  • 21
  • 39
  • I saw a section titled ``Path Equality'' in Adrian Moors notes here: https://groups.google.com/forum/#!msg/scala-language/8gWgzVY-Zd0/1m5VL26QZ6sJ, but I don't have any sense of how this relates to my question in Scala as it exists now. – Scott Morrison Dec 22 '11 at 19:52

1 Answers1

5

Iulian Dragos gave the answer you need in a recent question. The short version is that the compiler doesn't do flow analysis, so in your first example it can't tell that foo1.Bar and foo2.Bar are the same type since foo1 and foo2 are just of type Foo. But in the second example foo1 is inferred to be the singleton type Foo.type (a subtype of Foo), so things work as expected.

You can make your first example work by declaring foo2 as being the singleton type of foo1:

val foo2:foo1.type = foo1

See section 3.2.1 of the Scala Language Specification 2.9 for reference.

Community
  • 1
  • 1
rxg
  • 3,547
  • 19
  • 38