@@ -25,7 +25,7 @@ document, a pseudo-formal [grammar specification][lexical-structure], and
2525additionally a specification of the [ package format] [ package-format ] of a WIT
2626package suitable for distribution.
2727
28- See [ Gated Features] for an explanation of 🔧.
28+ See [ Gated Features] for an explanation of 🔧 and 🏷️ .
2929
3030[ IDL ] : https://en.wikipedia.org/wiki/Interface_description_language
3131[ components ] : https://github.com/webassembly/component-model
@@ -366,6 +366,57 @@ world union-my-world-b {
366366}
367367```
368368
369+ 🏷️ When a world being included contains plain-named imports or exports that
370+ reference a named interface (using the ` id: use-path ` syntax), the ` with `
371+ keyword renames the plain-name label while preserving the underlying
372+ ` (implements "I") ` annotation in the encoding. For example:
373+
374+ ``` wit
375+ package local:demo;
376+
377+ interface store {
378+ get: func(key: string) -> option<string>;
379+ }
380+
381+ world base {
382+ import cache: store;
383+ }
384+
385+ world extended {
386+ import cache: func();
387+ include base with { cache as my-cache }
388+ }
389+ ```
390+
391+ In this case, ` extended ` requires a ` with ` during its ` include ` because
392+ the plain-name ` cache ` is already taken in the world. The import here is renamed
393+ to ` my-cache ` that implements ` local:demo/store ` , equivalent to writing
394+ ` import my-cache: store; ` directly.
395+
396+ Unlike interface names (which are automatically de-duplicated when two
397+ ` include ` s import the same interface), plain names cannot be de-duplicated
398+ and will conflict. For example:
399+
400+ ``` wit
401+ world base-a {
402+ import cache: store;
403+ }
404+
405+ world base-b {
406+ import cache: store;
407+ }
408+
409+ world conflict {
410+ include base-a;
411+ include base-b; // error: plain name 'cache' conflicts
412+ }
413+
414+ world resolved {
415+ include base-a;
416+ include base-b with { cache as other-cache } // ok: renamed to avoid conflict
417+ }
418+ ```
419+
369420` with ` cannot be used to rename interface names, however, so the following
370421world would be invalid:
371422``` wit
@@ -1382,7 +1433,41 @@ export-item ::= 'export' id ':' extern-type
13821433import-item ::= 'import' id ':' extern-type
13831434 | 'import' use-path ';'
13841435
1385- extern-type ::= func-type ';' | 'interface' '{' interface-items* '}'
1436+ extern-type ::= func-type ';'
1437+ | 'interface' '{' interface-items* '}'
1438+ | use-path ';' 🏷️
1439+ ```
1440+
1441+ 🏷️ The third case of ` extern-type ` allows a named interface to be imported or
1442+ exported with a custom [ plain name] . For example:
1443+
1444+ ``` wit
1445+ world my-world {
1446+ import primary: wasi:keyvalue/store;
1447+ import secondary: wasi:keyvalue/store;
1448+ export my-handler: wasi:http/handler;
1449+ }
1450+ ```
1451+
1452+ Here, ` primary ` and ` secondary ` are two distinct imports that both have the
1453+ instance type of the ` wasi:keyvalue/store ` interface. The plain name of the
1454+ import is the ` id ` before the colon (e.g., ` primary ` ), not the interface name.
1455+ This contrasts with ` import wasi:keyvalue/store; ` (without the ` id : ` prefix),
1456+ which would create a single import using the full interface name
1457+ ` wasi:keyvalue/store ` . Similarly, the export ` my-handler ` has the instance type
1458+ of ` wasi:http/handler ` but uses the plain name ` my-handler ` instead of the full
1459+ interface name, which is useful when a component wants to export the same
1460+ interface multiple times or simply use a more descriptive name.
1461+
1462+ Note that the ` use-path ` form can have an ambiguity with the nested packages
1463+ feature (🪺) where ` a:b ` could mean two things. To resolve this ` a:b ` is lexed
1464+ as a single token instead of separate tokens, meaning:
1465+
1466+ ``` wit
1467+ world w {
1468+ import a:b; // error: can't import a package
1469+ import a: b; // ok, assuming `b` names an interface in scope
1470+ }
13861471```
13871472
13881473Note that worlds can import types and define their own types to be exported
@@ -2073,6 +2158,129 @@ This duplication is useful in the case of cross-package references or split
20732158packages, allowing a compiled ` world ` definition to be fully self-contained and
20742159able to be used to compile a component without additional type information.
20752160
2161+ 🏷️ When a world imports or exports a named interface with a custom plain name
2162+ (using the ` id: use-path ` syntax), the encoding uses the ` (implements "I") `
2163+ annotation defined in [ Explainer.md] ( Explainer.md#import-and-export-definitions ) to indicate which
2164+ interface the instance implements. Note though that each copy implements a
2165+ unique version of the interface in question. For example, the following WIT:
2166+
2167+ ``` wit
2168+ package local:demo;
2169+
2170+ interface store {
2171+ resource bucket {
2172+ constructor(name: string);
2173+ get: func(key: string) -> option<string>;
2174+ }
2175+ }
2176+
2177+ world w {
2178+ import one: store;
2179+ import two: store;
2180+ }
2181+ ```
2182+
2183+ is encoded as:
2184+
2185+ ``` wat
2186+ (component
2187+ (type (export "store") (component
2188+ (export "local:demo/store" (instance
2189+ (export "bucket" (type $b (sub resource)))
2190+ (export "[constructor]bucket" (func (param "name" string) (result (own $b))))
2191+ (export "[method]bucket.get" (func (param "self" (borrow $b)) (param "key" string) (result (option string))))
2192+ ))
2193+ ))
2194+ (type (export "w") (component
2195+ (export "local:demo/w" (component
2196+ (import "one" (implements "local:demo/store") (instance
2197+ (export "bucket" (type $b (sub resource)))
2198+ (export "[constructor]bucket" (func (param "name" string) (result (own $b))))
2199+ (export "[method]bucket.get" (func (param "self" (borrow $b)) (param "key" string) (result (option string))))
2200+ ))
2201+ (import "two" (implements "local:demo/store") (instance
2202+ (export "bucket" (type $b (sub resource)))
2203+ (export "[constructor]bucket" (func (param "name" string) (result (own $b))))
2204+ (export "[method]bucket.get" (func (param "self" (borrow $b)) (param "key" string) (result (option string))))
2205+ ))
2206+ ))
2207+ ))
2208+ )
2209+ ```
2210+
2211+ The ` (implements "local:demo/store") ` prefix tells bindings generators and
2212+ toolchains which interface each plain-named instance import implements, while
2213+ the labels ` one ` and ` two ` provide distinct plain names. This is a case of
2214+ the general ` (implements ..) ` pattern described in
2215+ [ Explainer.md] ( Explainer.md#import-and-export-definitions ) . Also note here that
2216+ two copies of the ` "bucket" ` resource are imported for the ` local:demo/w ` world.
2217+ This is because the interfaces ` one ` and ` two ` duplicate the ` store ` interface.
2218+ Note that this can import just a single ` bucket ` resource by extracting out the
2219+ resource definition into a separate interface. For example:
2220+
2221+ ``` wit
2222+ package local:demo;
2223+
2224+ interface types {
2225+ resource bucket {
2226+ get: func(key: string) -> option<string>;
2227+ }
2228+ }
2229+
2230+ interface store {
2231+ use types.{bucket};
2232+ open: func(name: string) -> bucket;
2233+ }
2234+
2235+ world w {
2236+ import one: store;
2237+ import two: store;
2238+ }
2239+ ```
2240+
2241+ is encoded as:
2242+
2243+ ``` wat
2244+ (component
2245+ (type (export "types") (component
2246+ (export "local:demo/types" (instance
2247+ (export "bucket" (type $b (sub resource)))
2248+ (export "[method]bucket.get" (func (param "self" (borrow $b)) (param "key" string) (result (option string))))
2249+ ))
2250+ ))
2251+ (type (export "store") (component
2252+ (import "local:demo/types" (instance $types
2253+ (export "bucket" (type $b (sub resource)))
2254+ ))
2255+ (alias export $types "bucket" (type $b))
2256+ (export "local:demo/store" (instance
2257+ (export "bucket" (type $b' (eq $b)))
2258+ (export "open" (func (param "name" string) (result (own $b'))))
2259+ ))
2260+ ))
2261+ (type (export "w") (component
2262+ (export "local:demo/w" (component
2263+ (import "local:demo/types" (instance $types
2264+ (export "bucket" (type $b (sub resource)))
2265+ ))
2266+ (alias export $types "bucket" (type $b))
2267+ (import "one" (implements "local:demo/store") (instance
2268+ (export "bucket" (type $b' (eq $b)))
2269+ (export "open" (func (param "name" string) (result (own $b'))))
2270+ ))
2271+ (import "two" (implements "local:demo/store") (instance
2272+ (export "bucket" (type $b' (eq $b)))
2273+ (export "open" (func (param "name" string) (result (own $b'))))
2274+ ))
2275+ ))
2276+ ))
2277+ )
2278+ ```
2279+
2280+ Where in this example the ` local:demo/w ` world imports only a single ` bucket `
2281+ resource under the ` local:demo/types ` interface. This resource is then used
2282+ by the ` one ` and ` two ` export.
2283+
20762284Putting this all together, the following WIT definitions:
20772285
20782286``` wit
0 commit comments