From 255fd6be0aae45ef6ca8e8158fe129cbd80d9a8d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 14 Feb 2023 14:54:37 -0600 Subject: [PATCH] Update world-selection in `bindgen!` macro (#5779) * Update world-selection in `bindgen!` macro Inspired by bytecodealliance/wit-bindgen#494 specifying a world or document to bindgen is now optional as it's inferred if there's only one `default world` in a package's documents. * Add cargo-vet entry --- Cargo.lock | 4 +- Cargo.toml | 2 +- crates/component-macro/src/bindgen.rs | 58 +++++-------------------- crates/component-macro/tests/codegen.rs | 6 ++- crates/wasmtime/src/component/mod.rs | 13 ++++-- supply-chain/audits.toml | 6 +++ 6 files changed, 34 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f2c64dbde..f908113083 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4110,9 +4110,9 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0fe225a32528b42a7037add1b5ed1dff83288f21a067007b34565ce87fc2c7" +checksum = "a84965789410bf21087f5a352703142f77b9b4d1478764c3f33a1ea8c7101f40" dependencies = [ "anyhow", "id-arena", diff --git a/Cargo.toml b/Cargo.toml index 9f66f48744..ed90c0d78c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -169,7 +169,7 @@ wasmprinter = "0.2.50" wasm-encoder = "0.23.0" wasm-smith = "0.12.1" wasm-mutate = "0.2.17" -wit-parser = "0.6.0" +wit-parser = "0.6.1" windows-sys = "0.45.0" env_logger = "0.9" rustix = "0.36.7" diff --git a/crates/component-macro/src/bindgen.rs b/crates/component-macro/src/bindgen.rs index d9caff8f32..c96e55e54b 100644 --- a/crates/component-macro/src/bindgen.rs +++ b/crates/component-macro/src/bindgen.rs @@ -46,14 +46,14 @@ impl Parse for Config { fn parse(input: ParseStream<'_>) -> Result { let call_site = Span::call_site(); let mut opts = Opts::default(); - let mut world = None; let mut source = None; + let mut world = None; - let document = if input.peek(token::Brace) { + if input.peek(token::Brace) { let content; syn::braced!(content in input); let fields = Punctuated::::parse_terminated(&content)?; - let mut document = None; + let mut world = None; for field in fields.into_pairs() { match field.into_value() { Opt::Path(s) => { @@ -63,10 +63,10 @@ impl Parse for Config { source = Some(Source::Path(s.value())); } Opt::World(s) => { - if document.is_some() { - return Err(Error::new(s.span(), "cannot specify second document")); + if world.is_some() { + return Err(Error::new(s.span(), "cannot specify second world")); } - document = Some(parse_doc(&s.value(), &mut world)); + world = Some(s.value()); } Opt::Inline(s) => { if source.is_some() { @@ -79,43 +79,17 @@ impl Parse for Config { Opt::TrappableErrorType(val) => opts.trappable_error_type = val, } } - match (document, &source) { - (Some(doc), _) => doc, - (None, Some(Source::Inline(_))) => "macro-input".to_string(), - _ => { - return Err(Error::new( - call_site, - "must specify a `world` to generate bindings for", - )) - } - } } else { - let document = input.parse::()?; + world = input.parse::>()?.map(|s| s.value()); if input.parse::>()?.is_some() { source = Some(Source::Path(input.parse::()?.value())); } - parse_doc(&document.value(), &mut world) - }; + } let (resolve, pkg, files) = parse_source(&source).map_err(|err| Error::new(call_site, format!("{err:?}")))?; - let doc = resolve.packages[pkg] - .documents - .get(&document) - .copied() - .ok_or_else(|| { - Error::new(call_site, format!("no document named `{document}` found")) - })?; - - let world = match &world { - Some(name) => resolve.documents[doc] - .worlds - .get(name) - .copied() - .ok_or_else(|| Error::new(call_site, format!("no world named `{name}` found")))?, - None => resolve.documents[doc].default_world.ok_or_else(|| { - Error::new(call_site, format!("no default world found in `{document}`")) - })?, - }; + let world = resolve + .select_world(pkg, world.as_deref()) + .map_err(|e| Error::new(call_site, format!("{e:?}")))?; Ok(Config { opts, resolve, @@ -152,16 +126,6 @@ fn parse_source(source: &Option) -> anyhow::Result<(Resolve, PackageId, Ok((resolve, pkg, files)) } -fn parse_doc(s: &str, world: &mut Option) -> String { - match s.find('.') { - Some(pos) => { - *world = Some(s[pos + 1..].to_string()); - s[..pos].to_string() - } - None => s.to_string(), - } -} - mod kw { syn::custom_keyword!(inline); syn::custom_keyword!(path); diff --git a/crates/component-macro/tests/codegen.rs b/crates/component-macro/tests/codegen.rs index 13d826a8dd..695f432fef 100644 --- a/crates/component-macro/tests/codegen.rs +++ b/crates/component-macro/tests/codegen.rs @@ -1,20 +1,22 @@ macro_rules! gentest { ($id:ident $name:tt $path:tt) => { mod $id { + mod sugar { + wasmtime::component::bindgen!(in $path); + } mod normal { wasmtime::component::bindgen!($name in $path); } mod async_ { wasmtime::component::bindgen!({ - world: $name, path: $path, async: true, }); } mod tracing { wasmtime::component::bindgen!({ - world: $name, path: $path, + world: $name, tracing: true, }); } diff --git a/crates/wasmtime/src/component/mod.rs b/crates/wasmtime/src/component/mod.rs index 3ff3e6e7bc..2b8430f47d 100644 --- a/crates/wasmtime/src/component/mod.rs +++ b/crates/wasmtime/src/component/mod.rs @@ -84,7 +84,7 @@ pub(crate) use self::store::ComponentStoreData; /// use wasmtime::component::*; /// use wasmtime::{Config, Engine, Store}; /// -/// bindgen!("my-component"); +/// bindgen!(); /// /// struct MyState { /// name: String, @@ -170,7 +170,7 @@ pub(crate) use self::store::ComponentStoreData; /// use wasmtime::component::*; /// use wasmtime::{Config, Engine, Store}; /// -/// bindgen!("my-component"); +/// bindgen!(); /// /// struct MyState { /// // ... @@ -223,6 +223,11 @@ pub(crate) use self::store::ComponentStoreData; /// /// ```rust,ignore /// // Parse the `wit/` folder adjacent to this crate's `Cargo.toml` and look +/// // for a `default world` in its documents. There must be exactly one +/// // `default world` for this to succeed. +/// bindgen!(); +/// +/// // Parse the `wit/` folder adjacent to this crate's `Cargo.toml` and look /// // for the document `foo`, which must have a `default world` contained /// // within it. /// bindgen!("foo"); @@ -232,6 +237,7 @@ pub(crate) use self::store::ComponentStoreData; /// bindgen!("foo.bar"); /// /// // Parse the folder `other/wit/folder` adjacent to `Cargo.toml`. +/// bindgen!(in "other/wit/folder"); /// bindgen!("foo" in "other/wit/folder"); /// bindgen!("foo.bar" in "other/wit/folder"); /// @@ -245,8 +251,9 @@ pub(crate) use self::store::ComponentStoreData; /// ```rust,ignore /// bindgen!({ /// world: "foo", // or "foo.bar", same as in `bindgen!("foo")` +/// // not needed if `path` has one `default world` /// -/// // same as in `bindgen!("foo" in "other/wit/folder") +/// // same as in `bindgen!(in "other/wit/folder") /// path: "other/wit/folder", /// /// // Instead of `path` the WIT document can be provided inline if diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index e1ff64eea6..52628504a2 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -1442,3 +1442,9 @@ criteria = "safe-to-deploy" version = "0.6.0" notes = "The Bytecode Alliance is the author of this crate." +[[audits.wit-parser]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.6.1" +notes = "The Bytecode Alliance is the author of this crate." +