Hi everyone,

I recently switched some classes in my framework from @CompileStatic to @TypeChecked (e.g. to get dynamic call site selection), and am still facing the problem that method/ctor calls where passing null for arguments is valid*, fail with ambigous overloading runtime errors. These cases of course work in the @CompileStatic case, since call site selection is static and dependent on the type of the parameter, but fail in the @TypeChecked case, since the null value does not carry type information. Groovy introduced explicit type cast support for these cases a while back, and I have started to refactor my code to do this, but it is very noisy/inconvenient/inelegant. So I am wondering if it would not make sense to use the parameter type from the method signature to decide on what method to call in the dynamic case, if the parameter value is null (basically like in the @CompileStatic case, only at runtime in this special case) ?

Samples (Goo1 is not a subtype of Goo0):

@TypeChecked
class Goo {
    def callFoo_Fails(Goo0 g0) { foo(g0) } // Expectation for g0 == null case: foo(Goo0) gets called; actual: Fails during runtime with ambigous method GroovyRuntimeError
    def callFoo_Works(Goo0 g0) { foo((Goo0) g0) }
    def foo(Goo0 g0) { ... }
    def foo(Goo1 g1) { ... }
}

or

@TypeChecked
class Goo {
    static createGoo_Fails(Goo0 g0 = null) { new Goo(g0) } // Expectation for g0 == null case: Goo(Goo0) ctor gets called; actual: Fails during runtime with ambigous ctor GroovyRuntimeError
    static createGoo_Works(Goo0 g0 = null) { new Goo((Goo0) g0) }
    Goo(Goo0 g0) { ... }
    Goo(Goo1 g1) { ... }
}

Cheers,
mg


*Mostly to indicate the use of a default value; this avoids the problem of having to change a lot of signatures if the default value needs to change, for methods with a deep call hierarchy.



Reply via email to