Bug 332423 - [1.5][compiler] ClassCastException when compiling against scala-libary.jar
Summary: [1.5][compiler] ClassCastException when compiling against scala-libary.jar
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 3.7 M5   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-12-13 05:48 EST by Martin Fischbach CLA
Modified: 2011-01-25 13:10 EST (History)
8 users (show)

See Also:
srikanth_sankaran: review+


Attachments
Proposed fix (1.33 KB, patch)
2010-12-17 11:03 EST, Olivier Thomann CLA
no flags Details | Diff
Proposed fix (1.74 KB, patch)
2011-01-06 11:17 EST, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Fischbach CLA 2010-12-13 05:48:36 EST
Build Identifier: M20100909-0800

When using the scala-libary.jar in a java project, the org.eclipse.jdt.ui.AllCompletionProposalComputer throws an exception in certain cases. One of this cases is described in the "Steps to Reproduce".

The autocompletion works fine in other IDEs.

Nevertheless I will report this at the scala tracker too, because I don't know if this is a problem with the scala-libary.jar or eclipse.

Reproducible: Always

Steps to Reproduce:
1. Create a new java project
2. Add the scala-libary.jar to the project (from "http://www.scala-lang.org/downloads" - version 2.8.1.final)
3. Create the following test class:

package simple;
import scala.collection.immutable.Nil;
public class Test  {
	public static void main(String[] args) {
		scala.collection.immutable.List<int> myList = new Nil();
	}
}

4. Try to activate the autocompletion on the variable "myList"
Comment 1 Markus Keller CLA 2010-12-13 06:07:37 EST
> 3. Create the following test class: [..]

This is not a valid Java source file. We will not pursue the Scala-related problems in JDT, but I'm keeping this bug for the ClassCastException that shows up when you follow the given steps 1-3.

Although the file has syntax errors and the scala-library.jar may contain invalid class files, the compiler should not write to the log and the compilation error "Internal compiler error: java.lang.ClassCastException: org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.initializeTypeVariable(BinaryTypeBinding.java:956)" could also be improved.


java.lang.ClassCastException: org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
	at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.initializeTypeVariable(BinaryTypeBinding.java:956)
	at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.createTypeVariables(BinaryTypeBinding.java:659)
	at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.createMethod(BinaryTypeBinding.java:497)
	at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.createMethods(BinaryTypeBinding.java:602)
	at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.cachePartsFrom(BinaryTypeBinding.java:337)
	at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.createBinaryTypeFrom(LookupEnvironment.java:678)
	at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.createBinaryTypeFrom(LookupEnvironment.java:657)
	at org.eclipse.jdt.internal.compiler.Compiler.accept(Compiler.java:295)
	at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:138)
	at org.eclipse.jdt.internal.compiler.lookup.PackageBinding.getTypeOrPackage(PackageBinding.java:183)
	at org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.findImport(CompilationUnitScope.java:486)
	at org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.findSingleImport(CompilationUnitScope.java:540)
	at org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.faultInImports(CompilationUnitScope.java:368)
	at org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope.faultInTypes(CompilationUnitScope.java:465)
	at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:752)
	at org.eclipse.jdt.internal.compiler.ProcessTaskManager.run(ProcessTaskManager.java:137)
	at java.lang.Thread.run(Thread.java:619)
Comment 2 Olivier Thomann CLA 2010-12-17 10:37:08 EST
The signature of the method:
  // Method descriptor #295 (Lscala/PartialFunction;)Lscala/PartialFunction;
  // Signature: <A1:IB1:Ljava/lang/Object;>(Lscala/PartialFunction<TA1;TB1;>;)Lscala/PartialFunction<TA1;TB1;>;
  // Stack: 2, Locals: 1
  public static final scala.PartialFunction orElse(scala.PartialFunction arg0);
    0  getstatic scala.collection.immutable.Nil$.MODULE$ : scala.collection.immutable.Nil. [11]
    3  aload_0 [arg0]
    4  invokevirtual scala.collection.immutable.Nil$.orElse(scala.PartialFunction) : scala.PartialFunction [297]
    7  areturn


is boggus. I investigate what is the cleanest way to reject that .class file.
Comment 3 Olivier Thomann CLA 2010-12-17 10:55:58 EST
Would this be a better error handling ?
The class file Nil contains a signature '<A1:IB1:Ljava/lang/Object;>(Lscala/PartialFunction<TA1;TB1;>;)Lscala/PartialFunction<TA1;TB1;>;' ill-formed at position 6
Comment 4 Olivier Thomann CLA 2010-12-17 10:56:48 EST
javac compiles the code, but doesn't run it. So I prefer to get an answer that tells me that something is wrong with the .class file.
Comment 5 Olivier Thomann CLA 2010-12-17 11:01:49 EST
The corrupted signature was properly detected, but could not be reported since it was failing before that.
I would report a bug against scala to find out how this signature was computed.
Comment 6 Olivier Thomann CLA 2010-12-17 11:03:53 EST
Created attachment 185433 [details]
Proposed fix
Comment 7 Olivier Thomann CLA 2010-12-17 11:25:15 EST
Patch is wrong. Will rework it.
Comment 8 Olivier Thomann CLA 2011-01-06 11:17:26 EST
Created attachment 186185 [details]
Proposed fix

I think the previous patch was right.
Srikanth, please verify.

This is a bug in the scala compiler in the way the class file is built. This patch simply try to improve the way the Eclipse compiler is handling the boggus class file.
Comment 9 Olivier Thomann CLA 2011-01-06 15:00:14 EST
Released for 3.7M5.
Comment 10 Srikanth Sankaran CLA 2011-01-10 01:42:58 EST
> Srikanth, please verify.
> 
> This is a bug in the scala compiler in the way the class file is built. This
> patch simply try to improve the way the Eclipse compiler is handling the boggus
> class file.

Agree with the patch.
Comment 11 Donnchadh Ó Donnabháin CLA 2011-01-15 06:38:29 EST
I'm geting a similar error in 3.6.1 with a java project using scala library 2.8.1:
java.lang.ClassCastException: org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.initializeTypeVariable(BinaryTypeBinding.java:944)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.createTypeVariables(BinaryTypeBinding.java:647)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.createMethod(BinaryTypeBinding.java:484)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.createMethods(BinaryTypeBinding.java:598)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.cachePartsFrom(BinaryTypeBinding.java:329)
at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.createBinaryTypeFrom(LookupEnvironment.java:674)
at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.createBinaryTypeFrom(LookupEnvironment.java:653)
at org.eclipse.jdt.internal.compiler.Compiler.accept(Compiler.java:295)
at org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:108)
at org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding.resolve(UnresolvedReferenceBinding.java:49)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.resolveType(BinaryTypeBinding.java:122)
at org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.resolve(ParameterizedTypeBinding.java:851)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.resolveType(BinaryTypeBinding.java:100)
at org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.resolve(ParameterizedTypeBinding.java:856)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.resolveType(BinaryTypeBinding.java:100)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.resolveTypesFor(BinaryTypeBinding.java:1040)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.getExactMethod(BinaryTypeBinding.java:795)
at org.eclipse.jdt.internal.compiler.lookup.Scope.findExactMethod(Scope.java:908)
at org.eclipse.jdt.internal.compiler.lookup.Scope.getMethod(Scope.java:2255)
at org.eclipse.jdt.internal.compiler.ast.MessageSend.resolveType(MessageSend.java:403)
at org.eclipse.jdt.internal.compiler.ast.LocalDeclaration.resolve(LocalDeclaration.java:186)
at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:451)
at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:212)
at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:410)
at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1147)
at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1235)
at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:540)
at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:883)
at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:928)
at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:189)
at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:255)
at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.makeConsistent(ReconcileWorkingCopyOperation.java:190)
at org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.executeOperation(ReconcileWorkingCopyOperation.java:89)
at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:728)
at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:788)
at org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1244)
at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:126)
at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.access$0(JavaReconcilingStrategy.java:108)
at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy$1.run(JavaReconcilingStrategy.java:89)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:87)
at org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.initialReconcile(JavaReconcilingStrategy.java:178)
at org.eclipse.jdt.internal.ui.text.CompositeReconcilingStrategy.initialReconcile(CompositeReconcilingStrategy.java:114)
at org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy.initialReconcile(JavaCompositeReconcilingStrategy.java:133)
at org.eclipse.jface.text.reconciler.MonoReconciler.initialProcess(MonoReconciler.java:105)
at org.eclipse.jdt.internal.ui.text.JavaReconciler.initialProcess(JavaReconciler.java:398)
at org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.run(AbstractReconciler.java:173)
Comment 12 Donnchadh Ó Donnabháin CLA 2011-01-15 06:57:15 EST
Has there been a bug logged against the scala compiler? This all I could find:
https://codereview.scala-lang.org/fisheye/cru/SCL-478
but I haven't found a bug report for the scala compiler problem causing this.
Comment 13 marko.mikulicic CLA 2011-01-20 15:42:46 EST
(In reply to comment #2)
> The signature of the method:
>   // Method descriptor #295 (Lscala/PartialFunction;)Lscala/PartialFunction;
>   // Signature:
> <A1:IB1:Ljava/lang/Object;>(Lscala/PartialFunction<TA1;TB1;>;)Lscala/PartialFunction<TA1;TB1;>;
>   // Stack: 2, Locals: 1
>   public static final scala.PartialFunction orElse(scala.PartialFunction arg0);
>     0  getstatic scala.collection.immutable.Nil$.MODULE$ :
> scala.collection.immutable.Nil. [11]
>     3  aload_0 [arg0]
>     4  invokevirtual
> scala.collection.immutable.Nil$.orElse(scala.PartialFunction) :
> scala.PartialFunction [297]
>     7  areturn
> 
> 
> is boggus. I investigate what is the cleanest way to reject that .class file.

can you please quickly describe what is the error/specs-deviation in that signature? I would help me as a starting point for further investigation within the scala community, but before starting reading the jvm bytecode spec I would like to have a glimpse of the issue.
Comment 14 paulp CLA 2011-01-22 15:05:04 EST
Hello.  The scala ticket is:

https://lampsvn.epfl.ch/trac/scala/ticket/4067

The signatures in question are definitely invalid.  I just checked in some code which suppresses signature generation entirely on invalid signatures.  Hopefully it won't be long before it isn't suppressing any, but until then you ought to have less troublesome bytecode.
Comment 15 Olivier Thomann CLA 2011-01-25 10:44:28 EST
The boggus part is:
<A1:IB1:Ljava/lang/Object;>
A FormalTypeParameter should be an identifier (A1) followed by a type descriptor. It is illegal to get a primitive type there (here int: I).

FormalTypeParameters:
  <FormalTypeParameter+>

FormalTypeParameter:
  Identifier ClassBound InterfaceBound*

Hope this clarify what is wrong.
Comment 16 marko.mikulicic CLA 2011-01-25 10:53:40 EST
I implemented a small tool which patches the scala-library.jar classes, as a workaround until the scalac compiler fix and/or eclipse 3.6 is released.

http://www.coldcode.net/2011/01/scala-generics-and-eclipse.html
Comment 17 marko.mikulicic CLA 2011-01-25 11:03:01 EST
(In reply to comment #15)
> The boggus part is:
> <A1:IB1:Ljava/lang/Object;>
> A FormalTypeParameter should be an identifier (A1) followed by a type
> descriptor. It is illegal to get a primitive type there (here int: I).
> 
> FormalTypeParameters:
>   <FormalTypeParameter+>
> 
> FormalTypeParameter:
>   Identifier ClassBound InterfaceBound*
> 
> Hope this clarify what is wrong.

Thank you a lot. That explains the lack of the semicolon, it's not needed with primitive type codes since they don't require an varying length argument.

For now I hardcoded my signature patcher it for ":I" and ":J" cases since I saw those cases in real-world the signatures, but now that I know what those letters stand for I can improve that :-)

(One life is really not enough to learn all...)
Comment 18 Srikanth Sankaran CLA 2011-01-25 11:04:23 EST
Verified for 3.7 M5 via code inspection.
Comment 19 paulp CLA 2011-01-25 13:10:59 EST
Hi - sorry I didn't get back to update the ticket, but I fixed the compiler the same day I commented about the bug.  Soon I'll have the compiler running the signature validater on all builds so this shouldn't come up again.  (Semantically invalid signatures will still be possible of course.)