Skip to content

Commit d25824a

Browse files
Add explicit scenarios for feature gate usage
This commit addds some explanation of the intended usage pattern of feature gates in order to make the transition points and functionality easier to identify/reason about. Signed-off-by: Victor Adossi <[email protected]>
1 parent 4eb255f commit d25824a

File tree

1 file changed

+153
-8
lines changed

1 file changed

+153
-8
lines changed

design/mvp/WIT.md

Lines changed: 153 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ interface a {
643643
resource r;
644644
}
645645
interface b {
646-
use a.{r};
646+
use a.{r};
647647
foo: func() -> r;
648648
}
649649
@@ -946,25 +946,23 @@ required to always be paired up with either a `@since` or `@deprecated` gate.
946946
Together, these gates support a development flow in which new features start
947947
with an `@unstable` gate while the details are still being hashed out. Then,
948948
once the feature is stable (and, in a WASI context, voted upon), the
949-
`@unstable` gate is switched to a `@since` gate. To enable a smooth transition
950-
(during which producer toolchains are targeting a version earlier than the
951-
`@since`-specified `version`), the `@since` gate contains an optional `feature`
952-
field that, when present, says to enable the feature when *either* the target
953-
version is greator-or-equal *or* the feature name is explicitly enabled by the
954-
developer. Thus, `c` is enabled if the version is `0.2.2` or newer or the
949+
`@unstable` gate is switched to a `@since` gate.
950+
951+
Thus, `c` is enabled if the version is `0.2.2` or newer or the
955952
`fancy-foo` feature is explicitly enabled by the developer. The `feature` field
956953
can be removed once producer toolchains have updated their default version to
957954
enable the feature by default.
958955

959956
Specifically, the syntax for feature gates is:
957+
960958
```wit
961959
gate ::= gate-item*
962960
gate-item ::= unstable-gate
963961
| since-gate
964962
| deprecated-gate
965963
966964
unstable-gate ::= '@unstable' '(' feature-field ')'
967-
since-gate ::= '@since' '(' version-field ( ',' feature-field )? ')'
965+
since-gate ::= '@since' '(' version-field ')'
968966
deprecated-gate ::= '@deprecated' '(' version-field ')'
969967
970968
feature-field ::= 'feature' '=' id
@@ -973,6 +971,7 @@ version-field ::= 'version' '=' <valid semver>
973971

974972
As part of WIT validation, any item that refers to another gated item must also
975973
be compatibly gated. For example, this is an error:
974+
976975
```wit
977976
interface i {
978977
@since(version = 1.0.1)
@@ -981,6 +980,7 @@ interface i {
981980
type t2 = t1; // error
982981
}
983982
```
983+
984984
Additionally, if an item is *contained* by a gated item, it must also be
985985
compatibly gated. For example, this is an error:
986986
```wit
@@ -993,6 +993,151 @@ interface i {
993993
}
994994
```
995995

996+
#### Scenario: Stabilization of a new feature
997+
998+
This section lays out the basic flow and expected usage of feature gate machinery when stabilizing a new feature.
999+
1000+
Assume the following WIT package as the initial interface:
1001+
1002+
```wit
1003+
package examples:[email protected];
1004+
1005+
@since(version = 0.1.0)
1006+
interface calc {
1007+
@since(version = 0.1.0)
1008+
variant calc-error {
1009+
integer-overflow,
1010+
integer-underflow,
1011+
unexpected,
1012+
}
1013+
1014+
@since(version = 0.1.0)
1015+
add: func(x: i32, y: i32) -> result<i32, calc-error>;
1016+
}
1017+
```
1018+
1019+
**First, add new items under an `@unstable` annotation with a `feature` specified:**
1020+
1021+
```wit
1022+
package examples:[email protected];
1023+
1024+
@since(version = 0.1.0)
1025+
interface calc {
1026+
@since(version = 0.1.0)
1027+
variant calc-error {
1028+
integer-overflow,
1029+
integer-underflow,
1030+
unexpected,
1031+
}
1032+
1033+
@since(version = 0.1.0)
1034+
add: func(x: i32, y: i32) -> result<i32, calc-error>;
1035+
1036+
/// By convention, feature flags should be prefixed with package name to reduce chance of collisions
1037+
///
1038+
/// see: https://github.com/WebAssembly/WASI/blob/main/Contributing.md#filing-changes-to-existing-phase-3-proposals
1039+
@unstable(feature = fgates-calc-minus)
1040+
sub: func(x: i32, y: i32) -> result<i32, calc-error>;
1041+
}
1042+
```
1043+
1044+
At this point, consumers of the WIT can enable feature `fgates-calc-minus` through their relevant tooling and get access to the `sub` function.
1045+
1046+
Note that, at least until subtyping is relaxed in the Component Model, if we had to *add* a new case to `calc-error`, this would be a *breaking change* and require either a new major version or adding a second, distinct `variant` definition used by new functions.
1047+
1048+
**Second, when the feature is ready to be stabilized, switch to a `@since` annotation:**
1049+
1050+
```wit
1051+
package examples:[email protected];
1052+
1053+
@since(version = 0.1.0)
1054+
interface calc {
1055+
@since(version = 0.1.0)
1056+
variant calc-error {
1057+
integer-overflow,
1058+
integer-underflow,
1059+
unexpected,
1060+
}
1061+
1062+
@since(version = 0.1.0)
1063+
add: func(x: i32, y: i32) -> result<i32, calc-error>;
1064+
1065+
@since(version = 0.1.2)
1066+
sub: func(x: i32, y: i32) -> result<i32, calc-error>;
1067+
}
1068+
```
1069+
1070+
#### Scenario: Deprecation of an existing stable feature
1071+
1072+
This section lays out the basic flow and expected usage of feature gate machinery when stabilizing a new feature.
1073+
1074+
Assume the following WIT package as the initial interface:
1075+
1076+
```wit
1077+
package examples:[email protected];
1078+
1079+
@since(version = 0.1.0)
1080+
interface calc {
1081+
@since(version = 0.1.0)
1082+
variant calc-error {
1083+
integer-overflow,
1084+
integer-underflow,
1085+
unexpected,
1086+
}
1087+
1088+
@since(version = 0.1.0)
1089+
add-one: func(x: i32) -> result<i32, calc-error>;
1090+
1091+
@since(version = 0.1.1)
1092+
add: func(x: i32, y: i32) -> result<i32, calc-error>;
1093+
}
1094+
```
1095+
1096+
**First: Add the `@deprecated` annotation to the relevant item in a new version**
1097+
1098+
```wit
1099+
package examples:[email protected];
1100+
1101+
@since(version = 0.1.0)
1102+
interface calc {
1103+
@since(version = 0.1.0)
1104+
variant calc-error {
1105+
integer-overflow,
1106+
integer-underflow,
1107+
unexpected,
1108+
}
1109+
1110+
@deprecated(version = 0.1.2)
1111+
add-one: func(x: i32) -> result<i32, calc-error>;
1112+
1113+
@since(version = 0.1.1)
1114+
add: func(x: i32, y: i32) -> result<i32, calc-error>;
1115+
}
1116+
```
1117+
1118+
At this point, tooling consuming this WIT will be able to appropriately alert users to the now-deprecated `add-one` function.
1119+
1120+
**Second: completely remove the deprecated item in the next SemVer-compliant major version**
1121+
1122+
```wit
1123+
package examples:[email protected];
1124+
1125+
@since(version = 0.1.0)
1126+
interface calc {
1127+
@since(version = 0.1.0)
1128+
variant calc-error {
1129+
integer-overflow,
1130+
integer-underflow,
1131+
unexpected,
1132+
}
1133+
1134+
@since(version = 0.1.1)
1135+
add: func(x: i32, y: i32) -> result<i32, calc-error>;
1136+
}
1137+
```
1138+
1139+
In this new "major" version (this is considered a major version under SemVer 0.X rules) -- the `add-one` function can be fully removed.
1140+
9961141
## Package declaration
9971142
[package declaration]: #package-declaration
9981143

0 commit comments

Comments
 (0)