The concept of "type arguments do not match the restrictions of type parameters" in Scala
Why aren't the following actions performed?
scala> abstract class Foo[B<:Foo[B]] defined class Foo scala> class Goo[B<:Foo[B]](x: B) defined class Goo scala> trait Hoo[B<:Foo[B]] { self: B => new Goo(self) } <console>:9: error: inferred type arguments [Hoo[B] with B] do not conform to class Goo type parameter bounds [B <: Foo[B]] trait Hoo[B<:Foo[B]] { self: B => new Goo(self) } ^ scala> trait Hoo[B<:Foo[B]] extends Foo[B] { new Goo(this) } <console>:9: error: inferred type arguments [Hoo[B]] do not conform to class Goo type parameter bounds [B <: Foo[B]] trait Hoo[B<:Foo[B]] extends Foo[B] { new Goo(this) } ^ In the first attempt, not Hoo[B] with B <: Foo[B] ?
In the second attempt, not Hoo[B] <: Foo[B] ?
To motivate this problem, there is a library with:
// "Foo" abstract class Record[PK, R <: Record[PK, R]] extends Equals { this: R => implicit def view(x: String) = new DefinitionHelper(x, this) ... } // "Hoo" class DefinitionHelper[R <: Record[_, R]](name: String, record: R) { def TEXT = ... ... } // now you can write: class MyRecord extends Record[Int, MyRecord] { val myfield = "myfield".TEXT } I am trying to introduce a new extension method along with TEXT called BYTEA so that I can write:
class MyRecord extends XRecord[Int, MyRecord] { val myfield = "myfield".BYTEA // implicit active only inside this scope } My attempts:
class XDefinitionHelper[R <: Record[_, R]](name: String, record: R) { def BYTEA = ... } trait XRecord[PK, R <: Record[PK, R]] { self: R => implicit def newView(x: String) = new XDefinitionHelper(x, self) } But this is facing the same problems as my smaller test case.
It seems too simple to be true (i.e.: to be good practice), but it still saved my day, so here is where:
scala> trait MyTrait[T <: MyTrait[T]] { self: T => def hello = println("hello") } scala> case class User(t: MyTrait[_]) <console>:8: error: type arguments [_$1] do not conform to trait MyTrait type parameter bounds [T <: MyTrait[T]] case class User(t: MyTrait[_]) scala> case class User(t: () => MyTrait[_]) defined class User