I checked in the implementation for covariant return types. If we just had to worry about Java then covariance is a one line change to the compiler since the JVM supports it natively. But to deal with .NET cleanly the actual covariance feature is implemented as follows:
Change fcode format such that each method defines both its return type and its "inherited return type" which is the return type of its original definition if covariant (extra 2 byte reference to the typeRefs table)
Compiler will output inherited return type when a covariant override detected
Fan reflection and compiler type checking use the covariant return type
Actual method emitted in JVM or IL uses the inherited return type
Any fcode call instructions use a method ref with the original inherited return type and automatically insert a cast operation if covariance detected
So to put another way from the fcode/emit world uses only the original definition of the return type, and we use the cast operation to keep the runtime happy. This is actually very similar to how generic return types are handled too.
brianMon 11 Dec 2006
I finished up the covariant error checking (I think - hopefully I've got my head around all the dark ugly boundary conditions). Basically when overriding a method defined by multiple types, the original methods must all have the exact same inherited type since that is the one actually used in the call instructions. Consider:
abstract class A
{
abstract A x()
}
mixin M
{
abstract M x()
}
class B extends A mixin M
{
override B x() { return this }
}
In this example according to the type system, then B correctly covariantly overrides x() from both A and M. However it has inconsistent inherited types so the runtime can't properly emit a single implementation and call instruction. So the compiler will report "Conflicting covariant returns" error.
Also I don't allow covariant fields or field/method overrides - covariance is only allowed on method/method overrides.
brian Sat 9 Dec 2006
I checked in the implementation for covariant return types. If we just had to worry about Java then covariance is a one line change to the compiler since the JVM supports it natively. But to deal with .NET cleanly the actual covariance feature is implemented as follows:
So to put another way from the fcode/emit world uses only the original definition of the return type, and we use the cast operation to keep the runtime happy. This is actually very similar to how generic return types are handled too.
brian Mon 11 Dec 2006
I finished up the covariant error checking (I think - hopefully I've got my head around all the dark ugly boundary conditions). Basically when overriding a method defined by multiple types, the original methods must all have the exact same inherited type since that is the one actually used in the call instructions. Consider:
In this example according to the type system, then B correctly covariantly overrides x() from both A and M. However it has inconsistent inherited types so the runtime can't properly emit a single implementation and call instruction. So the compiler will report "Conflicting covariant returns" error.
Also I don't allow covariant fields or field/method overrides - covariance is only allowed on method/method overrides.