[
https://issues.apache.org/jira/browse/GROOVY-11341?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Peter Schmitz updated GROOVY-11341:
-----------------------------------
Description:
Given the following Java classes:
{code:java}
public interface InterfaceBase {
Object getValue();
}
public class MyImplBase {
public Long getValue() {
return 42L;
}
}
public class MyImpl extends MyImplBase implements InterfaceBase {
} {code}
And the following SimpleCaller.groovy:
{code:java}
@groovy.transform.CompileStatic
class SimpleCaller {
public static void main(String[] args) {
Long v = new MyImpl().getValue();
System.out.println(v); //42
}
} {code}
The compilation fails with:
{{SimpleCaller.groovy: 7: [Static type checking] - Cannot assign value of type
java.lang.Object to variable of type java.lang.Long}}
{{ @ line 7, column 16.}}
{{ Long v = new MyImpl().getValue();}}
{{ ^}}
Compiling the equivalent {{SimpleCaller.java}} with _javac_ completes
successfully.
This structure is a bit uncommon, because MyImplBase uses a covariant return
type and doesn't implement the interface directly, only its subclass does.
I believe the problem is connected to the synthetic bridge method inserted into
the bytecode of {_}MyImpl{_}, which is picked up and preferred by _groovyc_
over the non-synthetic method in {_}MyImplBase{_}.
In case this is related: The synthetic bridge method is selected when using
reflection as well, causing the inferred type by javac and reflection to
diverge:
{code:java}
Method getValueMethod = MyImpl.class.getMethod("getValue");
// public java.lang.Object MyImpl.getValue() {code}
Workarounds:
* Disable static compilation
* An explicit cast to Long in SimpleCaller.
* Explicitly repeat the covariant method signature in MyImpl
* If possible, add/Move the implements to MyImplBase - then the synthetic
method is in the same class as the real one, which _groovyc_ is able to detect.
Using generics in the Interface doesn't work either (probably due to type
erasure).
Seems to be a more generalized issue when compared to the similar GROOVY-5003
was:
Given the following Java classes:
{code:java}
public interface InterfaceBase {
Object getValue();
}
public class MyImplBase {
public Long getValue() {
return 42L;
}
}
public class MyImpl extends MyImplBase implements InterfaceBase {
} {code}
And the following SimpleCaller.groovy:
{code:java}
@groovy.transform.CompileStatic
class SimpleCaller {
public static void main(String[] args) {
Long v = new MyImpl().getValue();
System.out.println(v); //42
}
} {code}
The compilation fails with:
{{SimpleCaller.groovy: 7: [Static type checking] - Cannot assign value of type
java.lang.Object to variable of type java.lang.Long}}
{{ @ line 7, column 16.}}
{{ Long v = new MyImpl().getValue();}}
{{ ^}}
Compiling the equivalent {{SimpleCaller.java}} with _javac_ completes
successfully.
This structure is a bit uncommon, because MyImplBase uses a covariant return
type and doesn't implement the interface directly, only its subclass does.
I believe the problem is connected to the synthetic bridge method inserted into
the bytecode of {_}MyImpl{_}, which is picked up and preferred by _groovyc_
over the non-synthetic method in {_}MyImplBase{_}.
In case this is related: The synthetic bridge method is selected when using
reflection as well, causing the inferred type by javac and reflection to
diverge:
{code:java}
Method getValueMethod = MyImpl.class.getMethod("getValue");
// public java.lang.Object MyImpl.getValue() {code}
Workarounds:
* Disable static compilation
* An explicit cast to Long in SimpleCaller.
* Explicitly repeat the method signature by repeating the method signature
* If possible, add/Move the implements to MyImplBase - then the synthetic
method is in the same class as the real one, which _groovyc_ is able to detect.
Using generics in the Interface doesn't work either (probably due to type
erasure).
Seems to be a more generalized issue when compared to the similar GROOVY-5003
> @CompileStatic: Compilation fails due to a synthetic bridge method in the
> subclass
> ----------------------------------------------------------------------------------
>
> Key: GROOVY-11341
> URL: https://issues.apache.org/jira/browse/GROOVY-11341
> Project: Groovy
> Issue Type: Bug
> Components: Static compilation, Static Type Checker
> Affects Versions: 2.4.x, 2.5.x, 3.0.21, 5.0.0-alpha-7, 4.0.20
> Reporter: Peter Schmitz
> Priority: Minor
> Labels: CompileStatic, groovyc
>
> Given the following Java classes:
> {code:java}
> public interface InterfaceBase {
> Object getValue();
> }
>
> public class MyImplBase {
> public Long getValue() {
> return 42L;
> }
> }
>
> public class MyImpl extends MyImplBase implements InterfaceBase {
> } {code}
>
> And the following SimpleCaller.groovy:
> {code:java}
> @groovy.transform.CompileStatic
> class SimpleCaller {
> public static void main(String[] args) {
> Long v = new MyImpl().getValue();
> System.out.println(v); //42
> }
> } {code}
> The compilation fails with:
>
> {{SimpleCaller.groovy: 7: [Static type checking] - Cannot assign value of
> type java.lang.Object to variable of type java.lang.Long}}
> {{ @ line 7, column 16.}}
> {{ Long v = new MyImpl().getValue();}}
> {{ ^}}
>
> Compiling the equivalent {{SimpleCaller.java}} with _javac_ completes
> successfully.
>
> This structure is a bit uncommon, because MyImplBase uses a covariant return
> type and doesn't implement the interface directly, only its subclass does.
>
> I believe the problem is connected to the synthetic bridge method inserted
> into the bytecode of {_}MyImpl{_}, which is picked up and preferred by
> _groovyc_ over the non-synthetic method in {_}MyImplBase{_}.
>
>
> In case this is related: The synthetic bridge method is selected when using
> reflection as well, causing the inferred type by javac and reflection to
> diverge:
> {code:java}
> Method getValueMethod = MyImpl.class.getMethod("getValue");
> // public java.lang.Object MyImpl.getValue() {code}
>
>
> Workarounds:
>
> * Disable static compilation
> * An explicit cast to Long in SimpleCaller.
> * Explicitly repeat the covariant method signature in MyImpl
> * If possible, add/Move the implements to MyImplBase - then the synthetic
> method is in the same class as the real one, which _groovyc_ is able to
> detect.
> Using generics in the Interface doesn't work either (probably due to type
> erasure).
>
> Seems to be a more generalized issue when compared to the similar GROOVY-5003
--
This message was sent by Atlassian Jira
(v8.20.10#820010)