-
Notifications
You must be signed in to change notification settings - Fork 244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support multiple package in a single WIT source #1577
Support multiple package in a single WIT source #1577
Conversation
336123a
to
b4e83ed
Compare
I believe this is ready for review. Afaict, the failing tests are all failing on head, with the exception of |
Also worth noting for future reviewers: I realize this is a rather large PR, which I think is due to this change modifying a lot of internal APIs to be be vectors of |
Ah looks like we're getting bitten by a warning in a new Rust nightly, and I think this should be fixed by #1581
No worries! That comes with the territory of changes like this. I'll dig in today for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fantastic to me, thank you again so much for working on this! I'm definitely looking forward to being able to refactor tools to use this and take advantage of it. I think this is going to unlock some quite nice refactorings and downstream abilities of other tooling.
/// This is the path, within the `WIT` source provided as a positional argument, to the `world` | ||
/// that the core wasm module works with. This can either be a bare string which is a document | ||
/// name that has a `default world`, or it can be a `foo/bar` name where `foo` names a document | ||
/// and `bar` names a world within that document. If the `WIT` source provided contains multiple | ||
/// packages, this option must be set, and must be of the fully-qualified form (ex: | ||
/// "wasi:http/proxy") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're up for some extra edits much of this preexisting documentation was already wrong/outdated. For example default world
s were removed awhile ago. If you'd like I think it'd be reasonable to update this entirely in addition to the qualification you've added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tbh, I'm not entirely clear on which parts of this comment are no longer relevant, so I'm not totally comfortable making deletions :/ My knowledge of the existing state of the tooling still leaves a lot to be desired!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries! I'm happy to take a pass after this PR as well.
crates/wit-parser/src/resolve.rs
Outdated
last = Some(pkgid); | ||
} | ||
|
||
ret.push((last.unwrap(), files)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is me musing a bit here, but I wanted to highlight this a bit. No action needed in this PR, but figured I'd jot down my ideas.
Here the previous API returned the PackageId
of the "top" package. That's being much more ambiguous after this PR because the concept of a "top" package is sort of gone where the top thing might have a whole bunch of packages. Once we buy into the concept of multiple "top" packages then some other related issues like #1461 and #1462 become more digestable (IMO at least).
AFAIK the only downside to having multiple "top" packages is the "world selection" process. Currently that allows the shorthand of specifying a single foo
world name (or no name at all) and an appropriate world is selected. If we can reframe that functionality somehow to work with a set of "top" packages then it'd be pretty easy to implement those issues. That being said I don't know how best to rationalize how to select a world from a set of "top" packages.
I also bring this up because I can see here that maintaining a return value of the "top" packages is kinda awkward here and might be more awkward with one of my suggestions below of using append
here. Anyway just wanted to muse a bit here in case you were inspired by something and had an idea.
b73dbb8
to
7b36db9
Compare
Thanks for the thorough feedback @alexcrichton! I've squashed existing commits, merged onto HEAD, and fixed some of the more striaghtforward comments. I'll try to address the remainder over the weekend! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again for this! Just a few more minor things but other than that happy to land 👍
crates/wit-parser/src/resolve.rs
Outdated
let id = self.push_file(path)?; | ||
Ok((id, vec![path.to_path_buf()])) | ||
let ids = self.push_file(path)?; | ||
let mut pkg_ids = Vec::new(); | ||
let mut path_bufs = Vec::new(); | ||
for id in ids { | ||
pkg_ids.push(id); | ||
path_bufs.push(path.to_path_buf()); | ||
} | ||
Ok((pkg_ids, path_bufs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be able to stay roughly as it was before, except renaming id
to ids
? There's no need to ensure that the two vectors have the same length, it's just that the second vector is the set of files to produce the first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
crates/wit-parser/src/resolve.rs
Outdated
} | ||
} | ||
|
||
fn _sort_unresolved_packages( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's ok in general to skip the leading underscore for private methods in Rust since the visibility (or lack thereof here) covers that. Some of the other methods have this underscore prefix but that's just because the public and private versions both wanted to be called the same thing so I gave up on naming an gave the private one a leading _
. For this case specifically though it's ok to just call this sort_unresolved_packages
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
crates/wit-component/src/printing.rs
Outdated
writeln!(&mut self.output, "}}\n")?; | ||
} | ||
/// Print a set of one or more WIT packages into a string. | ||
pub fn print(&mut self, resolve: &Resolve, pkg_ids: Vec<PackageId>) -> Result<String> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me 👍
/// * If there is a single resolved package with multiple worlds, the world name MUST be supplied, | ||
/// but MAY or MAY NOT be fully-qualified. | ||
/// * If there are multiple resolved packages, the world name MUST be fully-qualified. | ||
pub fn resolve_world_from_name( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me 👍
Do not write with additional braces for single-file, multi-package format. WebAssembly/component-model#340 bytecodealliance/wasm-tools#1577
Do not write with additional braces for single-file, multi-package format. WebAssembly/component-model#340 bytecodealliance/wasm-tools#1577
Do not write with additional braces for single-file, multi-package format. WebAssembly/component-model#340 bytecodealliance/wasm-tools#1577
Do not write with additional braces for single-file, multi-package format. WebAssembly/component-model#340 bytecodealliance/wasm-tools#1577
This is a follow-up to bytecodealliance#1577 to refactor a bit to have bindings generators continue to use `Resolve::select_world` for figuring out what to generate bindings for.
* Fold `resolve_world_from_name` helper into `select_world` This is a follow-up to #1577 to refactor a bit to have bindings generators continue to use `Resolve::select_world` for figuring out what to generate bindings for. * Review comments and API changes * Rename `Resolve::append` to `Resolve::push_group` * Add `Resolve::push_str` * Change `&Path` arguments to `impl AsRef<Path>` * Fix fuzzer build
This commit changes the output of `wasm-tools component wit` to by default output all WIT packages using the multi-package syntax implemented in bytecodealliance#1577. This means that a complete view of the WIT will be seen when running this command instead of just the top-level world.
* Improve the `--out-dir` flag of `component wit` * Lift files in `deps` outside of their folders to be `deps/*.wit` instead of `deps/*/main.wit` since this structure is now supported. * Handle multi-package input documents by placing each package in the main folder. * Name the main wit file after the package name. * Add some tests for these cases. * Print all WIT packages by default This commit changes the output of `wasm-tools component wit` to by default output all WIT packages using the multi-package syntax implemented in #1577. This means that a complete view of the WIT will be seen when running this command instead of just the top-level world. * Fix build of fuzzer * Sanitize output to be more platform agnostic
This change implements the narrow version of the work proposed at WebAssembly/component-model#313, and added to the language specification in WebAssembly/component-model#340. Multiple packages may now be described in a single WIT file, also known as "explicit" package declaration (ie, a block scope for every package), in addition to the already support "implicit" mode (a single package, spread over one or more files, with no block scope at the top level).
Relevant tools, like
component embed
andcomponent semver-check
, have been updated and given tests where required.A great number of APIs that previously assumed that they would receive exactly one
Package
/PackageId
/other package-describing object, or aResult
thereof, now receive vectors of these objects. This spidered out to various call-sites and tools in a fairly broad manner. I've made an effort to have these tools gracefully handle multiple packages where necessary, or, in cases where the tool cannot accept multiple packages, gracefully fail on these sorts of inputs.The AST has been modified a good deal to accommodate these new changes. Specifically, the concept of a
DeclList
has been introduced, to contain all of the non-package
declarations in a package scope. At the top-level, the AST is now a union of either a list ofExplicitPackage
s or a singlePartialImplicitPackage
; we try to deduce which of these two modes the given WIT file is in as early as possible, so that we can properly establish scope and start building the relevant package-level/file-levelDeclList
, respectively. Care is taken throughout the parser to catch scenarios where the explicit and implicit styles have been mixed and return a descriptive error to the user explaining that this is not allowed.As of this PR, single packages written in the explicit style (
package my-only-package:-in-this-file { ... }
) are allowed. My feeling is that the parser should accept this, but a future linter should discourage it and "auto-unwrap" such spellings into the implicit style.