I run into a StackOverflow error of the AspectJ compiler today and I thought I should share it on StackOverflow :-) To reproduce the error I made a toy example
public abstract class Node<T,Q extends Node<T,Q>> implements WithParent<Q>{
private T content;
//getter and setter for content
}
public aspect WithParentAspect {
private T WithParent<T>.parent;
public T WithParent<T>.getParent() {
return this.parent;
}
public void WithParent<T>.setParent(T parent) {
this.parent=parent;
}
}
public interface WithParent<T> { }
public class StringContentNode extends Node<String, StringContentNode>{
public static void main (String [] args) {
StringContentNode root = new StringContentNode();
StringContentNode leaf = new StringContentNode();
root.setContent("root");
leaf.setContent("leaf");
leaf.setParent(root);
System.out.println(leaf);
System.out.println(leaf.getParent());
}
}
Trying to compile this code results in the following error:
java.lang.StackOverflowError
at org.aspectj.weaver.World$TypeMap.put(World.java:1198)
at org.aspectj.weaver.World.resolve(World.java:398)
at org.aspectj.weaver.World.resolve(World.java:277)
at org.aspectj.weaver.World.resolve(World.java:229)
at org.aspectj.weaver.UnresolvedType.resolve(UnresolvedType.java:615)
at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:621)
at org.aspectj.weaver.ReferenceType.isAssignableFrom(Ref ...
bleFrom(ReferenceType.java:459)
at org.aspectj.weaver.TypeVariable.isASubtypeOf(TypeVariable.java:201)
However, if I modify the Generics in the Node class to
public abstract class Node<T,Q extends Node<T,?>> implements WithParent<Q>{
...
(notice the ? instead of Q), the program works, and prints what you would expect:
Node (content=leaf, parent=Node (content=root, parent=null))
Node (content=root, parent=null)
even though Eclipse complains that
The method setParent(StringContentNode) is undefined for the type StringContentNode
if I leave the WithParent Interface empty as is now, or that
The type StringContentNode must implement the inherited abstract method WithParent.getParent()
If I define the getter and the setter in the interface.
Should I signal the bug? Is there a cleaner way to achieve the same functionality, without incurring in any weird compilation issue?
Thanks!