Bug 316889 - Internal compiler error: java.lang.NullPointerException with a specific use of recursive generics
Summary: Internal compiler error: java.lang.NullPointerException with a specific use o...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.6   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P3 major (vote)
Target Milestone: 3.6.1   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 321918 (view as bug list)
Depends on:
Blocks:
 
Reported: 2010-06-15 08:33 EDT by Missing name CLA
Modified: 2010-08-05 17:34 EDT (History)
5 users (show)

See Also:
Olivier_Thomann: review+


Attachments
Test project to reproduce java.lang.NullPointerException compiler error (1.37 KB, application/zip)
2010-06-15 08:35 EDT, Missing name CLA
no flags Details
Proposed patch (1.54 KB, patch)
2010-06-17 03:12 EDT, Srikanth Sankaran CLA
no flags Details | Diff
Proposed patch (3.71 KB, patch)
2010-06-17 03:50 EDT, Srikanth Sankaran CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Missing name CLA 2010-06-15 08:33:38 EDT
Build Identifier: 20100610-0636

This is a challenging bug to describe in words, but easy to provide a small project to reproduce it. When you have a class that implements a recursive interface and a second referenced interface, and you have a member variable in that class that of type another class that is also templated on the referenced interface, you get an internal compiler error: java.lang.NullPointerException.

I also found that this happens on Eclipse 3.5.2 (20100218-1602), but the error is more descriptive: Internal compiler error: java.lang.NullPointerException at org.eclipse.jdt.internal.compiler.lookup.TypeBinding.findSuperTypeOriginatingFrom(TypeBinding.java:301). When searching on that message I found this bug:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=288621

which was supposed to be fixed, but that was happening under different conditions so I can't be sure it's the same.

Note that I have only tried this on OS X, but it seems like the type of bug that may appear in all operating systems.

Reproducible: Always

Steps to Reproduce:
1. Create a new Eclipse Java project with the following files (I used J2SE-1.5, but JavaSE-1.6 also exhibits the problem):

AnotherClass.java:
-----
public class AnotherClass<I extends IRecursiveInterface<? super I>>
{

}
-----

ImplementingClass.java
-----
public class ImplementingClass implements IRecursiveInterface<IReferencedInterface>, IReferencedInterface
{

private AnotherClass<IReferencedInterface> m_var;

@Override public void setAnother(final AnotherClass<? extends IReferencedInterface> a)
    {
    m_var = a;
    }

}
-----

IRecursiveInterface.java:
-----
public interface IRecursiveInterface<I extends IRecursiveInterface<? super I>>
{

void setAnother(final AnotherClass<? extends I> a);

}
-----

IReferencedInterface.java
-----
public interface IReferencedInterface extends IRecursiveInterface<IReferencedInterface>
{

}
-----

2. Ensure that the Java Builder is the only builder. This should be the default.

3. When the compiler goes to build the project, you'll see the java.lang.NullPointerException referenced in the Details section.
Comment 1 Missing name CLA 2010-06-15 08:35:04 EDT
Created attachment 171919 [details]
Test project to reproduce java.lang.NullPointerException compiler error
Comment 2 Missing name CLA 2010-06-15 08:40:31 EDT
Changed version to 3.6. Apologies if I've dropped this in the wrong place.
Comment 3 Srikanth Sankaran CLA 2010-06-15 09:06:06 EDT
I'll follow up.
Comment 4 Srikanth Sankaran CLA 2010-06-17 03:12:47 EDT
Created attachment 172092 [details]
Proposed patch
Comment 5 Srikanth Sankaran CLA 2010-06-17 03:50:56 EDT
Created attachment 172093 [details]
Proposed patch

Earlier patch got truncated for some reason. Reposting.
Comment 6 Srikanth Sankaran CLA 2010-06-17 06:14:47 EDT
Olivier, The proposed patch is simple and the change being made to org.eclipse.jdt.internal.compiler.lookup.TypeBinding.findSuperTypeOriginatingFrom(TypeBinding) is along the lines of existing protective code in org.eclipse.jdt.internal.compiler.lookup.TypeBinding.findSuperTypeOriginatingFrom(int, boolean). It fixes a crash which halts build with a compiler error.

I think this is safe for 3.6.1, do you agree ?
Comment 7 Srikanth Sankaran CLA 2010-06-18 00:15:38 EDT
Please take a look at the patch from a 3.6.1 candidate p.o.v - Thanks.
Comment 8 Srikanth Sankaran CLA 2010-06-24 03:30:36 EDT
Released in HEAD for 3.7 M1.
Will release in 3.6 maintenance stream if needed.
Comment 9 Missing name CLA 2010-06-24 03:37:52 EDT
(In reply to comment #8)
> Released in HEAD for 3.7 M1.
> Will release in 3.6 maintenance stream if needed.

Personally, I worked around it for now, so I don't absolutely need it in 3.6. Things may change if someone else runs into it. Thanks for the fix.
Comment 10 Olivier Thomann CLA 2010-06-24 11:38:31 EDT
(In reply to comment #6)
> I think this is safe for 3.6.1, do you agree ?
yes, +1 for 3.6.1.
Comment 11 Srikanth Sankaran CLA 2010-06-24 23:43:20 EDT
Olivier, please update the review flag.

Released in 3.6 maintenance stream for 3.6.1.
Comment 12 Stephan Herrmann CLA 2010-07-06 09:49:58 EDT
One thing I don't understand: the majority of all callers of
superInterfaces() now check for null before dereferencing,
but I still count at least 10 callers that would actually break (NPE)
if null is returned.

Do you have a rule saying when it is safe to expect non-null,
or should the remaining 10 or so callers be protected, too??

One interesting comment I found in ClassScope:
// in code assist cases when source types are added late, may not be finished connecting hierarchy
Comment 13 Srikanth Sankaran CLA 2010-07-07 02:57:47 EDT
(In reply to comment #12)

> Do you have a rule saying when it is safe to expect non-null,
> or should the remaining 10 or so callers be protected, too??
> 
> One interesting comment I found in ClassScope:
> // in code assist cases when source types are added late, may not be finished
> connecting hierarchy

By looking at the write references to the field, one can conclude
when it is safe not to check for null. As the comment you referenced
indicates (and as can be double checked by studying the write accesses),
once type hierarchy is connected, org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding.superInterfaces
is guaranteed to be not null.

However, such avoiding of null checks requires more understanding of the
code than I have right now, presumably the instances where null check is
missing some one reasonably felt sure it is ok - not always correctly of
course.
Comment 14 Ayushman Jain CLA 2010-08-03 09:37:00 EDT
Verified for 3.7M1 using build I20100802-1800.
Comment 15 Olivier Thomann CLA 2010-08-05 16:07:47 EDT
*** Bug 321918 has been marked as a duplicate of this bug. ***
Comment 16 Richard A. Sitze CLA 2010-08-05 17:25:51 EDT
(In reply to comment #11)
> Released in 3.6 maintenance stream for 3.6.1.

Much appreciated.  The recursive generics matches my situation.  I'm confident the fix will help resolve my issue.  The impact of this should not be minimized:

* any class referencing such an interface from within the same project seems to be fine.

* any class in another project that references such an interface is broken...
  - F3 fails for pretty much everything in the class
  - Ctrl+Space for content-assist causes an error (same NullPointerException).
  - Any "automatic" content-assist while entering java code brings up the error.
  - Content-assist errors are on *any* java reference, not necessarily related to the recursive generics-interface.

It becomes painful (errors popping up) just to enter/edit code, never mind "navigate" out of such a file.  The buggy code seems to be on a nexus of GUI interaction.  I want to say *everything* is broken... but it only seems that way.

Unfortunately, I'm not in a position to work around this... so I'm working "through" it (disabling content-assist helps eliminate the pop-up errors, but does nothing for the quick navigation I'm use to).  3.5 (as noted above somewhere) is also broken.

I feel I'm in the dark ages.  How/when/where can I pickup an snapshot/early-update of the 3.6.1 maintenance stream, or at least the JDT Core stream, that'll give me back my Eclipse?!
Comment 17 Olivier Thomann CLA 2010-08-05 17:34:25 EDT
(In reply to comment #16)
> I feel I'm in the dark ages.  How/when/where can I pickup an
> snapshot/early-update of the 3.6.1 maintenance stream, or at least the JDT Core
> stream, that'll give me back my Eclipse?!
This is fixed in M-builds since this build: Eclipse SDK 3.6.1 - July 7, 2010.
So if you grab the latest M-build, it should work without a problem.
Hope this help.