Implement canonical interface names in wit-component - #2602
Conversation
|
Thanks for the PR! Before diving too deep into review though I want to clarify a few things first. Primarily I don't think this'll work if it's a crate or a runtime flag feature unfortunately. We need a way to roll this out gradually which means that the previous implementation has to live side-by-side with the new implementation, and then eventually we can slowly transition everything over. Could you dig in a bit more to see if this is possible? If it's not possible that'd be somewhat surprising to me, so could you explain a bit more? Second is that I'm a bit confused by the breaking change you mentioned here -- I would expect being able to import 0.0.1 and 0.0.2 at the same time to work out. This is similar to importing both WASIp2 and WASIp3 APIs which is intended to work. |
You mean we need a runtime/CLI flag, instead of a feature flag? That's possible, but less cleaner. Primarily, we would like to define a custom If we opt to a runtime flag, like
My bad. It should be |
|
I think the question comes down to this: after we fully switch over, what's the expected behavior of During the transition period, we can probably wrap the Update: this new function is actually better. It decides the behavior at construction time and we can rely on the regular |
|
Personally what I'd expect is a configuration option on Internally though I don't think that updating What I would roughly envision for this is that |
|
I add a new CLI flag I defined a new wrapper type PackageKey, so that we can control whether to use the canonical version or not during construction time.
In this case, |
canon-names feature|
Reading over this, how come there needs to be a flag in |
|
Perhaps it's easier to understand from bytecodealliance/wit-bindgen#1686, with the flag in From the spec's point of view, canonical version essentially renames the package name to exclude the version suffix. This means that the Resolve behavior is going to change, because we are now loading a wit file with a different name, e.g., from
With the changes in
Not sure what you mean. We can do |
|
Personally at least I'm viewing this feature of the component model specification differently (I think) which I believe is what leads to a lot of my comments. I'm going to explain my thinking here before answering some of your points as I think it'll help convey better where I'm coming from. I see this feature of canonical names in the component model as simplifying the story for dealing with situations like composition, writing a runtime, and knowing what to supply as imports during instantiation. Right now Wasmtime sort of silently matches versions in its This then leaves the question of where all this is handled from a unifying perspective. Today in wit-component it's already merging everything together based on semver. This handles the case where wasi-libc, for example, binds against WASI 0.2.1, the Rust standard library binds against WASI 0.2.2, and then a user could use the One important point though is that this base situation isn't changing. When creating a component there's still type information from many sources at possible different versions, but all still semver-compatible versions. This means that something in the componentization process is still going to need to do some union-ing, no matter what. For bindings generators this technically doesn't need to affect anything. They're still emitting core wasm imports with whatever names With all that in mind, I want to clarify that the way I'm approaching this canonical names feature is that most of the process of handling WITs, bindings generation, etc, doesn't need to change. AFAIK everything is already pretty robust and working as intended, and the main feature that canonical-names is changing is the "last mile" of sorts where the actual literal names in the component are differing. This'll enable hosts or component-handling tools like Wasmtime and wac to start ignoring semver entirely and only think about string matching. Ok so with that background to answer some of your points:
This is not what I would have imagined for wit-bindgen. Internally a By putting this in
I understand that merge-on-semver isn't required when this flag is enabled, but that was a very tricky pass to get write and something that was intentionally left off-by-default. I don't think this simplifies wit-component since it's basically just a single function call, and I'd also need to do a complete audit of the WIT-loading-implementation to ensure it handles the myriad cases that the current pass already handles. For tools like
Yes, I would like to perserve the ability to import 1.0.0 and 1.0.1 in the same world. I disagree with the interpretation of the spec here where a generated component cannot simultaneously import 1.0.0 and 1.0.1 but that doesn't mean that the WIT packages don't exist and implicitly get unified. WIT, as a layer on the specification to assist with distributing/managing type information, has things like The main use case I have for preserving this is the situation where different libraries are using different WASI versions. When linking them together this all needs to be rationalized because all of bindings genertation and componentization is |
Follow-up to #2556.
resolve.use_canonical_namesinwit-parserto merge interfaces with the same canonical version.versionsuffixtowit-component, so that we can link two interfaces via the canonical version name.semver_compat = none|merge|canonicaltowasm-tools component newto control the merging behavior. Deprecate the oldmerge_imports_based_on_semverflag (equivalent tosemver_compat=merge).This is a breaking change. Notably,
import a:b/c@0.1.1; import a:b/c@0.1.2;would fail under the new feature flag, because of duplicate imports. Users can use theimplementsfeature to update the wit file if needed. See themerge-import-versionstest.import a:b/c@0.1.1may becomeimport a:b/c@0.1.2if the wit package fromdeps/is versioned at0.1.2. See thecanon-names-mergetest.Detailed changes
PackageName::canon_version_splitto split canonical version and its version suffix.wit_parser::PackageKey, so that we can control whether to use the canonical version or not during construction time.Resolvewill use PackageKey as the map key, instead ofPackageName. Gradually, we can migrate all uses ofPackageNametoPackageKey.sort_unresolved_packagesmerges packages that share a canonical name, keeping the larger version inResolve. This behavior needs to be made explicit in the spec.encode_interface()andencode_world()consistently use canonical names with version suffixes in the binary encoding.canon-namesfeature)canon-namesfeature use*.canon-names.*alternate blessed fileswit-component, test names withcanon-namesprefix are only run whencanon-namesfeature is enabled.Things left for future PRs
Resolve, when merging two canonical versions, check if the interfaces really conform to the subtyping relation.implementandversionsuffixare present, theversionsuffixshould refer to the version fromimplement, instead of the main package name. Need to clarify this from the spec as well.