-
Notifications
You must be signed in to change notification settings - Fork 193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue GROOVY-6899 is present in currently deployed 2.4 compiler #174
Comments
I was able to create a unit test for this issue. This would run from GroovySimpleTest if it were a Groovy class. (I have a separate pull request for splitting this test into some more manageable pieces.) The issue is still present using the latest 2.4.8 snapshot. So I'm not sure if the Greclipse compiled class file is differing from the Groovyc version. I have to do some more checking on that. void testExtendingGenerics_GroovyExtendsJava11() {
String[] sources = [
'Main.groovy', '''\
@groovy.transform.CompileStatic class Main {
public static void main(String[] args) {
def data = new MIData('V', 1, 'B')
print 'no error'
}
}'''.stripIndent(),
'MultiIndexed.java', '''\
public interface MultiIndexed<PK, SK> {
PK getPrimaryKey();
SK[] getSecondaryKeys();
}'''.stripIndent(),
'MIData.groovy', '''\
class MIData implements MultiIndexed<Integer, String> {
final String value
final Integer primaryKey
final String[] secondaryKeys
MIData(String val, Integer pk, String... sk) {
this.value = val
this.primaryKey = pk
this.secondaryKeys = sk
}
}'''.stripIndent()
]
runConformTest(sources, 'no error')
} |
I did a little more recon on this. Groovyc (with indy disabled) produces similar code, but it adds a field: I compiled the class above using groovyc and then pushed the .class file through a decompiler. Here is what it generated: @EqualsAndHashCode(includes={"value"})
@ToString(includes={"value"})
public class MiData implements MultiIndexed<Integer, String>, GroovyObject {
private final String value;
private final Integer primaryKey;
private final String[] secondaryKeys;
private static /* synthetic */ ClassInfo $staticClassInfo;
public static transient /* synthetic */ boolean __$stMC;
private transient /* synthetic */ MetaClass metaClass;
private static /* synthetic */ ClassInfo $staticClassInfo$;
private static /* synthetic */ SoftReference $callSiteArray;
public /* varargs */ MiData(String string, Integer n, String ... arrstring) {
void sk;
void pk;
MetaClass metaClass;
MiData miData;
void v;
CallSite[] arrcallSite = MiData.$getCallSiteArray();
this.metaClass = metaClass = this.$getStaticMetaClass();
void var6_6 = v;
this.value = ShortTypeHandling.castToString((Object)var6_6);
void var7_7 = pk;
this.primaryKey = (Integer)ScriptBytecodeAdapter.castToType((Object)var7_7, Integer.class);
void var8_8 = sk;
this.secondaryKeys = (String[])ScriptBytecodeAdapter.castToType((Object)var8_8, String[].class);
}
protected /* synthetic */ MetaClass $getStaticMetaClass() {
if (this.getClass() != MiData.class) {
return ScriptBytecodeAdapter.initMetaClass((Object)this);
}
ClassInfo classInfo = $staticClassInfo;
if (classInfo == null) {
$staticClassInfo = classInfo = ClassInfo.getClassInfo(this.getClass());
}
return classInfo.getMetaClass();
}
public int hashCode() {
CallSite[] arrcallSite = MiData.$getCallSiteArray();
Object _result = arrcallSite[0].callStatic(HashCodeHelper.class);
if (__$stMC || BytecodeInterface8.disabledStandardMetaClass()) {
if (!DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[1].call(arrcallSite[2].callCurrent((GroovyObject)this), (Object)this))) {
Object object;
_result = object = arrcallSite[3].callStatic(HashCodeHelper.class, _result, arrcallSite[4].callCurrent((GroovyObject)this));
}
} else if (!DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[5].call((Object)this.getValue(), (Object)this))) {
Object object;
_result = object = arrcallSite[6].callStatic(HashCodeHelper.class, _result, (Object)this.getValue());
}
return DefaultTypeTransformation.intUnbox((Object)_result);
}
public boolean canEqual(Object other) {
CallSite[] arrcallSite = MiData.$getCallSiteArray();
return other instanceof MiData;
}
public boolean equals(Object other) {
CallSite[] arrcallSite = MiData.$getCallSiteArray();
if (ScriptBytecodeAdapter.compareEqual((Object)other, (Object)null)) {
return false;
}
if (DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[7].callCurrent((GroovyObject)this, other))) {
return true;
}
if (!(other instanceof MiData)) {
return false;
}
MiData otherTyped = (MiData)other;
if (!DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[8].call((Object)otherTyped, (Object)this))) {
return false;
}
if (!ScriptBytecodeAdapter.compareEqual((Object)arrcallSite[9].callCurrent((GroovyObject)this), (Object)arrcallSite[10].call((Object)otherTyped))) {
return false;
}
return true;
}
public String toString() {
CallSite[] arrcallSite = MiData.$getCallSiteArray();
Object _result = arrcallSite[11].callConstructor(StringBuilder.class);
Boolean $toStringFirst = Boolean.TRUE;
arrcallSite[12].call(_result, (Object)"com.trgr.cobalt.search.dal.MiData(");
if (DefaultTypeTransformation.booleanUnbox((Object)$toStringFirst)) {
Boolean bl;
$toStringFirst = bl = Boolean.FALSE;
} else {
arrcallSite[13].call(_result, (Object)", ");
}
if (__$stMC || BytecodeInterface8.disabledStandardMetaClass()) {
if (DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[14].call(arrcallSite[15].callCurrent((GroovyObject)this), (Object)this))) {
arrcallSite[16].call(_result, (Object)"(this)");
} else {
arrcallSite[17].call(_result, arrcallSite[18].callStatic(InvokerHelper.class, arrcallSite[19].callCurrent((GroovyObject)this)));
}
} else if (DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[20].call((Object)this.getValue(), (Object)this))) {
arrcallSite[21].call(_result, (Object)"(this)");
} else {
arrcallSite[22].call(_result, arrcallSite[23].callStatic(InvokerHelper.class, (Object)this.getValue()));
}
arrcallSite[24].call(_result, (Object)")");
return ShortTypeHandling.castToString((Object)arrcallSite[25].call(_result));
}
public /* synthetic */ MetaClass getMetaClass() {
MetaClass metaClass = this.metaClass;
if (metaClass != null) {
return metaClass;
}
this.metaClass = this.$getStaticMetaClass();
return this.metaClass;
}
public /* synthetic */ void setMetaClass(MetaClass metaClass) {
this.metaClass = metaClass;
}
public /* synthetic */ Object invokeMethod(String string, Object object) {
return this.getMetaClass().invokeMethod((Object)this, string, object);
}
public /* synthetic */ Object getProperty(String string) {
return this.getMetaClass().getProperty((Object)this, string);
}
public /* synthetic */ void setProperty(String string, Object object) {
this.getMetaClass().setProperty((Object)this, string, object);
}
public final String getValue() {
return this.value;
}
public final Integer getPrimaryKey() {
return this.primaryKey;
}
public final String[] getSecondaryKeys() {
return this.secondaryKeys;
}
public /* synthetic */ String super$1$toString() {
return super.toString();
}
public /* synthetic */ boolean super$1$equals(Object object) {
return super.equals(object);
}
public /* synthetic */ int super$1$hashCode() {
return super.hashCode();
}
private static /* synthetic */ void $createCallSiteArray_1(String[] arrstring) {
arrstring[0] = "initHash";
arrstring[1] = "is";
arrstring[2] = "getValue";
arrstring[3] = "updateHash";
arrstring[4] = "getValue";
arrstring[5] = "is";
arrstring[6] = "updateHash";
arrstring[7] = "is";
arrstring[8] = "canEqual";
arrstring[9] = "getValue";
arrstring[10] = "getValue";
arrstring[11] = "<$constructor$>";
arrstring[12] = "append";
arrstring[13] = "append";
arrstring[14] = "is";
arrstring[15] = "getValue";
arrstring[16] = "append";
arrstring[17] = "append";
arrstring[18] = "toString";
arrstring[19] = "getValue";
arrstring[20] = "is";
arrstring[21] = "append";
arrstring[22] = "append";
arrstring[23] = "toString";
arrstring[24] = "append";
arrstring[25] = "toString";
}
private static /* synthetic */ CallSiteArray $createCallSiteArray() {
String[] arrstring = new String[26];
MiData.$createCallSiteArray_1(arrstring);
return new CallSiteArray(MiData.class, arrstring);
}
private static /* synthetic */ CallSite[] $getCallSiteArray() {
CallSiteArray callSiteArray;
if ($callSiteArray == null || (callSiteArray = (CallSiteArray)$callSiteArray.get()) == null) {
callSiteArray = MiData.$createCallSiteArray();
$callSiteArray = new SoftReference<CallSiteArray>(callSiteArray);
}
return callSiteArray.array;
}
} Then I compile using Greclipse and decompile and I get this: @EqualsAndHashCode(includes={"value"})
@ToString(includes={"value"})
public class MiDatav implements MultiIndexed<Integer, String>, GroovyObject {
private final String value;
private final Integer primaryKey;
private final String[] secondaryKeys;
private static /* synthetic */ ClassInfo $staticClassInfo;
public static transient /* synthetic */ boolean __$stMC;
private transient /* synthetic */ MetaClass metaClass;
private static /* synthetic */ SoftReference $callSiteArray;
public /* varargs */ MiData(String string, Integer n, String ... arrstring) {
void pk;
void v;
MetaClass metaClass;
MiData miData;
void sk;
CallSite[] arrcallSite = MiData.$getCallSiteArray();
this.metaClass = metaClass = this.$getStaticMetaClass();
void var6_6 = v;
this.value = ShortTypeHandling.castToString((Object)var6_6);
void var7_7 = pk;
this.primaryKey = (Integer)ScriptBytecodeAdapter.castToType((Object)var7_7, Integer.class);
void var8_8 = sk;
this.secondaryKeys = (String[])ScriptBytecodeAdapter.castToType((Object)var8_8, String[].class);
}
public int hashCode() {
CallSite[] arrcallSite = MiData.$getCallSiteArray();
Object _result = arrcallSite[0].callStatic(HashCodeHelper.class);
if (!DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[1].call(arrcallSite[2].callCurrent((GroovyObject)this), (Object)this))) {
Object object;
_result = object = arrcallSite[3].callStatic(HashCodeHelper.class, _result, arrcallSite[4].callCurrent((GroovyObject)this));
}
return DefaultTypeTransformation.intUnbox((Object)_result);
}
public boolean canEqual(Object other) {
CallSite[] arrcallSite = MiData.$getCallSiteArray();
return other instanceof MiData;
}
public boolean equals(Object other) {
CallSite[] arrcallSite = MiData.$getCallSiteArray();
if (ScriptBytecodeAdapter.compareEqual((Object)other, (Object)null)) {
return false;
}
if (DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[5].callCurrent((GroovyObject)this, other))) {
return true;
}
if (!(other instanceof MiData)) {
return false;
}
MiData otherTyped = (MiData)other;
if (!DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[6].call((Object)otherTyped, (Object)this))) {
return false;
}
if (!ScriptBytecodeAdapter.compareEqual((Object)arrcallSite[7].callCurrent((GroovyObject)this), (Object)arrcallSite[8].call((Object)otherTyped))) {
return false;
}
return true;
}
public String toString() {
CallSite[] arrcallSite = MiData.$getCallSiteArray();
Object _result = arrcallSite[9].callConstructor(StringBuilder.class);
Boolean $toStringFirst = Boolean.TRUE;
arrcallSite[10].call(_result, (Object)"com.trgr.cobalt.search.dal.MiData(");
if (DefaultTypeTransformation.booleanUnbox((Object)$toStringFirst)) {
Boolean bl;
$toStringFirst = bl = Boolean.FALSE;
} else {
arrcallSite[11].call(_result, (Object)", ");
}
if (DefaultTypeTransformation.booleanUnbox((Object)arrcallSite[12].call(arrcallSite[13].callCurrent((GroovyObject)this), (Object)this))) {
arrcallSite[14].call(_result, (Object)"(this)");
} else {
arrcallSite[15].call(_result, arrcallSite[16].callStatic(InvokerHelper.class, arrcallSite[17].callCurrent((GroovyObject)this)));
}
arrcallSite[18].call(_result, (Object)")");
return ShortTypeHandling.castToString((Object)arrcallSite[19].call(_result));
}
protected /* synthetic */ MetaClass $getStaticMetaClass() {
if (this.getClass() != MiData.class) {
return ScriptBytecodeAdapter.initMetaClass((Object)this);
}
ClassInfo classInfo = $staticClassInfo;
if (classInfo == null) {
$staticClassInfo = classInfo = ClassInfo.getClassInfo(this.getClass());
}
return classInfo.getMetaClass();
}
public /* synthetic */ MetaClass getMetaClass() {
MetaClass metaClass = this.metaClass;
if (metaClass != null) {
return metaClass;
}
this.metaClass = this.$getStaticMetaClass();
return this.metaClass;
}
public /* synthetic */ void setMetaClass(MetaClass metaClass) {
this.metaClass = metaClass;
}
public /* synthetic */ Object invokeMethod(String string, Object object) {
return this.getMetaClass().invokeMethod((Object)this, string, object);
}
public /* synthetic */ Object getProperty(String string) {
return this.getMetaClass().getProperty((Object)this, string);
}
public /* synthetic */ void setProperty(String string, Object object) {
this.getMetaClass().setProperty((Object)this, string, object);
}
public final String getValue() {
return this.value;
}
public final Integer getPrimaryKey() {
return this.primaryKey;
}
public final String[] getSecondaryKeys() {
return this.secondaryKeys;
}
public /* synthetic */ int super$1$hashCode() {
return super.hashCode();
}
public /* synthetic */ String super$1$toString() {
return super.toString();
}
public /* synthetic */ boolean super$1$equals(Object object) {
return super.equals(object);
}
private static /* synthetic */ void $createCallSiteArray_1(String[] arrstring) {
arrstring[0] = "initHash";
arrstring[1] = "is";
arrstring[2] = "getValue";
arrstring[3] = "updateHash";
arrstring[4] = "getValue";
arrstring[5] = "is";
arrstring[6] = "canEqual";
arrstring[7] = "getValue";
arrstring[8] = "getValue";
arrstring[9] = "<$constructor$>";
arrstring[10] = "append";
arrstring[11] = "append";
arrstring[12] = "is";
arrstring[13] = "getValue";
arrstring[14] = "append";
arrstring[15] = "append";
arrstring[16] = "toString";
arrstring[17] = "getValue";
arrstring[18] = "append";
arrstring[19] = "toString";
}
private static /* synthetic */ CallSiteArray $createCallSiteArray() {
String[] arrstring = new String[20];
MiData.$createCallSiteArray_1((String[])arrstring);
return new CallSiteArray(MiData.class, arrstring);
}
private static /* synthetic */ CallSite[] $getCallSiteArray() {
CallSiteArray callSiteArray;
if ($callSiteArray == null || (callSiteArray = (CallSiteArray)$callSiteArray.get()) == null) {
callSiteArray = MiData.$createCallSiteArray();
$callSiteArray = new SoftReference<CallSiteArray>(callSiteArray);
}
return callSiteArray.array;
}
} |
I'm going to see if I can disable the int optimization in the Ant build to see if this issue still exists in core Groovy under specific circumstances. |
It looks like the failure occurs dealing with the generic array return type of getSecondaryKeys. When I write the equivalent Java class, I get a slightly different return type. MiData.groovy class MIData implements MultiIndexed<Integer, String> {
final String value
final Integer primaryKey
final String[] secondaryKeys
MIData(String val, Integer pk, String... sk) {
this.value = val
this.primaryKey = pk
this.secondaryKeys = sk
}
} MiData2.java public class MIData2 implements MultiIndexed<Integer, String> {
private final String value;
private final Integer primaryKey;
private final String[] secondaryKeys;
public MIData2(String val, Integer pk, String... sk) {
this.value = val;
this.primaryKey = pk;
this.secondaryKeys = sk;
}
public String getValue() { return value; }
public Integer getPrimaryKey() { return primaryKey; }
public String[] getSecondaryKeys() { return secondaryKeys; }
} javap MiData.class
javap MiData2.class
The return type of the bridge method is Object[] in Java and SK[] in Groovy. The bean introspection is failing on the groovy return type. |
Could the Groovy compiler be updated to the latest stable release level? I am experiencing issue GROOVY-6899 within Eclipse. But a command-line compilation using Ant and Groovy 2.4.6 succeeds.
What I have is a simple POGO that implements an interface with type arguments. When running unit tests in Eclipse, I get this exception for every use of the MiData constructor.
The text was updated successfully, but these errors were encountered: