Bug 108378

Summary: [1.5][compiler] NPE on type hierarchy with complex generics
Product: [Eclipse Project] JDT Reporter: Eric Inman <eric-inman>
Component: CoreAssignee: JDT-Core-Inbox <jdt-core-inbox>
Status: RESOLVED DUPLICATE QA Contact:
Severity: major    
Priority: P3    
Version: 3.1   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Eric Inman CLA 2005-08-30 11:23:23 EDT
Given:

interface A<T extends A<T>> {}
interface B<T extends A<T>> {}
interface C extends B<D> {}
interface D extends A<D>, C {}

creating a type hierarchy (F4) for D produces a null pointer exception on a 
superInterfaces reference in ReferenceBinding.implementsInterface. The problem 
is due to ClassScope performing checkParameterizedTypeBounds() before the 
hierarchy is finished being connected. ClassScope.connectTypeHierarchy() 
defers calling checkParameterizedTypeBounds() until after connections are 
made, but this does not account for recursive calls to connectTypeHierarchy(). 
In this example, connectTypeHierarchy() is called for D, which recursively 
calls itself for C, where checkParameterizedTypeBounds() checks if D 
implements A<D> before D is finished being connected. Therefore, 
connectTypeHierarchy() should not call checkParameterizedTypeBounds() if it is 
being called recursively, but rather should save the scopes where 
checkParameterizedTypeBounds() is needed and perform it on all them in the 
outermost connectTypeHierarchy() call. For example:

public final class TypeBoundsChecker {
	private static final TypeBoundsChecker CHECKER =
            new TypeBoundsChecker();
	private final Stack<ClassScope> stack = new Stack<ClassScope>();
	private int nestingLevel = 0;

	private TypeBoundsChecker() {}
	
	private final void nest(final ClassScope scope) {
		stack.push(scope);
		nestingLevel++;}
	
	private final void unnest() {
		nestingLevel--;
		if (nestingLevel == 0) checkBounds();}
	
	private final void checkBounds() {
		while (!stack.isEmpty())
                    stack.pop().checkParameterizedTypeBounds();}
	
	public static final void nestScope(final ClassScope scope) {
		CHECKER.nest(scope);}
	
	public static final void unnestScope() {CHECKER.unnest();}
}

with connectTypeHierarchy() calling nestScope() and unnestScope() at the 
beginning and end of the hierarchy connection process seems to be one way to 
fix the problem.
Comment 1 Olivier Thomann CLA 2005-08-30 11:26:36 EDT
This might be a duplicate of bug 101456.
Difficult to say without a stack trace.
Could you please check if it works for 3.2M1?
Thanks.
Comment 2 Eric Inman CLA 2005-08-30 13:37:56 EDT
(In reply to comment #1)
> This might be a duplicate of bug 101456.
> Difficult to say without a stack trace.
> Could you please check if it works for 3.2M1?
> Thanks.

Yes, it works for 3.2M1. Thanks.

Also, the stack trace for 101456 was similar, so it does seem to be a 
duplicate.
Comment 3 Olivier Thomann CLA 2005-08-30 13:40:47 EDT

*** This bug has been marked as a duplicate of 101456 ***