Repository navigation
Closed
Closed
Copy link
Milestone
Description
The optimize flag for the GWT compiler changes results in compilation error of this switch expression
public class TestComposite extends Composite {
private final TextBox textBox = new TextBox();
public TestComposite() {
super();
}
void setText(TestEnum testEnum) {
Void ignored = switch (testEnum) {
case A -> {
textBox.setText("A");
yield null;
}
case B -> {
textBox.setText("B");
yield null;
}
};
}
enum TestEnum {
A, B
}
}
This results in IllegalStateException("top-level switch expr") coming from the GenerateJavaScriptAST#transformExpressionStatement when running with optimize level 9.
[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.JVisitor.accept(JVisitor.java:130)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:122)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer.transform(JTransformer.java:1100)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer.transformIntoExcludingNulls(JTransformer.java:1120)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformBlock(GenerateJavaScriptAST.java:583)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformBlock(GenerateJavaScriptAST.java:520)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer$JRewriterVisitor.visit(JTransformer.java:647)
[INFO] at com.google.gwt.dev.jjs.ast.JBlock.traverse(JBlock.java:93)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:127)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:122)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer.transform(JTransformer.java:1100)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transform(GenerateJavaScriptAST.java:2672)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformMethodBody(GenerateJavaScriptAST.java:833)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformMethodBody(GenerateJavaScriptAST.java:520)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer$JRewriterVisitor.visit(JTransformer.java:854)
[INFO] at com.google.gwt.dev.jjs.ast.JMethodBody.traverse(JMethodBody.java:81)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:127)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:122)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer.transform(JTransformer.java:1100)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformMethod(GenerateJavaScriptAST.java:804)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformMethod(GenerateJavaScriptAST.java:520)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer$JRewriterVisitor.visit(JTransformer.java:848)
[INFO] at com.google.gwt.dev.jjs.ast.JMethod.traverse(JMethod.java:777)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:127)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:122)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer.transform(JTransformer.java:1100)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.emitStaticMethods(GenerateJavaScriptAST.java:1869)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformDeclaredType(GenerateJavaScriptAST.java:647)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformDeclaredType(GenerateJavaScriptAST.java:520)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer.transformClassType(JTransformer.java:95)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer$JRewriterVisitor.visit(JTransformer.java:695)
[INFO] at com.google.gwt.dev.jjs.ast.JClassType.traverse(JClassType.java:145)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:127)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:122)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer.transform(JTransformer.java:1100)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformProgram(GenerateJavaScriptAST.java:1242)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformProgram(GenerateJavaScriptAST.java:520)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer$JRewriterVisitor.visit(JTransformer.java:943)
[INFO] at com.google.gwt.dev.jjs.ast.JProgram.traverse(JProgram.java:1248)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:127)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:122)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer.transform(JTransformer.java:1100)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST.execImpl(GenerateJavaScriptAST.java:3171)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST.exec(GenerateJavaScriptAST.java:2944)
[INFO] at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.compilePermutation(JavaToJavaScriptCompiler.java:380)
[INFO] at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.compilePermutation(JavaToJavaScriptCompiler.java:274)
[INFO] at com.google.gwt.dev.CompilePerms.compile(CompilePerms.java:198)
[INFO] at com.google.gwt.dev.ThreadedPermutationWorkerFactory$ThreadedPermutationWorker.compile(ThreadedPermutationWorkerFactory.java:50)
[INFO] at com.google.gwt.dev.PermutationWorkerFactory$Manager$WorkerThread.run(PermutationWorkerFactory.java:74)
[INFO] at java.base/java.lang.Thread.run(Thread.java:1583)
[INFO] Caused by: java.lang.IllegalStateException: top-level switch expr
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformExpressionStatement(GenerateJavaScriptAST.java:708)
[INFO] at com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST$GenerateJavaScriptTransformer.transformExpressionStatement(GenerateJavaScriptAST.java:520)
[INFO] at com.google.gwt.dev.jjs.ast.JTransformer$JRewriterVisitor.visit(JTransformer.java:755)
[INFO] at com.google.gwt.dev.jjs.ast.JExpressionStatement.traverse(JExpressionStatement.java:41)
[INFO] at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:127)
[INFO] ... 49 more
[INFO] [ERROR] at TestComposite.java(14): switch (0) {
[INFO] case 0:
[INFO] {
[INFO] ValueBoxBase.$setText(this$static.textBox, "A");
[INFO] yield null;
[INFO] }
[INFO] case 1:
[INFO] {
[INFO] ValueBoxBase.$setText(this$static.textBox, "B");
[INFO] yield null;
[INFO] }
[INFO] }
[INFO] com.google.gwt.dev.jjs.ast.JExpressionStatement
[INFO] [ERROR] at TestComposite.java(13): {
[INFO] switch (0) {
[INFO] case 0:
[INFO] {
[INFO] ValueBoxBase.$setText(this$static.textBox, "A");
[INFO] yield null;
[INFO] }
[INFO] case 1:
[INFO] {
[INFO] ValueBoxBase.$setText(this$static.textBox, "B");
[INFO] yield null;
[INFO] }
[INFO] }
[INFO] }
[INFO] com.google.gwt.dev.jjs.ast.JBlock
[INFO] [ERROR] at TestComposite.java(13): {
[INFO] switch (0) {
[INFO] case 0:
[INFO] {
[INFO] ValueBoxBase.$setText(this$static.textBox, "A");
[INFO] yield null;
[INFO] }
[INFO] case 1:
[INFO] {
[INFO] ValueBoxBase.$setText(this$static.textBox, "B");
[INFO] yield null;
[INFO] }
[INFO] }
[INFO] }
[INFO] com.google.gwt.dev.jjs.ast.JMethodBody
[INFO] [ERROR] at TestComposite.java(13): com.example.client.editor.TestComposite.$setText(Lcom/example/client/editor/TestComposite;Lcom/example/client/editor/TestComposite$TestEnum;)V
[INFO] com.google.gwt.dev.jjs.ast.JMethod
[INFO] [ERROR] at TestComposite.java(6): com.example.client.editor.TestComposite (extends Composite)
[INFO] com.google.gwt.dev.jjs.ast.JClassType
[INFO] [ERROR] at Unknown(0): <JProgram>
[INFO] com.google.gwt.dev.jjs.ast.JProgram
[INFO] [ERROR] Unrecoverable exception, shutting down
[INFO] com.google.gwt.core.ext.UnableToCompleteException: (see previous log entries)
[INFO] at com.google.gwt.dev.javac.CompilationProblemReporter.logAndTranslateException(CompilationProblemReporter.java:106)
[INFO] at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.compilePermutation(JavaToJavaScriptCompiler.java:461)
[INFO] at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.compilePermutation(JavaToJavaScriptCompiler.java:274)
[INFO] at com.google.gwt.dev.CompilePerms.compile(CompilePerms.java:198)
[INFO] at com.google.gwt.dev.ThreadedPermutationWorkerFactory$ThreadedPermutationWorker.compile(ThreadedPermutationWorkerFactory.java:50)
[INFO] at com.google.gwt.dev.PermutationWorkerFactory$Manager$WorkerThread.run(PermutationWorkerFactory.java:74)
[INFO] at java.base/java.lang.Thread.run(Thread.java:1583)
[INFO] [ERROR] Not all permutation were compiled , completed (0/1)
This does not occur when you have a function that returns instead of assigning it to a variable
public class TestComposite extends Composite {
private final TextBox textBox = new TextBox();
public TestComposite() {
super();
}
Void setText(TestEnum testEnum) {
return switch (testEnum) {
case A -> {
textBox.setText("A");
yield null;
}
case B -> {
textBox.setText("B");
yield null;
}
};
}
enum TestEnum {
A, B
}
}
I've tested a multitude of return types and they all lead to the same exception.
If I compile using --optimize=0, the bundle is generated without any issues.
Metadata
Metadata
Assignees
Labels
No labels
Activity
niloc132 commentedon Apr 30, 2025
Thanks for the report, still working on reproducing.
Can you confirm which GWT version you encountered this on?
Also, while I recognize that no code patterns should have a bug like this, can you explain briefly what this code is intended to do with the Void yield?
Switch exprs must be transformed rather than wrapped in statements
JeffreyDevloo commentedon Apr 30, 2025
The GWT version that I am using is 2.12.
The Void is just a pattern to force a compilation error when the enum would change. All branches are just blocks of side effects but it forces me as a developer to think about implementing them when I add new entries to the enum.
Just having
allows for any branch to exist. No branches are enforced during compile time.
A more common use case is to just compute a result while having intermediate steps:
The key here was to compile using the optimize=9 option. I did not encounter it during the codeserver compilations, only during our production build step.
JeffreyDevloo commentedon Apr 30, 2025
Judging by your commit. If I had used the result, it would've worked? I've used a work around using a supplier now π .
niloc132 commentedon Apr 30, 2025
Thanks, I've added a few tests that try this out in a few ways, and I think the bug should be fixed in that PR.
Yes, if you used the result, the compiler never would have removed it, and so the bug wouldn't have happened - that does seem like a valid way to work around it. Funny thing about your supplier though - in order for switch-exprs to make sense in JS (with regard to flow control), we already wrap a switch statement in a js
function, so you are effectively double wrapping a switch statement in a function with your workaround. It should work though, as long as at least one callsite in your program uses the result of Supplier.get().JeffreyDevloo commentedon Apr 30, 2025
Thanks for looking into it this fast! One of the few issues I've encountered with GWT that weren't caused by me.
Switch exprs must be transformed rather than wrapped in statements (gβ¦