Skip to content

Commit

Permalink
Rename generated structures to Guest in bindgen (#7794)
Browse files Browse the repository at this point in the history
This mirrors how traits for the host are all called `Host` and it avoids
name clashes with types that share the name of the interface they are in.

I've also added some simple debugging of macro-generated code to get
better error messages.

Closes #7775
  • Loading branch information
alexcrichton authored Jan 18, 2024
1 parent e5817d9 commit 38421d6
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 18 deletions.
5 changes: 5 additions & 0 deletions crates/component-macro/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
println!("cargo:rerun-if-changed=build.rs");
let out_dir = std::env::var("OUT_DIR").unwrap();
println!("cargo:rustc-env=DEBUG_OUTPUT_DIR={out_dir}");
}
27 changes: 26 additions & 1 deletion crates/component-macro/src/bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use quote::ToTokens;
use std::collections::HashMap;
use std::collections::HashSet;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::punctuated::Punctuated;
use syn::{braced, token, Token};
Expand All @@ -24,7 +25,31 @@ pub fn expand(input: &Config) -> Result<TokenStream> {
));
}

let src = input.opts.generate(&input.resolve, input.world);
let mut src = input.opts.generate(&input.resolve, input.world);

// If a magical `WASMTIME_DEBUG_BINDGEN` environment variable is set then
// place a formatted version of the expanded code into a file. This file
// will then show up in rustc error messages for any codegen issues and can
// be inspected manually.
if std::env::var("WASMTIME_DEBUG_BINDGEN").is_ok() {
static INVOCATION: AtomicUsize = AtomicUsize::new(0);
let root = Path::new(env!("DEBUG_OUTPUT_DIR"));
let world_name = &input.resolve.worlds[input.world].name;
let n = INVOCATION.fetch_add(1, Relaxed);
let path = root.join(format!("{world_name}{n}.rs"));

std::fs::write(&path, &src).unwrap();

// optimistically format the code but don't require success
drop(
std::process::Command::new("rustfmt")
.arg(&path)
.arg("--edition=2021")
.output(),
);

src = format!("include!({path:?});");
}
let mut contents = src.parse::<TokenStream>().unwrap();

// Include a dummy `include_str!` for any files we read so rustc knows that
Expand Down
10 changes: 10 additions & 0 deletions crates/component-macro/tests/codegen/wat.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package same:name;

interface this-name-is-duplicated {
resource this-name-is-duplicated {
}
}

world example {
export this-name-is-duplicated;
}
32 changes: 15 additions & 17 deletions crates/wit-bindgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,13 +362,13 @@ impl Wasmtime {
gen.gen.name_interface(resolve, *id, name, true);
gen.current_interface = Some((*id, name, true));
gen.types(*id);
let struct_name = "Guest";
let iface = &resolve.interfaces[*id];
let iface_name = match name {
WorldKey::Name(name) => name,
WorldKey::Interface(_) => iface.name.as_ref().unwrap(),
};
let camel = to_rust_upper_camel_case(iface_name);
uwriteln!(gen.src, "pub struct {camel} {{");
uwriteln!(gen.src, "pub struct {struct_name} {{");
for (_, func) in iface.functions.iter() {
uwriteln!(
gen.src,
Expand All @@ -378,13 +378,13 @@ impl Wasmtime {
}
uwriteln!(gen.src, "}}");

uwriteln!(gen.src, "impl {camel} {{");
uwriteln!(gen.src, "impl {struct_name} {{");
uwrite!(
gen.src,
"
pub fn new(
__exports: &mut wasmtime::component::ExportInstance<'_, '_>,
) -> wasmtime::Result<{camel}> {{
) -> wasmtime::Result<{struct_name}> {{
"
);
let mut fields = Vec::new();
Expand All @@ -393,7 +393,7 @@ impl Wasmtime {
uwriteln!(gen.src, "let {name} = {getter};");
fields.push(name);
}
uwriteln!(gen.src, "Ok({camel} {{");
uwriteln!(gen.src, "Ok({struct_name} {{");
for name in fields {
uwriteln!(gen.src, "{name},");
}
Expand Down Expand Up @@ -467,7 +467,7 @@ impl Wasmtime {
let (path, method_name) = match pkgname {
Some(pkgname) => (
format!(
"exports::{}::{}::{snake}::{camel}",
"exports::{}::{}::{snake}::{struct_name}",
pkgname.namespace.to_snake_case(),
self.name_package_module(resolve, iface.package.unwrap()),
),
Expand All @@ -477,7 +477,7 @@ impl Wasmtime {
self.name_package_module(resolve, iface.package.unwrap())
),
),
None => (format!("exports::{snake}::{camel}"), snake.clone()),
None => (format!("exports::{snake}::{struct_name}"), snake.clone()),
};
let getter = format!(
"\
Expand Down Expand Up @@ -519,7 +519,13 @@ impl Wasmtime {
self.toplevel_import_trait(resolve, world);

uwriteln!(self.src, "const _: () = {{");
uwriteln!(self.src, "use wasmtime::component::__internal::anyhow;");
uwriteln!(
self.src,
"
#[allow(unused_imports)]
use wasmtime::component::__internal::anyhow;
"
);

uwriteln!(self.src, "impl {camel} {{");
self.toplevel_add_to_linker(resolve, world);
Expand Down Expand Up @@ -1011,22 +1017,14 @@ impl<'a> InterfaceGenerator<'a> {

uwriteln!(self.src, "}}");
} else {
let iface_name = match self.current_interface.unwrap().1 {
WorldKey::Name(name) => name.to_upper_camel_case(),
WorldKey::Interface(i) => self.resolve.interfaces[*i]
.name
.as_ref()
.unwrap()
.to_upper_camel_case(),
};
self.rustdoc(docs);
uwriteln!(
self.src,
"
pub type {camel} = wasmtime::component::ResourceAny;
pub struct Guest{camel}<'a> {{
funcs: &'a {iface_name},
funcs: &'a Guest,
}}
"
);
Expand Down

0 comments on commit 38421d6

Please sign in to comment.