Skip to content

Commit 6d56eaf

Browse files
committed
Add interface version canonicalization
1 parent e362068 commit 6d56eaf

File tree

1 file changed

+41
-9
lines changed

1 file changed

+41
-9
lines changed

design/mvp/Explainer.md

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ sort ::= core <core:sort>
294294
| type
295295
| component
296296
| instance
297-
inlineexport ::= (export <exportname> <sortidx>)
297+
inlineexport ::= (export "<exportname>" <fullversion>? <sortidx>)
298298
```
299299
Because component-level function, type and instance definitions are different
300300
than core-level function, type and instance definitions, they are put into
@@ -574,8 +574,8 @@ instancedecl ::= core-prefix(<core:type>)
574574
| <alias>
575575
| <exportdecl>
576576
| <value> 🪙
577-
importdecl ::= (import <importname> bind-id(<externdesc>))
578-
exportdecl ::= (export <exportname> bind-id(<externdesc>))
577+
importdecl ::= (import "<importname>" <fullversion>? bind-id(<externdesc>))
578+
exportdecl ::= (export "<exportname>" <fullversion>? bind-id(<externdesc>))
579579
externdesc ::= (<sort> (type <u32>) )
580580
| core-prefix(<core:moduletype>)
581581
| <functype>
@@ -2242,8 +2242,9 @@ the identifier `$x`). In the case of exports, the `<id>?` right after the
22422242
preceding definition being exported (e.g., `(export $x "x" (func $f))` binds a
22432243
new identifier `$x`).
22442244
```ebnf
2245-
import ::= (import "<importname>" bind-id(<externdesc>))
2246-
export ::= (export <id>? "<exportname>" <sortidx> <externdesc>?)
2245+
import ::= (import "<importname>" <fullversion>? bind-id(<externdesc>))
2246+
export ::= (export <id>? "<exportname>" <fullversion>? <sortidx> <externdesc>?)
2247+
fullversion ::= (fullversion "<valid semver>")
22472248
```
22482249
All import names are required to be [strongly-unique]. Separately, all export
22492250
names are also required to be [strongly-unique]. The rest of the grammar for
@@ -2276,17 +2277,21 @@ fragment ::= <word>
22762277
| <acronym>
22772278
word ::= [a-z] [0-9a-z]*
22782279
acronym ::= [A-Z] [0-9A-Z]*
2279-
interfacename ::= <namespace> <label> <projection> <version>?
2280-
| <namespace>+ <label> <projection>+ <version>? 🪺
2280+
interfacename ::= <namespace> <label> <projection> <interfaceversion>?
2281+
| <namespace>+ <label> <projection>+ <interfaceversion>? 🪺
22812282
namespace ::= <words> ':'
22822283
words ::= <word>
22832284
| <words> '-' <word>
22842285
projection ::= '/' <label>
2285-
version ::= '@' <valid semver>
2286+
# FIXME: alignment
2287+
interfaceversion ::= '@' <valid semver>
2288+
| '@' [1-9] [0-9]*
2289+
| '@0.' [1-9] [0-9]*
22862290
depname ::= 'unlocked-dep=<' <pkgnamequery> '>'
22872291
| 'locked-dep=<' <pkgname> '>' ( ',' <hashname> )?
22882292
pkgnamequery ::= <pkgpath> <verrange>?
2289-
pkgname ::= <pkgpath> <version>?
2293+
pkgname ::= <pkgpath> <pkgversion>?
2294+
pkgversion ::= '@' <valid semver>
22902295
pkgpath ::= <namespace> <words>
22912296
| <namespace>+ <words> <projection>* 🪺
22922297
verrange ::= '@*'
@@ -2379,6 +2384,33 @@ interpreted with the same [semantics][SemVerRange]. (Mostly this
23792384
interpretation is the usual SemVer-spec-defined ordering, but note the
23802385
particular behavior of pre-release tags.)
23812386

2387+
The `version` production used in `interfacename`s accepts both `valid semver`
2388+
and "canonicalized interface versions" which can be constructed from a `valid
2389+
semver` as follows:
2390+
2391+
- An input version is split into `<major>.<minor>.<patch>`, with any trailing
2392+
`-<prerelease>` or `+<build>` field discarded.
2393+
- The canonicalized interface version is:
2394+
- if `major` and `minor` are `0`:
2395+
- `0.0.<patch>`
2396+
- otherwise, if `major` is `0`:
2397+
- `0.<minor>`
2398+
- otherwise:
2399+
- `<major>`
2400+
2401+
This canonicalization, when used in conjunction with interface consumers and
2402+
implementations that follow SemVer compatibility, allows the matching of
2403+
compatible imports and exports that differ only in "insignificant" (from a
2404+
SemVer semantics perspective) parts of their version numbers. For example, an
2405+
implementation of `a:b/c@0.2.5` should be compatible with a consumer of
2406+
`a:b/c@0.2.3`; version canonicalization would produce the identical interface
2407+
name `a:b/c@0.2` for both of these versions.
2408+
2409+
When a component producer canonicalizes an interface version the original
2410+
version should be preserved in imports / exports in the `fullversion` field.
2411+
This gives component runtimes and other tools access to the original version for
2412+
error messages, documentation, and other development purposes.
2413+
23822414
The `plainname` production captures several language-neutral syntactic hints
23832415
that allow bindings generators to produce more idiomatic bindings in their
23842416
target language. At the top-level, a `plainname` allows functions to be

0 commit comments

Comments
 (0)