Skip to content
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

Merged
merged 11 commits into from
Jun 6, 2024

Conversation

azaslavsky
Copy link
Contributor

@azaslavsky azaslavsky commented May 26, 2024

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 and component 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 a Result 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 of ExplicitPackages or a single PartialImplicitPackage; 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-level DeclList, 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.

@azaslavsky azaslavsky marked this pull request as ready for review May 27, 2024 16:54
@azaslavsky
Copy link
Contributor Author

I believe this is ready for review.

Afaict, the failing tests are all failing on head, with the exception of Rustfmt. However, when I run cargo fmt locally it produces no changes, so I'm not sure where the difference in formatting settings may be occurring.

@azaslavsky
Copy link
Contributor Author

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 Package, rather than singletons. I've tried to make the individual commits meaningful in their own right, so they each have their own commit messages and so on. The first 11 commits in this PR can be reviewed in order if more bite-sized review chunks are desired.

@alexcrichton
Copy link
Member

Afaict, the failing tests are all failing on head

Ah looks like we're getting bitten by a warning in a new Rust nightly, and I think this should be fixed by #1581

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 Package, rather than singletons

No worries! That comes with the territory of changes like this. I'll dig in today for review.

Copy link
Member

@alexcrichton alexcrichton left a 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.

Comment on lines +210 to +248
/// 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")
Copy link
Member

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 worlds 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.

Copy link
Contributor Author

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!

Copy link
Member

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-smith/src/lib.rs Outdated Show resolved Hide resolved
crates/wit-parser/src/lib.rs Show resolved Hide resolved
crates/wit-parser/src/resolve.rs Outdated Show resolved Hide resolved
crates/wit-parser/src/resolve.rs Outdated Show resolved Hide resolved
crates/wit-parser/src/resolve.rs Outdated Show resolved Hide resolved
last = Some(pkgid);
}

ret.push((last.unwrap(), files));
Copy link
Member

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.

crates/wit-parser/src/decoding.rs Outdated Show resolved Hide resolved
crates/wit-parser/src/ast.rs Outdated Show resolved Hide resolved
crates/wit-parser/src/ast.rs Outdated Show resolved Hide resolved
@azaslavsky
Copy link
Contributor Author

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!

Copy link
Member

@alexcrichton alexcrichton left a 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 👍

Comment on lines 147 to 190
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))
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
}

fn _sort_unresolved_packages(
Copy link
Member

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

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> {
Copy link
Member

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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me 👍

@alexcrichton alexcrichton added this pull request to the merge queue Jun 6, 2024
Merged via the queue into bytecodealliance:main with commit 2728f93 Jun 6, 2024
25 checks passed
ydnar added a commit to bytecodealliance/go-modules that referenced this pull request Jun 8, 2024
ydnar added a commit to bytecodealliance/go-modules that referenced this pull request Jun 8, 2024
ydnar added a commit to bytecodealliance/go-modules that referenced this pull request Jun 9, 2024
Do not write with additional braces for single-file, multi-package format.

WebAssembly/component-model#340
bytecodealliance/wasm-tools#1577
ydnar added a commit to bytecodealliance/go-modules that referenced this pull request Jun 9, 2024
Do not write with additional braces for single-file, multi-package format.

WebAssembly/component-model#340
bytecodealliance/wasm-tools#1577
ydnar added a commit to bytecodealliance/go-modules that referenced this pull request Jun 11, 2024
ydnar added a commit to bytecodealliance/go-modules that referenced this pull request Jun 11, 2024
Do not write with additional braces for single-file, multi-package format.

WebAssembly/component-model#340
bytecodealliance/wasm-tools#1577
ydnar added a commit to bytecodealliance/go-modules that referenced this pull request Jun 11, 2024
Do not write with additional braces for single-file, multi-package format.

WebAssembly/component-model#340
bytecodealliance/wasm-tools#1577
alexcrichton added a commit to alexcrichton/wasm-tools that referenced this pull request Jun 11, 2024
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.
github-merge-queue bot pushed a commit that referenced this pull request Jun 11, 2024
* 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
alexcrichton added a commit to alexcrichton/wasm-tools that referenced this pull request Jul 9, 2024
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.
github-merge-queue bot pushed a commit that referenced this pull request Jul 11, 2024
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants