The signature of your method
def test[T <: A](): T
promises that for any type T
that is a subtype of A
you return a value of this type T
. And then you returned a value of type B
. You violated the signature (there are many subtypes of A
, not only B
).
For example you can try a type class (in this way you say that you return a value of T
not for any T <: A
at all but for any T <: A
that can be handled by the type class MakeT
)
def test[T <: A]()(implicit makeT: MakeT[T]): T = makeT.makeT()
trait MakeT[T] { // or MakeT[+T]
def makeT(): T
}
object MakeT {
implicit val bMakeT: MakeT[B] = () => new B {}
// or implicit def bMakeT[T >: B]: MakeT[T] = () => new B {}
}
test[B]().isInstanceOf[B] // true
In the situation described by @LuisMiguelMejíaSuárez in his comment
trait C extends A
you'll have
// test[C]() // doesn't compile, could not find implicit value for parameter makeT: MakeT[C]
Regarding generic return type see also
Why can't I return a concrete subtype of A if a generic subtype of A is declared as return parameter?
Type mismatch on abstract type used in pattern matching
Or you can use standard type classes =:=
, <:<
def test[T <: A]()(implicit ev: B =:= T): T = {
new B {}
}
(not implicit ev: T =:= B
)
or
def test[T <: A]()(implicit ev: B <:< T): T = {
new B {}
}
trait C extends A
and then I calltest[C]
(which is correct) and then it returns a B but I wanted a C?! - What is the meta-problem you want to solve; Since this looks like an xy-problem. – Downhearted