The issue is not with covariance itself. (In particular, if it were contra-variance, Design-by-Contract would be impossible, because argument types in the features of descendant classes would not necessary have features available in their parents. With covariance there is no such a problem.)
Problematic is a combination of covariance with polymorphism. E.g.
class A feature
foo (a: A) do a.bar end -- (1)
bar do end
end
class B inherit A redefine foo end feature
foo (a: B) do a.qux end -- (2)
qux do end
end
Now the following code would crash:
a: A; b: B
...
create b
a := b
a.foo (create {A})
Indeed, a.foo
would call version (2) because a
is attached to an object of type B
. However, the argument passed to this feature will be of type A
. And A
has no feature qux
that leads to a run-time error. This kind of an error is know as a CAT-call (Changing Availability or Type).
A solution to this issue is to avoid using covariance together with polymorphism, i.e. a call should not be polymorphic or there should be no covariant redeclaration of arguments. The work on this solution is in progress.