A Promise is a mutable API that does not fit very well with covariance. Future does not suffer from this problem because you cannot manually complete them, as is the case with Promise .
Say we have:
class Animal class Cat extends Animal class Dog extends Animal
If you want Promise[A] be covariant compared to A , this means that we want Promise[Cat] <: Promise[Animal] and Promise[Dog] <: Promise[Animal] . Suppose we can do this.
Ok, let's assume that we have Promise[Cat] :
val p: Promise[Cat] = ...
By our assumption, it is also a Promise[Animal] :
val q: Promise[Animal] = p
Promise has a method called complete that takes a Try[T] , which is also covariant. This means that a Try[Dog] also a Try[Animal] . See where this is going?
We could call:
val value: Try[Dog] = ... q.complete(value)
Which would be legal because we are trying to complete Promise[Animal] with Try[Animal] , but unfortunately, we also just tried to complete Promise[Cat] with Promise[Dog] .
source share