[ 
https://issues.apache.org/jira/browse/GROOVY-11982?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Paul King updated GROOVY-11982:
-------------------------------
    Description: 
A Groovy interface with default methods whose bodies use dynamic Groovy 
features (e.g. GString interpolation) fails at runtime with 
{{IncompatibleClassChangeError}} when compiled with {{indy=false}}.

h3. Symptom
{noformat}
java.lang.IncompatibleClassChangeError: Method
  'org.codehaus.groovy.runtime.callsite.CallSite[] IConfig.$getCallSiteArray()'
  must be InterfaceMethodref constant
    at IConfig.getDescription(IConfig.groovy)
{noformat}

h3. Reproducer
{code:groovy}
interface IConfig {
    String getName()
    default String getDescription() { "config[name=${getName()}]" }
}
class ConfigImpl implements IConfig { String getName() { 'impl' } }

new ConfigImpl().description  // throws under indy=false
{code}

Compile with {{-Dgroovy.target.indy=false}} and invoke any default method.

h3. Root cause
{{CallSiteWriter.makeSiteEntry()}} emits {{INVOKESTATIC 
<interface>.$getCallSiteArray}} as a {{CONSTANT_Methodref_info}} entry. JVMS 
§5.4.3.3 requires {{CONSTANT_InterfaceMethodref_info}} when the owner is an 
interface, so resolution throws {{IncompatibleClassChangeError}}.

* {{CallSiteWriter.java:118}} uses {{controller.getInternalClassName()}} with 
{{isInterface=false}} instead of redirecting to the 
{{InterfaceHelperClassNode}} (cf. {{prepareCallSite()}} at line 233 which uses 
{{controller.getClassName()}}).
* {{AsmClassGenerator.createInterfaceSyntheticStaticFields()}} only 
materialises the helper inner class when {{referencedClasses}} is non-empty, so 
an interface with call sites but no class literals has no helper to redirect to.

h3. Workaround
Convert the interface to a {{trait}} — trait helper bodies live in a regular 
{{$Trait$Helper}} class where {{Methodref}} encoding is valid. Or compile with 
{{indy=true}} ({{IndyCallSiteWriter.makeSiteEntry()}} is a no-op).

> Default methods in interface throw IncompatibleClassChangeError under 
> indy=false
> --------------------------------------------------------------------------------
>
>                 Key: GROOVY-11982
>                 URL: https://issues.apache.org/jira/browse/GROOVY-11982
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>
> A Groovy interface with default methods whose bodies use dynamic Groovy 
> features (e.g. GString interpolation) fails at runtime with 
> {{IncompatibleClassChangeError}} when compiled with {{indy=false}}.
> h3. Symptom
> {noformat}
> java.lang.IncompatibleClassChangeError: Method
>   'org.codehaus.groovy.runtime.callsite.CallSite[] 
> IConfig.$getCallSiteArray()'
>   must be InterfaceMethodref constant
>     at IConfig.getDescription(IConfig.groovy)
> {noformat}
> h3. Reproducer
> {code:groovy}
> interface IConfig {
>     String getName()
>     default String getDescription() { "config[name=${getName()}]" }
> }
> class ConfigImpl implements IConfig { String getName() { 'impl' } }
> new ConfigImpl().description  // throws under indy=false
> {code}
> Compile with {{-Dgroovy.target.indy=false}} and invoke any default method.
> h3. Root cause
> {{CallSiteWriter.makeSiteEntry()}} emits {{INVOKESTATIC 
> <interface>.$getCallSiteArray}} as a {{CONSTANT_Methodref_info}} entry. JVMS 
> §5.4.3.3 requires {{CONSTANT_InterfaceMethodref_info}} when the owner is an 
> interface, so resolution throws {{IncompatibleClassChangeError}}.
> * {{CallSiteWriter.java:118}} uses {{controller.getInternalClassName()}} with 
> {{isInterface=false}} instead of redirecting to the 
> {{InterfaceHelperClassNode}} (cf. {{prepareCallSite()}} at line 233 which 
> uses {{controller.getClassName()}}).
> * {{AsmClassGenerator.createInterfaceSyntheticStaticFields()}} only 
> materialises the helper inner class when {{referencedClasses}} is non-empty, 
> so an interface with call sites but no class literals has no helper to 
> redirect to.
> h3. Workaround
> Convert the interface to a {{trait}} — trait helper bodies live in a regular 
> {{$Trait$Helper}} class where {{Methodref}} encoding is valid. Or compile 
> with {{indy=true}} ({{IndyCallSiteWriter.makeSiteEntry()}} is a no-op).



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to