Sean Fitts created GROOVY-12247:
-----------------------------------
Summary: NPE "Cannot invoke MetaMethod.isAbstract() because method
is null" on super call to inherited generic method with default parameter
Key: GROOVY-12247
URL: https://issues.apache.org/jira/browse/GROOVY-12247
Project: Groovy
Issue Type: Bug
Components: groovy-runtime
Affects Versions: 6.0.0-beta-1, 5.0.8
Reporter: Sean Fitts
A dynamic super. call throws:
{quote}java.lang.NullPointerException: Cannot invoke
"groovy.lang.MetaMethod.isAbstract()" because "method" is null
at groovy.lang.MetaClassImpl.getSuperMethodWithCaching(MetaClassImpl.java:1423)
at groovy.lang.MetaClassImpl.getMethodWithCaching(MetaClassImpl.java:1368)
at groovy.lang.MetaClassImpl.getMetaMethod(MetaClassImpl.java:1263)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1117)
at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:143)
{quote}
when all of the following hold:
# The super method is declared in a generic class, uses the type variable as a
parameter type, and has a default parameter value (which generates a short-form
overload). Declaring two explicit overloads instead of using a default
parameter fails the same way.
# An intermediate class binds the type parameter, so the overriding class sits
two levels below the generic declaration. (If the overriding class extends the
generic class directly, it works.)
# A subclass overrides the short-form overload with the concrete type argument
(producing a bridge method) and invokes it via super. with the optional
argument omitted.
Reproducer (tried attaching file, but that failed):
abstract class Base<T extends Number> {
protected String process(T value, String extra = null) {
return "base(${value}, ${extra})"
}
}
abstract class Mid extends Base<Integer> {}
class Sub extends Mid {
@Override
protected String process(Integer value) {
return 'sub->' + super.process(value)
}
}
// Expected (Groovy 3/4): sub->base(42, null)
// Groovy 5.0.8 / 6.0.0-beta-1: NPE "Cannot invoke
groovy.lang.MetaMethod.isAbstract() because method is null"
println new Sub().process(42)
Expected output sub->base(42, null), as produced by Groovy 3 and 4).
Removing any one ingredient avoids the failure: dropping the default parameter
(so the method is not overloaded), removing the intermediate class Mid, or
calling the full-arity form explicitly (super.process(value, null)), which is a
usable workaround.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)