Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java 8 method reference inference bug #9307

Closed
niloc132 opened this issue Mar 29, 2016 · 4 comments
Closed

Java 8 method reference inference bug #9307

niloc132 opened this issue Mar 29, 2016 · 4 comments
Labels
Milestone

Comments

@niloc132
Copy link
Contributor

Found while implementing some aspects of Streams/Collectors, stripped down as simply as I could. It looks like the compiler is getting confused as to what type should be returned from the functional interface (String[] instead of String), and the actual returned type from the method reference doesn't match that, so it crashes.

public class Sample implements EntryPoint {
    @Override
    public void onModuleLoad() {
        Window.alert(wrap(StringBuilder::toString));
    }

    static String wrap(F wrapper) {//java.util.function.Function also fails here
        return wrapper.apply(new StringBuilder());
    }

    @FunctionalInterface
    public interface F {
        String apply(StringBuilder t);
    }
}

Built off of https://gwt.googlesource.com/gwt/+/e2a95dc/, but have reproduced this in some way or another for a while.

Expected results, shows a boring alert with an empty string message. Actual result, compiler error:

[INFO] Compiling module my.app.SampleModule
[INFO]    [ERROR] An internal compiler exception occurred
[INFO] com.google.gwt.dev.jjs.InternalCompilerException: Unexpected error during visit.
[INFO]  at com.google.gwt.dev.jjs.ast.JVisitor.translateException(JVisitor.java:111)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:276)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
[INFO]  at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:118)
[INFO]  at com.google.gwt.dev.jjs.ast.JReturnStatement.traverse(JReturnStatement.java:40)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor$ListContext.traverse(JModVisitor.java:88)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.acceptWithInsertRemove(JModVisitor.java:331)
[INFO]  at com.google.gwt.dev.jjs.ast.JBlock.traverse(JBlock.java:92)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
[INFO]  at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:139)
[INFO]  at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:135)
[INFO]  at com.google.gwt.dev.jjs.ast.JMethodBody.traverse(JMethodBody.java:83)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
[INFO]  at com.google.gwt.dev.jjs.ast.JMethod.visitChildren(JMethod.java:787)
[INFO]  at com.google.gwt.dev.jjs.ast.JMethod.traverse(JMethod.java:779)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst.mainLoop(UnifyAst.java:1387)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst.exec(UnifyAst.java:885)
[INFO]  at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.unifyJavaAst(JavaToJavaScriptCompiler.java:1442)
[INFO]  at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.constructJavaAst(JavaToJavaScriptCompiler.java:1254)
[INFO]  at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.precompile(JavaToJavaScriptCompiler.java:1174)
[INFO]  at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.precompile(JavaToJavaScriptCompiler.java:255)
[INFO]  at com.google.gwt.dev.Precompile.precompile(Precompile.java:255)
[INFO]  at com.google.gwt.dev.Precompile.precompile(Precompile.java:202)
[INFO]  at com.google.gwt.dev.Precompile.precompile(Precompile.java:143)
[INFO]  at com.google.gwt.dev.Compiler.run(Compiler.java:197)
[INFO]  at com.google.gwt.dev.Compiler.run(Compiler.java:156)
[INFO]  at com.google.gwt.dev.Compiler$1.run(Compiler.java:117)
[INFO]  at com.google.gwt.dev.CompileTaskRunner.doRun(CompileTaskRunner.java:55)
[INFO]  at com.google.gwt.dev.CompileTaskRunner.runWithAppropriateLogger(CompileTaskRunner.java:50)
[INFO]  at com.google.gwt.dev.Compiler.main(Compiler.java:124)
[INFO] Caused by: java.lang.NoSuchMethodError: java.lang.StringBuilder.toString()Ljava/lang/String;
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst.translate(UnifyAst.java:1603)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst.access$1000(UnifyAst.java:132)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.visit(UnifyAst.java:415)
[INFO]  at com.google.gwt.dev.jjs.ast.JMethodCall.traverse(JMethodCall.java:256)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
[INFO]  ... 34 more
[INFO]       [ERROR] at Sample.java(12): ((StringBuilder) t).toString()
[INFO]          com.google.gwt.dev.jjs.ast.JMethodCall
[INFO]       [ERROR] at Sample.java(12): return ((StringBuilder) t).toString()
[INFO]          com.google.gwt.dev.jjs.ast.JReturnStatement
[INFO]       [ERROR] at Sample.java(12): {
[INFO]   return ((StringBuilder) t).toString();
[INFO] }
[INFO]          com.google.gwt.dev.jjs.ast.JBlock
[INFO]       [ERROR] at Sample.java(12): {
[INFO]   return ((StringBuilder) t).toString();
[INFO] }
[INFO]          com.google.gwt.dev.jjs.ast.JMethodBody
[INFO]       [ERROR] at Sample.java(12): my.app.client.my_app_client_Sample$$__$$my_app_client_Sample$F$$__$$static$$java_lang_StringBuilder$$toString__Ljava_lang_String_2$Type.apply(Ljava/lang/StringBuilder;)Ljava/lang/String;
[INFO]          com.google.gwt.dev.jjs.ast.JMethod

Workaround: Replace the method reference with a lambda:

        Window.alert(wrap((stringBuilder) -> stringBuilder.toString()));
@rluble
Copy link
Contributor

rluble commented Mar 29, 2016

The issue here is that GWT is not resolving correctly method references. StringBuilder::toString is a reference to AbstractStringBuilder::toString (so using AbstractStringBuilder::toString or Object::toString should work)

I'll send up a fix for review shortly.

@rluble
Copy link
Contributor

rluble commented Mar 29, 2016

@niloc132
Copy link
Contributor Author

Thanks for the quick fix! Can you comment on what will generate the "nicest" (speed/size) output from the compiler, or are all lambdas/references/anon classes created equally in the eyes of gwt?

@rluble
Copy link
Contributor

rluble commented Mar 29, 2016

I think that lambdas or, references are mostly equal to anon classes wrt
speed and size; GWT synthesizes anonymous classes for both lambdas and
references. There might be a very small, almost insignificant edge for anon
classes just because you have the control; but that is completely
outweighed by the readability and simplicity of using lambdas and
references.

And in the future we might even make some of the cases (@JsFunction comes to
mind) to be plain functions with no supporting anonymous classes.

On Tue, Mar 29, 2016 at 10:45 AM, Colin Alworth notifications@github.com
wrote:

Thanks for the quick fix! Can you comment on what will generate the
"nicest" (speed/size) output from the compiler, or are all
lambdas/references/anon classes created equally in the eyes of gwt?


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#9307 (comment)

@rluble rluble closed this as completed Mar 29, 2016
zerovcs pushed a commit to zerovcs/gwt that referenced this issue Apr 3, 2016
…ences.

GwtAstBuilder must resolve the method reference to point to
the right declaring class, e.g.

class A {
   public void m() {}
}

class B extends A {
}

B:m() needs to be resolved to A::m() at AST building time in
order for UnifyAST to stitch compilation units together.

Change-Id: I2833e13473bc35945055040d2f318244d012a98d
Bug-Link: gwtproject#9307
@tbroyer tbroyer modified the milestone: 2.8 Apr 14, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants