konsoletyper / teavm

Compiles Java bytecode to JavaScript, WebAssembly and C
https://teavm.org
Apache License 2.0
2.66k stars 265 forks source link

`ClassCastException` in Wasm GC backend #964

Closed SquidDev closed 1 month ago

SquidDev commented 1 month ago

Really excited about the new WasmGC backend, thank you so much for your work on this! I wasn't sure if you wanted bugs reported on the issue tracker, or on the discussion itself, so apologies if this is the wrong place.

Trying to compile my one of my projects threw an internal error when using Guava's com.google.common.base.Splitter. I've narrowed it down to the following reproduction case:

import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        Pattern.compile("^\\.{3,}$");
        var logger = Logger.getLogger("Main");
        for (var i = 0; i < 2; i++) {
            logger.log(Level.WARNING, "A warning");
        }
    }
}

Throws the following error:

ERROR: Failed generating method body due to internal exception: java.lang.ClassCastException: class org.teavm.backend.wasm.model.WasmStructure cannot be cast to class org.teavm.backend.wasm.model.WasmArray (org.teavm.backend.wasm.model.WasmStructure and org.teavm.backend.wasm.model.WasmArray are in unnamed module of loader 'app')
        at org.teavm.backend.wasm.generate.gc.methods.WasmGCGenerationVisitor.visit(WasmGCGenerationVisitor.java:587)
        at org.teavm.ast.SubscriptExpr.acceptVisitor(SubscriptExpr.java:51)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.accept(BaseWasmGenerationVisitor.java:156)
        at org.teavm.backend.wasm.generate.gc.methods.WasmGCGenerationVisitor.accept(WasmGCGenerationVisitor.java:117)
        at org.teavm.backend.wasm.generate.gc.methods.WasmGCGenerationVisitor.acceptWithType(WasmGCGenerationVisitor.java:123)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.generateInvocation(BaseWasmGenerationVisitor.java:875)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.invocation(BaseWasmGenerationVisitor.java:831)
        at org.teavm.backend.wasm.generate.gc.methods.WasmGCGenerationVisitor.invocation(WasmGCGenerationVisitor.java:653)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visit(BaseWasmGenerationVisitor.java:486)
        at org.teavm.ast.AssignmentStatement.acceptVisitor(AssignmentStatement.java:60)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.accept(BaseWasmGenerationVisitor.java:160)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visitMany(BaseWasmGenerationVisitor.java:1285)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visit(BaseWasmGenerationVisitor.java:760)
        at org.teavm.ast.WhileStatement.acceptVisitor(WhileStatement.java:39)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.accept(BaseWasmGenerationVisitor.java:160)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visitMany(BaseWasmGenerationVisitor.java:1285)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visit(BaseWasmGenerationVisitor.java:976)
        at org.teavm.ast.BlockStatement.acceptVisitor(BlockStatement.java:30)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.accept(BaseWasmGenerationVisitor.java:160)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visitMany(BaseWasmGenerationVisitor.java:1285)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visit(BaseWasmGenerationVisitor.java:598)
        at org.teavm.ast.ConditionalStatement.acceptVisitor(ConditionalStatement.java:44)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.accept(BaseWasmGenerationVisitor.java:160)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visitMany(BaseWasmGenerationVisitor.java:1285)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visit(BaseWasmGenerationVisitor.java:760)
        at org.teavm.ast.WhileStatement.acceptVisitor(WhileStatement.java:39)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.visit(BaseWasmGenerationVisitor.java:558)
        at org.teavm.ast.SequentialStatement.acceptVisitor(SequentialStatement.java:30)
        at org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor.generate(BaseWasmGenerationVisitor.java:151)
        at org.teavm.backend.wasm.generate.gc.methods.WasmGCMethodGenerator.generateRegularMethodBody(WasmGCMethodGenerator.java:311)
        at org.teavm.backend.wasm.generate.gc.methods.WasmGCMethodGenerator.generateMethodBody(WasmGCMethodGenerator.java:221)
        at org.teavm.backend.wasm.generate.gc.methods.WasmGCMethodGenerator.lambda$createStaticFunction$0(WasmGCMethodGenerator.java:180)
        at org.teavm.backend.wasm.generate.gc.methods.WasmGCMethodGenerator.process(WasmGCMethodGenerator.java:155)
        at org.teavm.backend.wasm.generate.gc.WasmGCDeclarationsGenerator.generate(WasmGCDeclarationsGenerator.java:140)
        at org.teavm.backend.wasm.WasmGCModuleGenerator.generate(WasmGCModuleGenerator.java:32)
        at org.teavm.backend.wasm.WasmGCTarget.emit(WasmGCTarget.java:280)
        at org.teavm.vm.TeaVM.build(TeaVM.java:440)
        at org.teavm.tooling.TeaVMTool.generate(TeaVMTool.java:514)
        at cc.tweaked.web.builder.Builder.run(Builder.java:89)
        at cc.tweaked.web.builder.Builder.buildClasses(Builder.java:74)
        at cc.tweaked.web.builder.Builder.main(Builder.java:42)

    at cc.tweaked.web.Main.main
    at cc.tweaked.web.Main.main$exported$0

java.util.logging.Logger isn't currently supported on the WASM GC backend as these methods are @JSBody only, not @Import, but I don't believe this is related to that — if I replace those methods with stubs, the error still occurs.

konsoletyper commented 1 month ago

isn't currently supported on the WASM GC backend as these methods are @JSBody only, not @Import, but I don't believe this is related to that — if I replace those methods with stubs, the error still occurs.

No, Wasm GC supports @JSBody, as well as 99% of other JSO features. So this is definitely something different.

SquidDev commented 1 month ago

No, Wasm GC supports @JSBody, as well as 99% of other JSO features. So this is definitely something different.

Yeah, I was a little confused about this! It definitely works elsewhere, but the Logger methods fail with the following:

ERROR: Method is not annotated with org.teavm.interop.Import
    at java.util.logging.Logger.warn
    at java.util.logging.Logger.log(TLogger.java:75)
    at java.util.logging.Logger.log(TLogger.java:132)
    at cc.tweaked.web.Main.main(Main.java:15)
    at cc.tweaked.web.Main.main$exported$0