Backend error in Java functional-interface interop
While the compiler usually accepts Ceylon Callables with a matching signature when a Java method wants an object satisfying a functional (only-one-abstract-method) interface, whether it's a reference to a local method or a parameter (or field) of type Callable, I've stumbled on one interface that triggers a backend error: java.awt.image::ImageObserver. As the following error-inducing code shows, passing a direct method reference where the method wants an ImageObserver compiles fine, but if that method reference is stored in a field or parameter of type Boolean(Image, Integer, Integer, Integer, Integer, Integer), this causes a backend error; it also produces a CompilerBugException stacktrace when compiling on the command line, and a RuntimeException "Error generating bytecode" with a stacktrace in the Eclipse IDE.
import java.awt {
Image,
Graphics
}
class SwingSMI(Boolean(Image, Integer, Integer, Integer, Integer, Integer) observer) {
Boolean observerImpl(Image img, Integer one, Integer two, Integer three, Integer four, Integer five)
=> false;
Boolean(Image, Integer, Integer, Integer, Integer, Integer) reference = observerImpl;
shared void draw(Graphics pen, Image image) {
pen.drawImage(image, 0, 0, 0, 0, observerImpl); // works
// Next line: additionally: error: Ceylon backend error: method invoked with incorrect number of arguments; expected 6, found 0
pen.drawImage(image, 0, 0, 0, 0, reference); // Ceylon backend error: cannot find symbol // symbol: variable getReference$priv$
pen.drawImage(image, 0, 0, 0, 0, observer); // Ceylon backend error: cannot find symbol // symbol: variable getObserver$priv$
}
}
The stack trace on the command line:
com.redhat.ceylon.compiler.CompilerBugException: Codegen Error
at com.redhat.ceylon.compiler.CeylonCompileTool.handleExitCode(CeylonCompileTool.java:933)
at com.redhat.ceylon.compiler.CeylonCompileTool.run(CeylonCompileTool.java:915)
at com.redhat.ceylon.common.tools.CeylonTool.run(CeylonTool.java:547)
at com.redhat.ceylon.common.tools.CeylonTool.execute(CeylonTool.java:423)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.redhat.ceylon.launcher.Launcher.runInJava7Checked(Launcher.java:108)
at com.redhat.ceylon.launcher.Launcher.run(Launcher.java:38)
at com.redhat.ceylon.launcher.Launcher.run(Launcher.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.redhat.ceylon.launcher.Bootstrap.runVersion(Bootstrap.java:162)
at com.redhat.ceylon.launcher.Bootstrap.runInternal(Bootstrap.java:117)
at com.redhat.ceylon.launcher.Bootstrap.run(Bootstrap.java:93)
at com.redhat.ceylon.launcher.Bootstrap.main(Bootstrap.java:85)
Caused by: java.lang.RuntimeException: Error generating bytecode for source/mwe/SwingSMI.ceylon
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.genCodeUnlessError(LanguageCompiler.java:839)
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.genCode(LanguageCompiler.java:776)
at com.redhat.ceylon.langtools.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1575)
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.generate(LanguageCompiler.java:953)
at com.redhat.ceylon.langtools.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1539)
at com.redhat.ceylon.langtools.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:904)
at com.redhat.ceylon.langtools.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:862)
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.compile(LanguageCompiler.java:270)
at com.redhat.ceylon.compiler.java.launcher.Main.compile(Main.java:660)
at com.redhat.ceylon.compiler.java.launcher.Main.compile(Main.java:563)
at com.redhat.ceylon.compiler.java.launcher.Main.compile(Main.java:555)
at com.redhat.ceylon.compiler.java.launcher.Main.compile(Main.java:544)
at com.redhat.ceylon.compiler.CeylonCompileTool.run(CeylonCompileTool.java:914)
... 17 more
Caused by: java.lang.AssertionError: typecode ERROR
at com.redhat.ceylon.langtools.tools.javac.jvm.Code.typecode(Code.java:248)
at com.redhat.ceylon.langtools.tools.javac.jvm.Items$Item.coerce(Items.java:269)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genExpr(Gen.java:951)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitSelect(Gen.java:2345)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:1896)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genExpr(Gen.java:949)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitApply(Gen.java:1843)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1464)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genExpr(Gen.java:949)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitReturn(Gen.java:1809)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1383)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genDef(Gen.java:739)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genStat(Gen.java:774)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genStat(Gen.java:760)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genStats(Gen.java:811)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitBlock(Gen.java:1159)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:908)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genDef(Gen.java:739)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genStat(Gen.java:774)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genMethod(Gen.java:1033)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitMethodDef(Gen.java:996)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:777)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genDef(Gen.java:739)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genClass(Gen.java:2461)
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.genCodeUnlessError(LanguageCompiler.java:810)
... 29 more
The stack trace in Eclipse:
The Ceylon Java backend compilation failed
with 6 malformed Javac tree cases
with a throwable : java.lang.RuntimeException: Error generating bytecode for /Users/kingjon/tmp/ceylon/source/mwe/SwingSMI.ceylon
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.genCodeUnlessError(LanguageCompiler.java:839)
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.genCode(LanguageCompiler.java:776)
at com.redhat.ceylon.langtools.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1575)
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.generate(LanguageCompiler.java:953)
at com.redhat.ceylon.langtools.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1539)
at com.redhat.ceylon.langtools.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:904)
at com.redhat.ceylon.langtools.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:862)
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.compile(LanguageCompiler.java:270)
at com.redhat.ceylon.compiler.java.launcher.Main.compile(Main.java:660)
at com.redhat.ceylon.langtools.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:132)
at com.redhat.ceylon.langtools.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:141)
at com.redhat.ceylon.compiler.java.tools.CeyloncTaskImpl.call(CeyloncTaskImpl.java:59)
at com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.compile(CeylonBuilder.java:2663)
at com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.generateBinaries(CeylonBuilder.java:2392)
at com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.access$100(CeylonBuilder.java:210)
at com.redhat.ceylon.eclipse.core.builder.CeylonBuilder$4.call(CeylonBuilder.java:1075)
at com.redhat.ceylon.eclipse.core.builder.CeylonBuilder$4.call(CeylonBuilder.java:1072)
at com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.doWithCeylonModelCaching(CeylonBuilder.java:260)
at com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.build(CeylonBuilder.java:1072)
at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:735)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:206)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:246)
at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:301)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:304)
at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:360)
at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:383)
at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:142)
at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:232)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:56)
Caused by: java.lang.AssertionError: typecode ERROR
at com.redhat.ceylon.langtools.tools.javac.jvm.Code.typecode(Code.java:248)
at com.redhat.ceylon.langtools.tools.javac.jvm.Items$Item.coerce(Items.java:269)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genExpr(Gen.java:951)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitSelect(Gen.java:2345)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:1896)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genExpr(Gen.java:949)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitApply(Gen.java:1843)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1464)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genExpr(Gen.java:949)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitReturn(Gen.java:1809)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1383)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genDef(Gen.java:739)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genStat(Gen.java:774)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genStat(Gen.java:760)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genStats(Gen.java:811)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitBlock(Gen.java:1159)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:908)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genDef(Gen.java:739)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genStat(Gen.java:774)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genMethod(Gen.java:1033)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.visitMethodDef(Gen.java:996)
at com.redhat.ceylon.langtools.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:777)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genDef(Gen.java:739)
at com.redhat.ceylon.langtools.tools.javac.jvm.Gen.genClass(Gen.java:2461)
at com.redhat.ceylon.compiler.java.tools.LanguageCompiler.genCodeUnlessError(LanguageCompiler.java:810)
... 30 more
ceylon --version reports ceylon version 1.3.3 0d594b3 (Contents May Differ); the Eclipse plugin looks to be version 1.3.3.v20170818-1632-Final, and I'm running Eclipse 4.7.3a. For completeness, this is MacOS Sierra, and the Ceylon command-line SDK was installed via Homebrew.
Related issue #7379.