Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
4.0.6
-
Groovy 4.0.6, openjdk 17.0.4.1, Guava 31.1-jre
Description
When I compile groovy that uses Java classes that has circular meta annotations in their class hierarcy. The compile crash with:
>>> a serious error occurred: null
>>> stacktrace:
java.lang.StackOverflowError
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:632)
at org.codehaus.groovy.ast.ClassNode.<init>(ClassNode.java:349)
at org.codehaus.groovy.ast.ClassNode.<init>(ClassNode.java:327)
at org.codehaus.groovy.ast.ClassHelper.makeWithoutCaching(ClassHelper.java:281)
at org.apache.groovy.contracts.util.AnnotationUtils.hasMetaAnnotations(AnnotationUtils.java:123)
at org.apache.groovy.contracts.util.AnnotationUtils.hasMetaAnnotations(AnnotationUtils.java:125)
at org.apache.groovy.contracts.util.AnnotationUtils.hasMetaAnnotations(AnnotationUtils.java:125)
at org.apache.groovy.contracts.util.AnnotationUtils.hasMetaAnnotations(AnnotationUtils.java:125)
at org.apache.groovy.contracts.util.AnnotationUtils.hasMetaAnnotations(AnnotationUtils.java:125)
at org.apache.groovy.contracts.util.AnnotationUtils.hasMetaAnnotations(AnnotationUtils.java:125)
at org.apache.groovy.contracts.util.AnnotationUtils.hasMetaAnnotations(AnnotationUtils.java:125)
at org.apache.groovy.contracts.util.AnnotationUtils.hasMetaAnnotations(AnnotationUtils.java:125)
...
this can be produced with this small example (2 java files and 1 groovy file):
MyMetaAnnotation.java:
import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(RUNTIME) @Target({TYPE, METHOD}) @MyMetaAnnotation public @interface MyMetaAnnotation {}
MyAnnotation.java:
import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @MyMetaAnnotation @Retention(RUNTIME) @Target({FIELD, METHOD, PARAMETER}) public @interface MyAnnotation {}
and UseMyAnnotation.groovy
import MyAnnotation public interface A<T> { @MyAnnotation T a() } def b = new A() { def a() { return 0 } }
A real world example is using some Guava classes which several has circularities in their meta annotations (e.g. com.google.common.base.Supplier) . This example will yield the same stackoverflow:
import com.google.common.base.Supplier def zeroSupplier = new Supplier() { def get() { return 0 } }
Note that circularity in meta annotations is permitted according to the java spec:
An annotation of interface A may appear as a meta-annotation on the declaration of the interface A itself. More generally, circularities in the transitive closure of the "annotates" relation are permitted.
(from https://docs.oracle.com/javase/specs/jls/se17/html/jls-9.html#jls-9.7.1)
Also note. These compile succesfully using Groovy 3.0.11