I have a generic F-bounded trait in Scala. Lets me write methods that return the same underlying implementation type, super! But now lets say a sub-trait also defines methods that require F-bounding. Scala is sending me back compile errors that don't make sense:
package sandbox
import sandbox.ComplexImpl.AnyComplexImpl
import scala.language.existentials
trait FBounded[IMPL <: FBounded[IMPL]] { self: IMPL =>
def foo: IMPL
}
trait FBoundedUser[F <: FBounded[F]] {
def bar(value: F): F = value.foo
}
trait SimpleImpl extends FBounded[SimpleImpl] {
override def foo: SimpleImpl = this
}
object SimpleUser extends FBoundedUser[SimpleImpl]
// A-OK so far...
trait ComplexImpl[IMPL <: ComplexImpl[IMPL]] extends FBounded[IMPL] { self: IMPL =>
def baz: IMPL
}
object ComplexImpl {
type AnyComplexImpl = ComplexImpl[T] forSome { type T <: ComplexImpl[T] }
}
object ComplexUser1 extends FBoundedUser[ComplexImpl[_]]
object ComplexUser2 extends FBoundedUser[AnyComplexImpl]
Trying to compile with either of ComplexUser1 or ComplexUser2 results in:
Error:(32, 29) type arguments [sandbox.ComplexImpl.AnyComplexImpl] do not conform to trait
FBoundedUser's type parameter bounds [F <: sandbox.FBounded[F]]
Which doesn't make sense to me. AnyComplexImpl definitely implements FBounded. Am I missing something, or is the type checker just failing me here?
EDIT:
class Concrete() extends ComplexImpl[Concrete] {
override def baz: Concrete = this
override def foo: Concrete = this
}
object ComplexUser3 extends FBoundedUser[Concrete]
Compiles just fine. So why won't the generic version?