Skip to content

Commit 8d34a70

Browse files
committed
Add gates to 'interface' and 'world' definitions
1 parent 8c066b4 commit 8d34a70

File tree

1 file changed

+57
-48
lines changed

1 file changed

+57
-48
lines changed

design/mvp/WIT.md

Lines changed: 57 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,61 @@ Concretely, the structure of a `wit` file is:
851851
wit-file ::= package-decl? (toplevel-use-item | interface-item | world-item)*
852852
```
853853

854+
### Feature Gates
855+
856+
Various WIT items can be "gated", to reflect the fact that the item is part of
857+
an unstable feature or that the item was added as part of a minor version
858+
update and shouldn't be used when targeting an earlier minor version.
859+
860+
For example, the following interface has 4 items, 3 of which are gated:
861+
```wit
862+
interface foo {
863+
a: func();
864+
865+
@since(version = "0.2.1")
866+
b: func();
867+
868+
@since(version = "0.2.2", feature = "fancy-foo")
869+
c: func();
870+
871+
@unstable(feature = "fancier-foo")
872+
d: func();
873+
}
874+
```
875+
The `@since` gate indicates that `b` and `c` were added as part of the `0.2.1`
876+
and `0.2.2` releases, resp. Thus, when building a component targeting, e.g.,
877+
`0.2.1`, `b` can be used, but `c` cannot. An important expectation set by the
878+
`@since` gate is that, once applied to an item, the item is not modified
879+
incompatibly going forward (according to general semantic versioning rules).
880+
881+
In contrast, the `@unstable` gate on `d` indicates that `d` is part of the
882+
`fancier-foo` feature that is still under active development and thus `d` may
883+
change type or be removed at any time. An important expectation set by the
884+
`@unstable` gate is that toolchains will not expose `@unstable` features by
885+
default unless explicitly opted-into by the developer.
886+
887+
Together, these gates support a development flow in which new features start
888+
with an `@unstable` gate while the details are still being hashed out. Then,
889+
once the feature is stable (and, in a WASI context, voted upon), the
890+
`@unstable` gate is switched to a `@since` gate. To enable a smooth transition
891+
(during which producer toolchains are targeting a version earlier than the
892+
`@since`-specified `version`), the `@since` gate contains an optional `feature`
893+
field that, when present, says to enable the feature when *either* the target
894+
version is greator-or-equal *or* the feature name is explicitly enabled by the
895+
developer. Thus, `c` is enabled if the version is `0.2.2` or newer or the
896+
`fancy-foo` feature is explicitly enabled by the developer. The `feature` field
897+
can be removed once producer toolchains have updated their default version to
898+
enable the feature by default.
899+
900+
Specifically, the syntax for feature gates is:
901+
```wit
902+
gate ::= unstable-gate
903+
| since-gate
904+
unstable-gate ::= '@unstable' '(' feature-field ')'
905+
feature-field ::= 'feature' '=' '"' id '"'
906+
since-gate ::= '@since' '(' 'version' '=' '"' <valid semver> '"' ( ',' feature-field )? ')'
907+
```
908+
854909
## Package declaration
855910

856911
WIT files optionally start with a package declaration which defines the ID of
@@ -895,7 +950,7 @@ Worlds define a [componenttype](https://github.com/WebAssembly/component-model/b
895950
Concretely, the structure of a world is:
896951

897952
```ebnf
898-
world-item ::= 'world' id '{' world-items* '}'
953+
world-item ::= gate 'world' id '{' world-items* '}'
899954
900955
world-items ::= export-item | import-item | use-item | typedef-item | include-item
901956
@@ -937,61 +992,15 @@ Interfaces can be defined in a `wit` file. Interfaces have a name and a
937992
sequence of items and functions, all of which can be gated on an `id` or a
938993
semantic version.
939994

940-
For example, the following interface has 4 items, 3 of which are gated:
941-
```wit
942-
interface foo {
943-
a: func();
944-
945-
@since(version = "0.2.1")
946-
b: func();
947-
948-
@since(version = "0.2.2", feature = "fancy-foo")
949-
c: func();
950-
951-
@unstable(feature = "fancier-foo")
952-
d: func();
953-
}
954-
```
955-
The `@since` gate indicates that `b` and `c` were added as part of the `0.2.1`
956-
and `0.2.2` releases, resp. Thus, when building a component targeting, e.g.,
957-
`0.2.1`, `b` can be used, but `c` cannot. An important expectation set by the
958-
`@since` gate is that, once applied to an item, the item is not modified
959-
incompatibly going forward (according to general semantic versioning rules).
960-
961-
In contrast, the `@unstable` gate on `d` indicates that `d` is part of the
962-
`fancier-foo` feature that is still under active development and thus `d` may
963-
change type or be removed at any time. An important expectation set by the
964-
`@unstable` gate is that toolchains will not expose `@unstable` features by
965-
default unless explicitly opted-into by the developer.
966-
967-
Together, these gates support a development flow in which new features start
968-
with an `@unstable` gate while the details are still being hashed out. Then,
969-
once the feature is stable (and, in a WASI context, voted upon), the
970-
`@unstable` gate is switched to a `@since` gate. To enable a smooth transition
971-
(during which producer toolchains are targeting a version earlier than the
972-
`@since`-specified `version`), the `@since` gate contains an optional `feature`
973-
field that, when present, says to enable the feature when *either* the target
974-
version is greator-or-equal *or* the feature name is explicitly enabled by the
975-
developer. Thus, `c` is enabled if the version is `0.2.2` or newer or the
976-
`fancy-foo` feature is explicitly enabled by the developer. The `feature` field
977-
can be removed once producer toolchains have updated their default version to
978-
enable the feature by default.
979-
980995
Specifically interfaces have the structure:
981996

982997
> **Note**: The symbol `ε`, also known as Epsilon, denotes an empty string.
983998
984999
```ebnf
985-
interface-item ::= 'interface' id '{' interface-items* '}'
1000+
interface-item ::= gate 'interface' id '{' interface-items* '}'
9861001
9871002
interface-items ::= gate interface-definition
9881003
989-
gate ::= unstable-gate
990-
| since-gate
991-
unstable-gate ::= '@unstable' '(' feature-field ')'
992-
feature-field ::= 'feature' '=' '"' id '"'
993-
since-gate ::= '@since' '(' 'version' '=' '"' <valid semver> '"' ( ',' feature-field )? ')'
994-
9951004
interface-definition ::= typedef-item
9961005
| use-item
9971006
| func-item

0 commit comments

Comments
 (0)