conflicting import when composing components
Hello!
I'd be thrilled if you could help me resolve my issue with wasm compose.
I want to build an application that is composed of two components. Both components are made with cargo component, and I use the wit deps out of the wasmtime 14 branch.
The application has one application component, the root component. This component imports the backend components interface.
When composing with
wasm-tools compose -o composed.wasm -c config.yml sample-application.wasm
I encountered this error:
cannot import instance with name `wasi:io/streams` for an instantiation argument of component `backend` because it conflicts with an imported instantiation argument of component `$input
My config:
instantiations:
$input:
arguments:
falumpaset:backend/[email protected]:
instance: backend
backend:
dependency: backend
dependencies:
backend: backend.wasm
I understand that both components import the wasi:io/streams interface. However, they seem to be conflicting.
I´ve looked into the composing logic, and the error seems to originate from the process of merging the two wasi:io interfaces. Hence, I´ve looked into the translated components and compared the two wasi:io/stream imports. It occurs to me that one instance is entirely different from the other.
Within the backend component, I notice that the wasi:io interface also exports elements from the wasi:http world. Is this intended?
If not, how can I resolve this issue?
The backend component
Its world after building:
package root:component
world root {
import wasi:io/poll
import wasi:io/streams
import wasi:http/types
import wasi:http/outgoing-handler
import wasi:filesystem/types
import wasi:filesystem/preopens
import wasi:sockets/tcp
import wasi:cli/environment
import wasi:cli/exit
import wasi:cli/stdin
import wasi:cli/stdout
import wasi:cli/stderr
import wasi:cli/terminal-input
import wasi:cli/terminal-output
import wasi:cli/terminal-stdin
import wasi:cli/terminal-stdout
import wasi:cli/terminal-stderr
export falumpaset:backend/[email protected]
}
(import (interface "wasi:io/streams") (instance (;1;) (type 2)))
(alias export 1 "input-stream" (type (;3;)))
(alias export 0 "pollable" (type (;4;)))
(type (;5;)
(instance
(export (;0;) "fields" (type (sub resource)))
(type (;1;) (variant (case "get") (case "head") (case "post") (case "put") (case "delete") (case "connect") (case "options") (case "trace") (case "patch") (case "other" string)))
(export (;2;) "method" (type (eq 1)))
(type (;3;) (variant (case "HTTP") (case "HTTPS") (case "other" string)))
(export (;4;) "scheme" (type (eq 3)))
(export (;5;) "headers" (type (eq 0)))
(export (;6;) "outgoing-request" (type (sub resource)))
(export (;7;) "outgoing-body" (type (sub resource)))
(export (;8;) "incoming-response" (type (sub resource)))
(type (;9;) u16)
(export (;10;) "status-code" (type (eq 9)))
(export (;11;) "incoming-body" (type (sub resource)))
(alias outer 1 3 (type (;12;)))
(export (;13;) "input-stream" (type (eq 12)))
(export (;14;) "trailers" (type (eq 0)))
(export (;15;) "future-incoming-response" (type (sub resource)))
(type (;16;) (variant (case "invalid-url" string) (case "timeout-error" string) (case "protocol-error" string) (case "unexpected-error" string)))
(export (;17;) "error" (type (eq 16)))
(alias outer 1 4 (type (;18;)))
(export (;19;) "pollable" (type (eq 18)))
(type (;20;) (option u32))
(type (;21;) (record (field "connect-timeout-ms" 20) (field "first-byte-timeout-ms" 20) (field "between-bytes-timeout-ms" 20)))
(export (;22;) "request-options" (type (eq 21)))
(type (;23;) (list u8))
(type (;24;) (tuple string 23))
(type (;25;) (list 24))
(type (;26;) (own 0))
(type (;27;) (func (param "entries" 25) (result 26)))
(export (;0;) "[constructor]fields" (func (type 27)))
(type (;28;) (borrow 0))
(type (;29;) (func (param "self" 28) (result 25)))
(export (;1;) "[method]fields.entries" (func (type 29)))
(type (;30;) (option string))
(type (;31;) (option 4))
(type (;32;) (borrow 5))
(type (;33;) (own 6))
(type (;34;) (func (param "method" 2) (param "path-with-query" 30) (param "scheme" 31) (param "authority" 30) (param "headers" 32) (result 33)))
(export (;2;) "[constructor]outgoing-request" (func (type 34)))
(type (;35;) (borrow 6))
(type (;36;) (own 7))
(type (;37;) (result 36))
(type (;38;) (func (param "self" 35) (result 37)))
(export (;3;) "[method]outgoing-request.write" (func (type 38)))
(type (;39;) (borrow 8))
(type (;40;) (func (param "self" 39) (result 10)))
(export (;4;) "[method]incoming-response.status" (func (type 40)))
(type (;41;) (own 5))
(type (;42;) (func (param "self" 39) (result 41)))
(export (;5;) "[method]incoming-response.headers" (func (type 42)))
(type (;43;) (own 11))
(type (;44;) (result 43))
(type (;45;) (func (param "self" 39) (result 44)))
(export (;6;) "[method]incoming-response.consume" (func (type 45)))
(type (;46;) (borrow 11))
(type (;47;) (own 13))
(type (;48;) (result 47))
(type (;49;) (func (param "self" 46) (result 48)))
(export (;7;) "[method]incoming-body.stream" (func (type 49)))
(type (;50;) (own 14))
(type (;51;) (option 50))
(type (;52;) (func (param "this" 36) (param "trailers" 51)))
(export (;8;) "[static]outgoing-body.finish" (func (type 52)))
(type (;53;) (borrow 15))
(type (;54;) (own 8))
(type (;55;) (result 54 (error 17)))
(type (;56;) (result 55))
(type (;57;) (option 56))
(type (;58;) (func (param "self" 53) (result 57)))
(export (;9;) "[method]future-incoming-response.get" (func (type 58)))
(type (;59;) (own 19))
(type (;60;) (func (param "self" 53) (result 59)))
(export (;10;) "[method]future-incoming-response.subscribe" (func (type 60)))
)
The application component
The world:
package root:component
world root {
import falumpaset:backend/[email protected]
import wasi:io/streams
import wasi:filesystem/types
import wasi:filesystem/preopens
import wasi:sockets/tcp
import wasi:cli/environment
import wasi:cli/exit
import wasi:cli/stdin
import wasi:cli/stdout
import wasi:cli/stderr
import wasi:cli/terminal-input
import wasi:cli/terminal-output
import wasi:cli/terminal-stdin
import wasi:cli/terminal-stdout
import wasi:cli/terminal-stderr
export wasi:cli/run
}
The WAT:
(import (interface "wasi:io/streams") (instance (;1;) (type 1)))
(alias export 1 "output-stream" (type (;2;)))
(alias export 1 "error" (type (;3;)))
(type (;4;)
(instance
(export (;0;) "descriptor" (type (sub resource)))
(type (;1;) u64)
(export (;2;) "filesize" (type (eq 1)))
(alias outer 1 2 (type (;3;)))
(export (;4;) "output-stream" (type (eq 3)))
(type (;5;) (enum "access" "would-block" "already" "bad-descriptor" "busy" "deadlock" "quota" "exist" "file-too-large" "illegal-byte-sequence" "in-progress" "interrupted" "invalid" "io" "is-directory" "loop" "too-many-links" "message-size" "name-too-long" "no-device" "no-entry" "no-lock" "insufficient-memory" "insufficient-space" "not-directory" "not-empty" "not-recoverable" "unsupported" "no-tty" "no-such-device" "overflow" "not-permitted" "pipe" "read-only" "invalid-seek" "text-file-busy" "cross-device"))
(export (;6;) "error-code" (type (eq 5)))
(type (;7;) (enum "unknown" "block-device" "character-device" "directory" "fifo" "symbolic-link" "regular-file" "socket"))
(export (;8;) "descriptor-type" (type (eq 7)))
(type (;9;) (flags "symlink-follow"))
(export (;10;) "path-flags" (type (eq 9)))
(type (;11;) (flags "create" "directory" "exclusive" "truncate"))
(export (;12;) "open-flags" (type (eq 11)))
(type (;13;) (flags "read" "write" "file-integrity-sync" "data-integrity-sync" "requested-write-sync" "mutate-directory"))
(export (;14;) "descriptor-flags" (type (eq 13)))
(type (;15;) (flags "readable" "writable" "executable"))
(export (;16;) "modes" (type (eq 15)))
(alias outer 1 3 (type (;17;)))
(export (;18;) "error" (type (eq 17)))
(export (;19;) "directory-entry-stream" (type (sub resource)))
(type (;20;) (borrow 0))
(type (;21;) (own 4))
(type (;22;) (result 21 (error 6)))
(type (;23;) (func (param "self" 20) (param "offset" 2) (result 22)))
(export (;0;) "[method]descriptor.write-via-stream" (func (type 23)))
(type (;24;) (func (param "self" 20) (result 22)))
(export (;1;) "[method]descriptor.append-via-stream" (func (type 24)))
(type (;25;) (result 8 (error 6)))
(type (;26;) (func (param "self" 20) (result 25)))
(export (;2;) "[method]descriptor.get-type" (func (type 26)))
(type (;27;) (own 0))
(type (;28;) (result 27 (error 6)))
(type (;29;) (func (param "self" 20) (param "path-flags" 10) (param "path" string) (param "open-flags" 12) (param "flags" 14) (param "modes" 16) (result 28)))
(export (;3;) "[method]descriptor.open-at" (func (type 29)))
(type (;30;) (borrow 18))
(type (;31;) (option 6))
(type (;32;) (func (param "err" 30) (result 31)))
(export (;4;) "filesystem-error-code" (func (type 32)))
)
)
I hope this finds you well, and thanks in advance!
This sounds like the same issue I ran into here: https://bytecodealliance.zulipchat.com/#narrow/stream/407292-cargo-component/topic/Component.20composition.20confusion/near/396244085
Thanks for sharing that! I will try and go back to pre resource WITs then.
If I understand correctly (big if 😛) then this may be a manifestation of https://github.com/bytecodealliance/wasm-tools/issues/1253, which would be resolved once https://github.com/bytecodealliance/wasm-tools/pull/1252 (impl of https://github.com/WebAssembly/component-model/pull/248) lands.
Someone with a better understanding and more sleep please feel free to correct me!