D#B
is a type projection, and is not the same as d.B
. You have a type mismatch because in foo
, B
actually meant this.B
, which as said is not the same as D#B
(the latter being more general).
Informally, you can think of D#B
as representing any possible type that the abstract type B
can take for any instance of D
, while d.B
is the type of B
for the specific instance d
.
See What does the `#` operator mean in Scala? and What is meant by Scala's path-dependent types? for some context.
One way to make it compile it is by changing createB
's return type to d.B
:
def createB(): d.B
However in many cases such a solution is too restrictive because you are tied to the specific instance d
, which might not be what you had in mind.
Another solution is then to replace the abstract type with a type parameter (though it is more verbose):
trait A[B] {
def foo(b: B)
}
trait C[B, D <: A[B]] {
val d: D
def createB(): B
def bar() {
d.foo(createB)
}
}