5

Say I have a type

trait Mode[T]
trait MyType[T, M <: Mode[T]]

This compiles

val t: MyType[_, _] = ???
t

But not this one

val t: MyType[_, _] = ???
"some_string" -> t

Error says something like type arguments [_$0,_$1] do not conform to trait MyType's type parameter bounds

So my question is that why this does not compile on tuple creation?

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
darkjh
  • 2,821
  • 7
  • 35
  • 43
  • 1
    By the way, if you specify types for tuple explicitly this compiles: `Tuple2[String, MyType[_, _]]("some_string", t)`. – Dmytro Mitin Feb 26 '19 at 17:21
  • https://stackoverflow.com/questions/4323140/why-are-the-bounds-of-type-parameters-ignored-when-using-existential-types-in-sc – Dmytro Mitin Feb 27 '19 at 19:56

1 Answers1

2

Actually both t and "some string" -> t will break at runtime with the same issue:

import scala.language.existentials
import scala.reflect.runtime.universe._

type SubMode[T] = M forSome { type M <: Mode[T] }

val t: MyType[_, _] = new MyType[String, SubMode[String]] {}
// t: MyType[_, _] = $anon$1@596afb2f

"some string" -> t
// error: type arguments [_$1,_$2] do not conform to trait MyType's type parameter bounds [T,M <: Mode[T]]

reify(t)
// error: type arguments [_$1,_$2] do not conform to trait MyType's type parameter bounds [T,M <: Mode[T]]

reify("some string" -> t)
// error: type arguments [_$1,_$2] do not conform to trait MyType's type parameter bounds [T,M <: Mode[T]]

In fact, the issue at compile-time is not specific to Tuples. For example:

List(t)
// error: type arguments [_$1,_$2] do not conform to trait MyType's type parameter bounds [T,M <: Mode[T]]

My guess is that while the definition of t alone does not trigger a compilation error, an additional "touch" on t might. It'll all work fine if you let the compiler infer the proper type:

val t2 = new MyType[String, SubMode[String]] {}
t2: MyType[String,SubMode[String]] = $anon$1@19d53ab4

"some string" -> t2
// res1: (String, MyType[String,SubMode[String]]) = (some string,$anon$1@19d53ab4)

List(t2)
// res2: List[MyType[String,SubMode[String]]] = List($anon$1@19d53ab4)
Leo C
  • 22,006
  • 3
  • 26
  • 39
  • "any additional "touch" on t does" It's not so easy. `trait Mode[T]` `trait MyType[T1, M1 <: Mode[T1]] { def foo: Any }` `val t: MyType[_, _] = ???` `t.foo` compiles. – Dmytro Mitin Feb 26 '19 at 19:45
  • 1
    @Dmytro Mitin, thanks for the example. I've softened the said clause. – Leo C Feb 26 '19 at 20:11