Bug 163680 - [1.5] [compiler] JDT Internal Exception under import circularity
Summary: [1.5] [compiler] JDT Internal Exception under import circularity
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.2.2   Edit
Assignee: Kent Johnson CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-11-07 11:23 EST by Greg Gibeling CLA
Modified: 2007-01-16 05:03 EST (History)
1 user (show)

See Also:


Attachments
Philippe - proposed patch to HEAD for the case described in comment #8 (2.60 KB, patch)
2006-11-23 11:58 EST, Kent Johnson CLA
no flags Details | Diff
Patch for 3.2.x stream (2.62 KB, patch)
2006-11-23 12:29 EST, Kent Johnson CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Greg Gibeling CLA 2006-11-07 11:23:42 EST
The below exception, or something like it, sometimes crops up during incremental builds with JDT over code which has circularities in the file level dependancies (imports) i.e. code wherein file A references file B which references file C which references file A.  This appears is the code searching for hierarchy loops barfing on some kinds of potential loops.

Incidentally I should mention that the code is (of course) free of class hierarchy loops and will compiles just fine during a full build, or a automatic build trigered by a "clean project".  Unfortunately this is not something which can be easily duplicated, since it seems to depend on build order.

This error is reported for the first line of SOME file (which happens to be a comment).  The file the error is reported in is usually one recently built, but may or may not be part of the file loop as described in the first paragraph of this bug.

Internal compiler error
	java.lang.ClassCastException: org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding
	at org.eclipse.jdt.internal.compiler.lookup.ClassScope.detectHierarchyCycle(ClassScope.java:1072)
	at org.eclipse.jdt.internal.compiler.lookup.ClassScope.detectHierarchyCycle(ClassScope.java:1030)
	at org.eclipse.jdt.internal.compiler.lookup.ClassScope.detectHierarchyCycle(ClassScope.java:981)
	at org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference.internalResolveType(ParameterizedSingleTypeReference.java:146)
	at org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference.resolveType(ParameterizedSingleTypeReference.java:209)
	at org.eclipse.jdt.internal.compiler.ast.TypeReference.resolveSuperType(TypeReference.java:110)
	at org.eclipse.jdt.internal.compiler.lookup.ClassScope.findSupertype(ClassScope.java:1083)
	at org.eclipse.jdt.internal.compiler.lookup.ClassScope.connectSuperclass(ClassScope.java:803)
	at org.eclipse.jdt.internal.compiler.lookup.ClassScope.connectTypeHierarchy(ClassScope.java:928)
	at org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.connectTypeHierarchy(CompilationUnitScope.java:289)
	at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.completeTypeBindings(LookupEnvironment.java:198)
	at org.eclipse.jdt.internal.compiler.Compiler.beginToCompile(Compiler.java:383)
	at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:397)
	at org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.compile(AbstractImageBuilder.java:300)
	at org.eclipse.jdt.internal.core.builder.IncrementalImageBuilder.compile(IncrementalImageBuilder.java:292)
	at org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.compile(AbstractImageBuilder.java:237)
	at org.eclipse.jdt.internal.core.builder.IncrementalImageBuilder.build(IncrementalImageBuilder.java:120)
	at org.eclipse.jdt.internal.core.builder.JavaBuilder.buildDeltas(JavaBuilder.java:260)
	at org.eclipse.jdt.internal.core.builder.JavaBuilder.build(JavaBuilder.java:185)
	at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:603)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:167)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:201)
	at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:230)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:233)
	at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:252)
	at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:285)
	at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:145)
	at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:208)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:58)


There is a second symptom of what may or may not be the same problem: occasionally at least one of the files in the cycle remains somehow improperly built, leaving the hierarchy of some class inconsistent and resulting in errors along the lines of "class not found".  I mention this out of completeness, but it may be an entirely separate bug, and I will submit it as soon as I have time to isolate a code fragment which makes it easily repeatable.
Comment 1 Philipe Mulet CLA 2006-11-08 05:28:59 EST
The latter could be a side effect of the ClassCastException.
Can you provide steps to recreate ?
Comment 2 Greg Gibeling CLA 2006-11-08 09:33:24 EST
I can provide a tarball/zipfile of code to recreate the problem mentioned at the end of the first comment as that is easy and darn near deterministic.  But I can't easily recreate exactly that exception since it seems to be a nondeterministic side effect of build order.

If you'd like a tarball or zipfile to create the later problem, just let me know an e-mail address.  It's code I'd rather not post to bugzilla for now.
Comment 3 Maxime Daniel CLA 2006-11-08 09:46:32 EST
Please send it to me.
Comment 4 Maxime Daniel CLA 2006-11-09 04:57:45 EST
Got the file, thanks.
Comment 5 Maxime Daniel CLA 2006-11-14 06:10:33 EST
Using the files you sent, I do not get the exception, but I get the error you mention in the accompanying note, by following the given steps. Thanks again for sharing.
I'll try to forge a smaller test case, and I'll investigate the causes.

If the exception for which you initially opened the bug shows up again, please let us know steps to reproduce (as far as isolating those can be done).
Comment 6 Maxime Daniel CLA 2006-11-14 06:59:04 EST
The issue is around the resolution of ParameterizedTypeBinding-s when the generic type happens to be unresolved (yet). The method used to break the recursion marks the type has not having unresolved parameters... which happens to be interpreted down the path as not having parameters at all. Then the result is not generic, hence the message.
(This has been observed by stepping through code with 3.2 maintenance code. Need to write a test case and to assess its behavior on 3.2 and 3.3.)
Comment 7 Greg Gibeling CLA 2006-11-14 10:00:52 EST
The initial exception hasn't shown up again quite the same way, but it's been exhibiting the same characteristics as the error you desribed.  I'll try to get a smaller test case together when I have some time to work on it, but it might be a while.
Comment 8 Maxime Daniel CLA 2006-11-14 11:32:14 EST
The problem is a bit more involved than what I thought initially.
My current understanding is the following:
- BinaryTypeBinding#BinaryTypeBinding(PackageBinding, IBinaryType, LookupEnvironment) delegates to BinaryTypeBinding#cachePartsFrom the proper initialization of the type variables for the newly created binding; it puts it to null to signal that it is not properly initialized yet; (amongst other things, this avoids being considered as non generic);
- BinaryTypeBinding#cachePartsFrom starts by setting typeVariables to NO_TYPE_VARIABLES, to protect the case where something goes wrong before the resolution is complete; this is generally harmless...
- except in this case where the resolution of the type parameters themselves involve the current type itself, which is the case here; when the type is returned by the cache by the standard mechanism, it is then marked as non generic - because it has NO_TYPE_VARIABLES - and fails to satisfy the needs of the calling point.

The clean build does not involve those binary bindings and keeps safe.

Released (inactive) GenericTypeTest#1075 that illustrates the problem on a much smaller source:

public class X <T extends X<?>.J>{
	public class J implements I<T> {
	}
}
public interface I <T> {
}
public class Y extends X {
}

Compiled altogether, Y behaves correctly. Compiled alone against X.class and I.class, it fails with the following message: 1. ERROR in Y.java (at line 1)
	public class Y extends X {
	                       ^
The type X is not generic; it cannot be parameterized with arguments <?>

Note that this is probably only one of the problems that you have met.
Moving to Philippe for the BinaryTypeBinding issue.
Comment 9 Philipe Mulet CLA 2006-11-22 12:27:06 EST
If the fix is simple, can we backport it for 3.2.2 ?
Comment 10 Philipe Mulet CLA 2006-11-22 12:28:34 EST
+1 for 3.2.2
Comment 11 Kent Johnson CLA 2006-11-23 11:58:37 EST
Created attachment 54422 [details]
Philippe - proposed patch to HEAD for the case described in comment #8
Comment 12 Kent Johnson CLA 2006-11-23 12:29:12 EST
Created attachment 54423 [details]
Patch for 3.2.x stream
Comment 13 Kent Johnson CLA 2006-11-23 13:18:47 EST
Added GenericTypeTest 1090

Released for 3.3M4
Released for 3.2.2
Comment 14 Kent Johnson CLA 2006-11-23 13:25:24 EST
Enabled inactive test1075() and removed test1090()
Comment 15 David Audel CLA 2006-12-12 11:15:52 EST
Verified for 3.3M4 with I20061212-0010.
Comment 16 Frederic Fusier CLA 2007-01-16 05:03:57 EST
Verified for 3.2.2 using build M20060112-1200.