You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Eric Milles (Jira)" <ji...@apache.org> on 2021/12/02 15:06:00 UTC
[jira] [Commented] (GROOVY-8693) Calling indirect default interface methods fails both dynamic/static compiled
[ https://issues.apache.org/jira/browse/GROOVY-8693?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17452458#comment-17452458 ]
Eric Milles commented on GROOVY-8693:
-------------------------------------
The SC case has been fixed. For the dynamic case, I think I understand all the moving parts and was able to make it work experimentally. There are a few other cases that would require fixes to make it all hold together.
{code:groovy}
interface I {
default def m() { }
}
class C implements I {
}
class D extends C {
def m() {
super.m()
}
}
{code}
1. {{InvocationWriter#makeCall}} converts "super.m()" into "ScriptBytecodeAdapter.invokeMethodOnSuper0(C.class, this, "m")". The choice of "C" was made for GROOVY-4035 and I think it should be "D".
2. As part of (1), a note is made to trigger {{MopWriter}} to create the method "super$2$m" that writes the {{INVOKESPECIAL}} call "super.m()" for the dynamic runtime.
3. When {{invokeMethodOnSuper0}} is executed, {{MetaClassImpl}}/{{MetaMethodIndex}} build up an index of the mehtods of C. The entry for "m" has the declared method of C in the "methods" slot. And the "methodsForSuper" has the interface default method. methodsForSuper is supposed to have "super$2$m" substituted by {{MetaClassImpl#replaceWithMOPCalls}}, but the distance calculation of the compiler and runtime differs.
So, if {{InvocationWriter#makeCall}} drops ".getSuperClass()", {{MetaMethodIndex#isOverridden}} is adjusted for interface methods, and {{MetaClassImpl#replaceWithMOPCalls}} is adjusted for distance of interface methods then the test case will succeed.
I think these changes are in keeping with the design of the "super$dist$name" MOP methods, which are meant for the runtime when carrying out "super.name()" invocation. Using "D" as the sender (today's behavior) falls down when D is not a Groovy class.
> Calling indirect default interface methods fails both dynamic/static compiled
> -----------------------------------------------------------------------------
>
> Key: GROOVY-8693
> URL: https://issues.apache.org/jira/browse/GROOVY-8693
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 2.5.0
> Reporter: Christoph Frick
> Assignee: Eric Milles
> Priority: Major
> Labels: default-methods
>
> Given _<interface> Intr <|- Impl <| SubImpl_ where _Intr_ is an Java8 interface with a default implementation, running _SubImpl_ fails both with _CompileDynamic:_
> {noformat}
> Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: sut.SubImpl.doSomething() is applicable for argument types: () values: []
> Possible solutions: doSomething(), toString(), toString()
> at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:72)
> at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:148)
> at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuper0(ScriptBytecodeAdapter.java:166)
> at sut.SubImpl.doSomething(SubImpl.groovy:6)
> at sut.Intr$doSomething.call(Unknown Source)
> at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
> at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
> at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
> at sut.Main.main(Main.groovy:8)
> {noformat}
> and -_Static_.
> {noformat}
> Exception in thread "main" java.lang.VerifyError: Bad invokespecial instruction: interface method reference is in an indirect superinterface.
> Exception Details:
> Location:
> sut/SubImpl.doSomething()V @1: invokespecial
> Reason:
> Error exists in the bytecode
> Bytecode:
> 0x0000000: 2ab7 0014 0157 2a12 16b8 001c 0157 b1
> at java.lang.Class.getDeclaredConstructors0(Native Method)
> at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
> at java.lang.Class.getDeclaredConstructors(Class.java:2020)
> at org.codehaus.groovy.reflection.CachedClass$2$1.run(CachedClass.java:88)
> at java.security.AccessController.doPrivileged(Native Method)
> at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:86)
> at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:81)
> at org.codehaus.groovy.util.LazyReference.getLocked(LazyReference.java:50)
> at org.codehaus.groovy.util.LazyReference.get(LazyReference.java:37)
> at org.codehaus.groovy.reflection.CachedClass.getConstructors(CachedClass.java:311)
> at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:218)
> at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:228)
> at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:171)
> at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:161)
> at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:144)
> at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:288)
> at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:331)
> at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:270)
> at org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:976)
> at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallConstructorSite(CallSiteArray.java:86)
> at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
> at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:238)
> at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:242)
> at sut.Main.main(Main.groovy:8)
> {noformat}
> See a full example here: https://github.com/christoph-frick/groovy-inheritance-vs-default-interface-method
--
This message was sent by Atlassian Jira
(v8.20.1#820001)