bytecodealliance / wasm-tools

CLI and Rust libraries for low-level manipulation of WebAssembly modules
Apache License 2.0
1.22k stars 225 forks source link

wasm-compose resource subtype mismatch #1163

Open juntyr opened 10 months ago

juntyr commented 10 months ago

I have the following wit file:

package test:ser

interface serializer {
    resource serializer-resource {
        constructor()
        serialize-i32: static func(self: serializer-resource, v: s32) -> string
    }
}

world test-serialize {
    import serializer
}

world test-serializer {
    export serializer
}

and two WASM components which implement test-serialize and test-serializer, respectively (both are implemented in Rust and then transformed into components with wasm-tools component new).

I am trying to compose these two components such that the serialize component can construct a new serializer-resource and call a method on it, even though it imports both from another component, i.e. none of the functionality comes from the host.

When running wasm-tools compose serialize.wasm -d serializer.wasm -o composed.wasm, I get the following error:

error: failed to connect instance `$input` to definition component `./serializer.wasm`

Caused by:
    0: source instance export `test:ser/serializer` is not compatible with target instance import `test:ser/serializer`

After a bit of digging, I found that the following two subtyping checks cause this error: https://github.com/bytecodealliance/wasm-tools/blob/a0c46a7a16fef5cc9143ad30c77f19303c27d907/crates/wasmparser/src/validator/types.rs#L2521 and https://github.com/bytecodealliance/wasm-tools/blob/a0c46a7a16fef5cc9143ad30c77f19303c27d907/crates/wasmparser/src/validator/types.rs#L3074

I have no idea why two independent resource IDs are generated even though the resource imported by the serialize component is the same as the resource exported by the serializer component. Crudely commenting out this check allows the components to be composed, and the composed component to be run in wasmtime, and the resource seems to work perfectly fine (constructor, method, and destructor are all called as expected).

Is there a way for the component subtyping match to succeed? Thank you for your help!

Attachments: serializer.zip serialize.zip

alexcrichton commented 10 months ago

Thanks for the report! This is a known issue with wasm-compose where it does not yet have support for resources. This hasn't quite bubbled up to the top of the priority queue for anyone yet and is likely to require a bit of surgery to handle this, so it's unfortunately not an easy lift.

That being said this is good to keep track of, thanks for filing this!

dicej commented 8 months ago

FYI, I'm starting work on a subset of resource support in wasm-compose, specifically composing two components which import the same resource type such that they can pass handles to that type between each other. Hopefully we can build upon that work to support other cases as well.

fitzgen commented 8 months ago

@dicej you might want to do it on top of #1257 to avoid annoying rebase conflicts.