Same type ascription loses type member information on variable declaration but not on method parameter declaration

90 Views Asked by At

Consider path-dependent type

trait Foo[In] {
  type Out
  def f(v: In): Out
}

implicit val preciseFooInt: Foo[Int] { type Out = String } = new Foo[Int] {
  type Out = String
  def f(v: Int): String = v.toString
}

where we see output type Out declared as type member. Also note the precisely declared type of preciseFooInt instance

Foo[Int] { type Out = String }

Now let's lose the type member precision by forcing assignment to its supertype

val ev: Foo[Int] = preciseFooInt

Because we omitted type refinement { type Out = String } the compiler does not know the output type is precisely String which makes sense

scala> val ev: Foo[Int] = preciseFooInt
val ev: Foo[Int] = $anon$1@2fd641f6

scala> val s: String = ev.f(42)
                           ^
       error: type mismatch;
        found   : ev.Out
        required: String

However let's do very similar motions but via method parameter declaration

def g(ev: Foo[Int]) = ev.f(42)

Note how method parameter ev has exactly the same type ascription as variable ev before, namely Foo[Int] without the specific type member refinement { type Out = String }. Nevertheless now there is no loss of type member precision

scala> def g(ev: Foo[Int]) = ev.f(42)
def g(ev: Foo[Int]): ev.Out

scala> val s: String = g(ev = preciseFooInt)
val s: String = 42

What is the difference between the variable declaration and method parameter declaration with respect to type members? Given type ascription was the same in both cases, why was there no loss of information in method parameter case?

0

There are 0 best solutions below