Single-level call rule and generics
The single-level call rule says that every call has to be valid for all possible dynamic types of an entity. So for a formal generic
G this means that the call has to be valid for all possible descendants of the constraint (or at least for every generic derivation that occurs in a system).
Let's look at an example using
class X [G -> NUMERIC] feature f (g1, g2: G): G do Result := g1 + g2 end end
Here, the call to
+ has to be valid for all possible descendants of
NUMERIC. Since the signature of the feature is
like Current, the call is never valid. This has to be the case as otherwise, the following code would produce a catcall:
x: X [NUMERIC] x.f (1, 1.0)
The problem is that the formal generic
G is always assumed to be of any type which satisfies the constraint, so normally the formal generic is polymorphic.
As the above example show, the use of features on formal generic parameters which are covariantly redefined is severely limited. But as the purpose of
NUMERIC is exactly to allow creation of generic algorithms over numeric types, this has to be addressed (Note that
COMPARABLE is also a problem).
Monomorphic formal generics
The first idea is to be able to mark a formal generic as monomorphic:
class X [monomorphic G -> NUMERIC] feature f (g1, g2: G): G do Result := g1 + g2 end end
[Comment by BM 5 Nov 2007: this does not seem desirable as there is nothing wrong with the class, only with the feature.]
For the check we can now assume that
G will be monomorphic. This helps a little bit further: For every feature argument which is
like Current we can assume that the exact type will be given. But this works only for covariant features which have
like Current arguments which are never redefined into something else. Take the following classes for an example:
class A feature f (a: like Current) do end end class B inherit A end class C inherit A redefine f feature f (a: D) do end end class D inherit C end
Now assume the following generic class:
class X [monomorphic G -> A] feature f local g1, g2: G do g1.f (g2) end end
The call to
g1.f is not valid since
G could be of type
C, and then the argument has to be of type
D. So now, not even the
like Current feature is callable with monomorphic generics. Basically it is the same as the declaration without monomorphic for the generic.
So this solution works only for the case of
like Current features never change the signature. Only then it can be guaranteed for a monomorphic generic formal, that the signature will match the formal generic exactly. Other covariant features have still to be valid for all possible descendants.
For the case of
COMPARABLE the use of monomorphic formal arguments would work as they define only
like Current features which are normally kept that way in subclasses. A more general mechanism would be nice but at the moment it is unclear how such a mechanism should look like.
Another way to solve the problem of
COMPARABLE would be to change the library. As these classes have mostly
like Current arguments and result types, they can be modeled via generics in the first place.
class NUMERIC [G -> NUMERIC [G]] feature infix "+" (other: G): G end class COMPARABLE [G -> COMPARABLE [G]] feature less_than (other: G): BOOLEAN end