Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 428247

Summary: [1.8][compiler] Race condition causes injection of spurious raw types into the type system.
Product: [Eclipse Project] JDT Reporter: Srikanth Sankaran <srikanth_sankaran>
Component: CoreAssignee: Srikanth Sankaran <srikanth_sankaran>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: jarthana, stephan.herrmann
Version: 4.4   
Target Milestone: BETA J8   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Bug Depends on:    
Bug Blocks: 427787    

Description Srikanth Sankaran CLA 2014-02-15 04:53:49 EST
In this call stack:

SourceTypeBinding.kind() line: 797	
LookupEnvironment.convertUnresolvedBinaryToRawType(TypeBinding) line: 605	
ParameterizedTypeBinding.swapUnresolved(UnresolvedReferenceBinding, ReferenceBinding, LookupEnvironment) line: 1221	
UnresolvedReferenceBinding.setResolvedType(ReferenceBinding, LookupEnvironment) line: 133	
PackageBinding.addType(ReferenceBinding) line: 78	
ClassScope.buildType(SourceTypeBinding, PackageBinding, AccessRestriction) line: 411	
CompilationUnitScope.buildTypeBindings(AccessRestriction) line: 153	
LookupEnvironment.buildTypeBindings(CompilationUnitDeclaration, AccessRestriction) line: 190	
CompilationUnitResolver(Compiler).accept(ICompilationUnit, AccessRestriction) line: 331	
CompilationUnitResolver.accept(ICompilationUnit, AccessRestriction) line: 178	
CompilationUnitResolver.accept(ISourceType[], PackageBinding, AccessRestriction) line: 174	
LookupEnvironment.askForType(char[][]) line: 147	
UnresolvedReferenceBinding.resolve(LookupEnvironment, boolean) line: 103	
BinaryTypeBinding.resolveType(TypeBinding, LookupEnvironment, boolean) line: 174	
PackageBinding.getTypeOrPackage(char[]) line: 190	
ClassScope(Scope).getTypeOrPackage(char[], int, boolean) line: 3296	
ClassScope(Scope).getType(char[]) line: 3008	
SingleTypeReference.getTypeBinding(Scope) line: 54	
SingleTypeReference(TypeReference).internalResolveType(Scope) line: 468	
SingleTypeReference(TypeReference).resolveType(ClassScope) line: 559	
SingleTypeReference(TypeReference).resolveSuperType(ClassScope) line: 537	
ClassScope.findSupertype(TypeReference) line: 1264	
ClassScope.connectSuperInterfaces() line: 1030	
ClassScope.connectTypeHierarchy() line: 1085	
CompilationUnitScope.connectTypeHierarchy() line: 308	
LookupEnvironment.completeTypeBindings() line: 228	
LookupEnvironment.completeTypeBindings(CompilationUnitDeclaration) line: 260	
CompilationUnitResolver(Compiler).accept(ICompilationUnit, AccessRestriction) line: 335	
CompilationUnitResolver.accept(ICompilationUnit, AccessRestriction) line: 178	
CompilationUnitResolver.accept(ISourceType[], PackageBinding, AccessRestriction) line: 174	
LookupEnvironment.askForType(char[][]) line: 147	
UnresolvedReferenceBinding.resolve(LookupEnvironment, boolean) line: 103	
BinaryTypeBinding.resolveType(TypeBinding, LookupEnvironment, boolean) line: 174	
PackageBinding.getTypeOrPackage(char[]) line: 190	
MethodScope(Scope).getTypeOrPackage(char[], int, boolean) line: 3296	
MethodScope(Scope).getType(char[]) line: 3008	
SingleTypeReference.getTypeBinding(Scope) line: 54	
SingleTypeReference(TypeReference).internalResolveType(Scope) line: 468	
SingleTypeReference(TypeReference).resolveType(BlockScope, boolean) line: 555	
MethodScope(Scope).connectTypeVariables(TypeParameter[], boolean) line: 935	
SourceTypeBinding.resolveTypesFor(MethodBinding) line: 1793	
SourceTypeBinding.methods() line: 1467	
SourceTypeBinding.faultInTypesForFieldsAndMethods() line: 855	
CompilationUnitScope.faultInTypes() line: 424	
CompilationUnitResolver.resolve(CompilationUnitDeclaration, ICompilationUnit, NodeSearcher, boolean, boolean, boolean) line: 1201	
CompilationUnitResolver.resolve(ICompilationUnit, IJavaProject, List, NodeSearcher, Map, WorkingCopyOwner, int, IProgressMonitor) line: 693	
ASTParser.internalCreateAST(IProgressMonitor) line: 1187	
ASTParser.createAST(IProgressMonitor) line: 813	
ASTProvider$1.run() line: 548	
SafeRunner.run(ISafeRunnable) line: 42	
ASTProvider.createAST(ITypeRoot, IProgressMonitor) line: 541	
ASTProvider.getAST(ITypeRoot, SharedASTProvider$WAIT_FLAG, IProgressMonitor) line: 484	
SharedASTProvider.getAST(ITypeRoot, SharedASTProvider$WAIT_FLAG, IProgressMonitor) line: 132	
SelectionListenerWithASTManager$PartListenerGroup.calculateASTandInform(ITypeRoot, ITextSelection, IProgressMonitor) line: 170	
SelectionListenerWithASTManager$PartListenerGroup$3.run(IProgressMonitor) line: 155	
Worker.run() line: 53	

we could conclude that a non-generic type is a generic type and create
raw versions of it.

This is because, ClassScope.buildType() calls PackageBinding.addType() to
add the new source type that is being built *before* its type variables are
built. These type variables are consulted by frame 0 i.e 
SourceTypeBinding.kind()

which reads:

if (this.typeVariables != Binding.NO_TYPE_VARIABLES) 
    return Binding.GENERIC_TYPE;

since this.typeVariables is still null and not initialized with either
the special value Binding.NO_TYPE_VARIABLES or to the built type variables
in the case of generic type, we would confuse a non-generic type to be
a generic type and create raw versions of it.

This results various type incompatibilities down the road between

  List<Type#Raw> and List<Type>

For example, while building JRE8 from the sources, we obsreve errors of
the form:

Type mismatch: cannot convert from List<GarbageCollectorMXBean> to List<GarbageCollectorMXBean>	ManagementFactory.java	/JDK Source/src/java/lang/management	line 415	Java Problem
Type mismatch: cannot convert from List<MemoryManagerMXBean> to List<MemoryManagerMXBean>	ManagementFactory.java	/JDK Source/src/java/lang/management	line 399	Java Problem
Type mismatch: cannot convert from List<MemoryPoolMXBean> to List<MemoryPoolMXBean>	ManagementFactory.java	/JDK Source/src/java/lang/management	line 386	Java Problem
Comment 1 Srikanth Sankaran CLA 2014-02-15 04:55:04 EST
I have a fairly straightforward fix in the works that simply pulls up
a couple of statements before the type is added to the package. Testing
underway.
Comment 2 Srikanth Sankaran CLA 2014-02-15 07:04:04 EST
Fix released here: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=eb0413d7c3f6c8377e410e116826fcfccbec3365. I had some trouble
getting this reproduced in a junit - resorted to verifying the fix by rebuilding
the JRE from sources instead.
Comment 3 Srikanth Sankaran CLA 2014-02-21 05:12:20 EST
Verified as working for Eclipse + Java 8 RC1 using Kepler SR1 +   
Eclipse Java Development Tools Patch for Java 8 Support (BETA)	1.0.0.v20140220-2054

(I am able to build JRE8 successfully with the above)
Comment 4 Srikanth Sankaran CLA 2014-02-21 05:20:59 EST
See that the equivalent race condition in the case of BinaryTypeBinding
is already taken care of by the constructor eagerly initializing this.typeVariables to a suitable value.
Comment 5 Srikanth Sankaran CLA 2014-02-22 07:23:58 EST
(In reply to Srikanth Sankaran from comment #4)
> See that the equivalent race condition in the case of BinaryTypeBinding
> is already taken care of by the constructor eagerly initializing
> this.typeVariables to a suitable value.

Seeing how this is handled for BinaryTypeBinding, I released amended fix
that follows the same approach - Any potential for side effects is eliminated.
(I did verify there are no material side effects with the original fix
as things stand today - but that executes a fair amount of code as opposed
to just an inlined pair of statements as in the present fix.

I verified that JRE8 builds fine.
Comment 6 Srikanth Sankaran CLA 2014-02-22 07:25:51 EST
(In reply to Srikanth Sankaran from comment #5)

> Seeing how this is handled for BinaryTypeBinding, I released amended fix
> that follows the same approach - Any potential for side effects is
> eliminated.

Amended fix is here:
http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=ca551e9f50d120a7df024c143f37ec7681949c67