Yordis Prieto Logo
Back to TIL

Component WAT restates imported types instead of pointing at them

wasmcomponent-modelwit

I was writing a proposal to allow type declarations at package scope in WIT, and got asked to show an encoding that actually passes wasm-tools validate.

In WIT, use reads like a reference to a type that lives somewhere else:

package other:app;

use local:demo/point;

interface api {
    move-to: func(p: point);
}

So I expected the WAT to name local:demo/point and stop there. It does not. You restate the whole record, then import it to say where it came from:

(component
  (type (export "api") (component
    (type $point (record (field "x" u32) (field "y" u32)))
    (import "local:demo/point" (type $point' (eq $point)))
    (export "other:app/api" (instance
      (export "move-to" (func (param "p" $point')))
    ))
  ))
)

That (type $point (record ...)) line looks redundant. I kept trying to delete it, and kept getting:

error: unknown type: failed to find name `$point`
  (import "local:demo/point" (type $point' (eq $point)))
                                               ^

The import is not fetching the type. The local definition is the type, and the import only names where it came from. (eq $point) ties the two together.

The reason: a component carries every type it needs to be validated and compiled on its own, without fetching other packages just to pull out a definition. Same as importing an interface from another package and restating its types locally, with imports recording the provenance.

I was expecting something fancier here.

Luke Wagner spelled out the encoding on component-model#699, where he hoists the record to the outer component and exports it there.