Understanding “inferred type arguments do not conform to type parameter bounds” errors in Scala

GDD picture GDD · Jan 11, 2013 · Viewed 7.3k times · Source

I fail to understand why I am getting an “inferred type arguments do not conform to type parameter bounds”. First, I defined a trait called CS which may be implemented by several classes (e.g., CS01 and CS02):

trait CS[+T <: CS[T]] {
  this: T =>
  def add: T
  def remove: T
}

class CS01 extends CS[CS01] {
  def add: CS01 = new CS01
  def remove: CS01 = new CS01
}

class CS02 extends CS[CS02] {
  def add: CS02 = new CS02
  def remove: CS02 = new CS02
}

The idea is to keep the implemented type when calling add or remove on CS01 and CS02. Secondly, I would like to define operations that may be executed on every classes compliant with trait CS. Then, I defined a trait called Exec(with two very simple examples of classes Exec01 and Exec02 mixin the Exec traits):

trait Exec {
  def exec[U <: CS[U]](x: U): U
}

class Exec01 extends Exec {
  def exec[U <: CS[U]](x: U): U = x.add
}

class Exec02 extends Exec {
  def exec[U <: CS[U]](x: U): U = x.remove
}

Once again, I need to keep the implemented type of the class that mixes the CS trait. That is why exec is parametrized with [U <: CS[U]].

Finally, I want any CS enabling operations on it to mixin the trait Executable which makes it possible to execute an operation that follows trait Exec:

trait Executable[T <: CS[T]] {
  this: T =>
  def execute(e: Exec): T = e.exec(this)
}

However, I get the following error when I am trying to compile:

error: inferred type arguments [this.Executable[T] with T] do not conform to method exec's type parameter bounds [U <: this.CS[U]]
  def execute(e: Exec): T = e.exec(this)
                              ^

I don't quite understand because any classes that mix Executable must be of type T with the constraint of mixin the CS trait due to the bound in trait Executable[T <: CS[T]]. So, why this does not conform to the type parameter bound U <: CS[U] ?

Answer

Jesper Nordenberg picture Jesper Nordenberg · Jan 11, 2013

Works if you specify the type parameter to exec explicitly:

def execute(e: Exec): T = e.exec[T](this)

Seems to be a limitation in the type inference.