bytecodealliance / bytecodealliance/wasm-tools

conflicting import when composing components

Open
#1,254 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
1.8k
Forks
351
Avg merge
16h 57m
Merged PRs (30d)
38

Description

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/connector@0.1.0:
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/connector@0.1.0
}
```
```
(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/connector@0.1.0
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!

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.