Skip to content

Tuple with Java class throws ClassCastException #365

Closed
renatoathaydes opened this Issue Nov 27, 2013 · 8 comments

6 participants

@renatoathaydes

This problem seems to only occur when using Java classes in the tuple.

Here's an example:

import java.awt { Color }

shared void run() {
  value x = [ [1, Color(0)] ];
  value y = { for(e in x) e[1] };
}

When trying to compute y, this Exception is thrown:

ceylon run: java.awt.Color cannot be cast to com.redhat.ceylon.compiler.java.
runtime.model.ReifiedType
java.lang.ClassCastException: java.awt.Color cannot be cast to com.redhat.ceylon.compiler.java.runtime.model.ReifiedType
    at ceylon.language.Tuple.$getElementType(Tuple.java:286)
    at ceylon.language.Tuple.$getUnionOfAllType(Tuple.java:279)
    at ceylon.language.Tuple.$getType(Tuple.java:266)
    at ceylon.language.Tuple.$getType$(Tuple.java:257)
    at ceylon.language.Tuple.$getElementType(Tuple.java:287)
    at ceylon.language.Tuple.$getUnionOfAllType(Tuple.java:279)
    at ceylon.language.Tuple.$getReifiedElement$(Tuple.java:102)
    at ceylon.language.ArraySequence$ArrayListIterator.<init>(ArraySequence.java:355)
    at ceylon.language.ArraySequence.iterator(ArraySequence.java:349)
    at ceylon.language.Tuple.iterator(Tuple.java:234)
    at firstModule.run_$1$1.<init>(run.ceylon:8)
    at firstModule.run_$1.iterator(run.ceylon:8)
    at com.redhat.ceylon.compiler.java.language.AbstractIterable.getEmpty(AbstractIterable.java:93)
    at ceylon.language.Iterable$impl.toString(Iterable.ceylon:561)
    at com.redhat.ceylon.compiler.java.language.AbstractIterable.toString(AbstractIterable.java:83)
    at firstModule.run_.run(run.ceylon:9)
    at firstModule.run_.main(run.ceylon)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at ceylon.modules.api.runtime.SecurityActions.invokeRunInternal(SecurityActions.java:61)
    at ceylon.modules.api.runtime.SecurityActions.invokeRun(SecurityActions.java:51)
    at ceylon.modules.api.runtime.AbstractRuntime.invokeRun(AbstractRuntime.java:89)
    at ceylon.modules.api.runtime.AbstractRuntime.execute(AbstractRuntime.java:141)
    at ceylon.modules.api.runtime.AbstractRuntime.execute(AbstractRuntime.java:126)
    at ceylon.modules.Main.execute(Main.java:69)
    at ceylon.modules.Main.main(Main.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.jboss.modules.Module.run(Module.java:270)
    at org.jboss.modules.Main.main(Main.java:294)
    at ceylon.modules.bootstrap.CeylonRunTool.run(CeylonRunTool.java:208)
    at com.redhat.ceylon.common.tools.CeylonTool.run(CeylonTool.java:343)
    at com.redhat.ceylon.common.tools.CeylonTool.execute(CeylonTool.java:283)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.redhat.ceylon.launcher.Launcher.run(Launcher.java:89)
    at com.redhat.ceylon.launcher.Launcher.main(Launcher.java:21)

I used a comprehension in the example above, but using map, for example, also results in the same error.

If we use an Iterable such as in:

value x = { [1, Color(0)] };
value y = { for(e in x) e[1] };

Then, no error occurs.

Question originally posted on StackOverflow with another example:

stackoverflow.com/questions/20226520/ceylon-cannot-apply-some-functions-to-tuples

@FroMage
Ceylon member
FroMage commented Nov 27, 2013

Yes, apparently we forgot to deal with Java types in there, sorry.

@renatoathaydes

I think I found another Java interop issue but may be closely related to this issue:

Here's 2 Java classes:

public class X<B> {}
public class Y {
    public String hi(X<Boolean> b) {
        return b.toString();
    }
}

Now, in Ceylon, I want to do this:

value x = X<Boolean>();
value y = Y();
y.hi(x);

This results in an error:

argument must be assignable to parameter x of hi in Y: X<Boolean> is not assignable to X<Boolean>?

I believe the Ceylon Boolean should have been mapped to Java's Boolean?!

@gavinking
Ceylon member

@renatoathaydes just add import java.lang { Boolean } and it will compile.

I believe the Ceylon Boolean should have been mapped to Java's Boolean?!

No, that doesn't (and can't) happen with generic types. Sorry.

@ncorai
ncorai commented Dec 7, 2013

I get the same error when passing a Java type to a curried first-class function:

java.lang.ClassCastException: my.package.MyJavaClass$MyJavaEnum cannot be cast to com.redhat.ceylon.compiler.java.runtime.model.ReifiedType
        at ceylon.language.Tuple.$getElementType(Tuple.java:286)
        at ceylon.language.Tuple.$getUnionOfAllType(Tuple.java:279)
        at ceylon.language.Tuple.$getReifiedElement$(Tuple.java:102)
        at ceylon.language.ArraySequence$ArrayListIterator.<init>(ArraySequence.java:355)
        at ceylon.language.ArraySequence.iterator(ArraySequence.java:349)
        at ceylon.language.Tuple.iterator(Tuple.java:234)
        at ceylon.language.Tuple.copyToArray(Tuple.java:86)
        at ceylon.language.Tuple.makeArray(Tuple.java:75)
        at ceylon.language.Tuple.<init>(Tuple.java:54)
        at ceylon.language.curry_$1$1.$call$(curry.ceylon:17)
        at ceylon.language.flatten_$1.$call$(flatten_.java:47)
        at my.other.package.DataAccessObject$1.$call$(DataAccessObject.ceylon:132)

The function invoked at DataAccessObject.ceylon:132 has previously been curried so that the DAO wouldn't have to bother with a parameter that's irrelevant to the persistence layer, so it's a related but somewhat different use-case than a straight use of Tuple.

@ncorai
ncorai commented Dec 8, 2013

And here's another one courtesy of the SDK:

java.lang.ClassCastException: java.nio.file.StandardCopyOption cannot be cast to com.redhat.ceylon.compiler.java.runtime.model.ReifiedType
        at ceylon.language.Tuple.$getElementType(Tuple.java:286)
        at ceylon.language.Tuple.$getUnionOfAllType(Tuple.java:279)
        at ceylon.language.Tuple.$getReifiedElement$(Tuple.java:102)
        at ceylon.language.Tuple.backedBy$hidden(Tuple.java:96)
        at ceylon.language.Tuple.backedBy$hidden(Tuple.java:10)
        at ceylon.language.ArraySequence.getRest(ArraySequence.java:241)
        at ceylon.language.Tuple.getRest(Tuple.java:120)
        at ceylon.language.Tuple.getRest(Tuple.java:10)
        at com.redhat.ceylon.compiler.java.Util.toArray(Util.java:518)
        at ceylon.file.internal.ConcreteFile.copyOverwriting$canonical$(ConcreteFile.ceylon:32)
        at ceylon.file.internal.ConcreteFile.copyOverwriting(ConcreteFile.ceylon)

If you guys release 1.0.1, any chance a fix for this issue could make it?

@lucaswerkmeister
Ceylon member

This was fixed in 8171fd8 and 23dc1ed, wasn’t it? At least Renato’s example works for me now…

@FroMage
Ceylon member
FroMage commented Mar 12, 2014

Then we just need a test to close this.

@tombentley tombentley self-assigned this Mar 24, 2014
@tombentley tombentley added a commit that referenced this issue Mar 24, 2014
@tombentley tombentley Tests for #365. I put these in a separate module because they are not…
… really compiler tests, but are JVM only.
3f7ce79
@tombentley
Ceylon member

Added a test. Closing.

@tombentley tombentley closed this Mar 24, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.