Consider the following example:

```
case class C[T](x:T) {
  def f(t:T) = println(t)
  type ValueType = T
}

val list = List(1 -> C(2), "hello" -> C("goodbye"))

for ((a,b) <- list) {
  b.f(a)
}

```

In this example, I know (runtime guarantee) that the type of `a` will be some `T`, and `b` will have type `C[T]` with the same `T`. Of course, the compiler cannot know that, hence we get a typing error in `b.f(a)`.

To tell the compiler that this invocation is OK, we need to do a typecast à la `b.f(a.asInstanceOf[T])`. Unfortunately, `T` is not known here. So my question is: How do I rewrite `b.f(a)` in order to make this code compile?

I am looking for a solution that does not involve complex constructions (to keep the code readable), and that is "clean" in the sense that we should not rely on code erasure to make it work (see the first approach below).

I have some working approaches, but I find them unsatisfactory for various reasons.

Approaches I tried:
-------------------

```
b.asInstanceOf[C[Any]].f(a)

```

This works, and is reasonably readable, but it is based on a "lie". `b` is not of type `C[Any]`, and the only reason we do not get a runtime error is because we rely on the limitations of the JVM (type erasure). I think it is good style only to use `x.asInstanceOf[X]` when we know that `x` is really of type `X`.

```
  b.f(a.asInstanceOf[b.ValueType])

```

This should work according to my understanding of the type system. I have added the member `ValueType` to the class `C` in order to be able to explicitly refer to the type parameter `T`. However, in this approach we get a mysterious error message:

```
Error:(9, 22) type mismatch;
 found   : b.ValueType
    (which expands to)  _1
 required: _1
  b.f(a.asInstanceOf[b.ValueType])
                    ^

```

Why? It seems to complain that we expect type `_1` but got type `_1`! (But even if this approach works, it is limited to the cases where we have the possibility to add a member `ValueType` to `C`. If `C` is some existing library class, we cannot do that either.)

```
for ((a,b) <- list.asInstanceOf[List[(T,C[T]) forSome {type T}]]) {
  b.f(a)
}

```

This one works, and is semantically correct (i.e., we do not "lie" when invoking `asInstanceOf`). The limitation is that this is somewhat unreadable. Also, it is somewhat specific to the present situation: if `a,b` do not come from the same iterator, then where can we apply this type cast? (This code also has the side effect of being too complex for Intelli/J IDEA 2016.2 which highlights it as an error in the editor.)

```
  val (a2,b2) = (a,b).asInstanceOf[(T,C[T]) forSome {type T}]
  b2.f(a2)

```

I would have expected this one to work since `a2,b2` now should have types `T` and `C[T]` for the same existential `T`. But we get a compile error:

```
Error:(10, 9) type mismatch;
 found   : a2.type (with underlying type Any)
 required: T
  b2.f(a2)
       ^

```

Why? (Besides that, the approach has the disadvantage of incurring runtime costs (I think) because of the creation and destruction of a pair.)

```
  b match {
    case b : C[t] => b.f(a.asInstanceOf[t])
  }

```

This works. But enclosing the code with a match makes the code much less readable. (And it also is too complicated for Intelli/J.)