Skip to content

Allow type declarations at package scope - #699

Open
yordis wants to merge 2 commits into
WebAssembly:mainfrom
yordis:yordis/feat-package-scope-types
Open

Allow type declarations at package scope#699
yordis wants to merge 2 commits into
WebAssembly:mainfrom
yordis:yordis/feat-package-scope-types

Conversation

@yordis

@yordis yordis commented Aug 15, 2026

Copy link
Copy Markdown

This PR allows type, record, variant, enum and flags declarations at package scope in WIT, as proposed in #694. Today, sharing a type vocabulary across interfaces requires inventing an interface to hold it, and that container reaches the artifact as an instance import that nothing calls.

resource is deliberately excluded. Resources carry identity rather than structure, so an interface is what gives a resource its identity, and package scope has nothing to offer there. That is why the grammar names a package-typedef-item rather than reusing typedef-item, which already includes resource-item.

Sharing a type vocabulary between interfaces requires inventing an interface
to hold it, and that container reaches the artifact as an import nothing calls.

Refs WebAssembly#694

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Comment thread design/mvp/WIT.md
Comment on lines +2156 to +2166
```wat
(component
(type (export "point") (record (field "x" u32) (field "y" u32)))
(type (export "api") (component
(export "local:demo/api" (instance
(type $point (record (field "x" u32) (field "y" u32)))
(export "move-to" (func (param "p" $point)))
))
))
)
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For myself this is the main point of question for me of how these top-level types would be encoded in WIT. This component as-is is not valid (doesn't pass wasm-tools validate), and I assume that you don't want to change the validation rules for components, so could this be updated with an encoding that's valid?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great question! Here's one idea I think might work:

For WIT interfaces like the above, we treat these dependencies on package-level types just like use of an interface that contains the analogous type definition, we just strip out the wrapping instance type:

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

and then for the analogous WIT world (that exports move-to), we move the (import "local:demo/point" (type ...)) inside the inner component type so that it works like a type definition inside an imported interface, just not wrapped in an instance type:

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

A component-model export may only refer to named types, so the encoding
example did not validate. The scheme has to hold under the existing
component validation rules rather than ask for new ones.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis
yordis requested a review from alexcrichton August 17, 2026 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants