Change the name of wit-bindgen's host implementation traits. (#5890)

* Change the name of wit-bindgen's host implementation traits.

Instead of naming the host implementation trait something like
`wasi_filesystem::WasiFilesystem`, name it `wasi_filesystem::Host`, and
avoid using the identifier `Host` in other places.

This fixes a collision when generating bindings for the current
wasi-clock API, which contains an interface `wall-clock` which contains
a type `wall-clock`, which created a naming collision on the name
`WallClock`.

* Update tests to use the new trait name.

* Fix one more.

* Add the new test interface to the simple-wasi world.
This commit is contained in:
Dan Gohman
2023-02-27 15:14:55 -08:00
committed by GitHub
parent f2dce812c3
commit c19b742d1c
5 changed files with 36 additions and 20 deletions

View File

@@ -10,6 +10,12 @@ interface wasi-filesystem {
stat: func() -> result<descriptor-stat, errno> stat: func() -> result<descriptor-stat, errno>
} }
interface wall-clock {
record wall-clock {
}
}
default world wasi { default world wasi {
import wasi-filesystem: self.wasi-filesystem import wasi-filesystem: self.wasi-filesystem
import wall-clock: self.wall-clock
} }

View File

@@ -1,4 +1,4 @@
use crate::rust::{to_rust_ident, RustGenerator, TypeMode}; use crate::rust::{to_rust_ident, to_rust_upper_camel_case, RustGenerator, TypeMode};
use crate::types::{TypeInfo, Types}; use crate::types::{TypeInfo, Types};
use heck::*; use heck::*;
use std::collections::BTreeMap; use std::collections::BTreeMap;
@@ -162,7 +162,7 @@ impl Wasmtime {
gen.generate_trappable_error_types(TypeOwner::Interface(*id)); gen.generate_trappable_error_types(TypeOwner::Interface(*id));
let iface = &resolve.interfaces[*id]; let iface = &resolve.interfaces[*id];
let camel = name.to_upper_camel_case(); let camel = to_rust_upper_camel_case(name);
uwriteln!(gen.src, "pub struct {camel} {{"); uwriteln!(gen.src, "pub struct {camel} {{");
for (_, func) in iface.functions.iter() { for (_, func) in iface.functions.iter() {
uwriteln!( uwriteln!(
@@ -237,7 +237,7 @@ impl Wasmtime {
} }
fn finish(&mut self, resolve: &Resolve, world: WorldId) -> String { fn finish(&mut self, resolve: &Resolve, world: WorldId) -> String {
let camel = resolve.worlds[world].name.to_upper_camel_case(); let camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
uwriteln!(self.src, "pub struct {camel} {{"); uwriteln!(self.src, "pub struct {camel} {{");
for (name, (ty, _)) in self.exports.fields.iter() { for (name, (ty, _)) in self.exports.fields.iter() {
uwriteln!(self.src, "{name}: {ty},"); uwriteln!(self.src, "{name}: {ty},");
@@ -363,7 +363,7 @@ impl Wasmtime {
return; return;
} }
let world_camel = resolve.worlds[world].name.to_upper_camel_case(); let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
if self.opts.async_ { if self.opts.async_ {
uwriteln!(self.src, "#[wasmtime::component::__internal::async_trait]") uwriteln!(self.src, "#[wasmtime::component::__internal::async_trait]")
} }
@@ -401,11 +401,11 @@ impl Wasmtime {
where U: \ where U: \
" "
); );
let world_camel = resolve.worlds[world].name.to_upper_camel_case(); let world_camel = to_rust_upper_camel_case(&resolve.worlds[world].name);
let world_trait = format!("{world_camel}Imports"); let world_trait = format!("{world_camel}Imports");
for (i, name) in interfaces for (i, name) in interfaces
.iter() .iter()
.map(|n| format!("{n}::{}", n.to_upper_camel_case())) .map(|n| format!("{n}::Host"))
.chain(if functions.is_empty() { .chain(if functions.is_empty() {
None None
} else { } else {
@@ -591,7 +591,7 @@ impl<'a> InterfaceGenerator<'a> {
self.rustdoc(docs); self.rustdoc(docs);
self.src.push_str("wasmtime::component::flags!(\n"); self.src.push_str("wasmtime::component::flags!(\n");
self.src self.src
.push_str(&format!("{} {{\n", name.to_upper_camel_case())); .push_str(&format!("{} {{\n", to_rust_upper_camel_case(name)));
for flag in flags.flags.iter() { for flag in flags.flags.iter() {
// TODO wasmtime-component-macro doesnt support docs for flags rn // TODO wasmtime-component-macro doesnt support docs for flags rn
uwrite!( uwrite!(
@@ -657,7 +657,7 @@ impl<'a> InterfaceGenerator<'a> {
let info = self.info(id); let info = self.info(id);
for (name, mode) in self.modes_of(id) { for (name, mode) in self.modes_of(id) {
let name = name.to_upper_camel_case(); let name = to_rust_upper_camel_case(&name);
self.rustdoc(docs); self.rustdoc(docs);
let lt = self.lifetime_for(&info, mode); let lt = self.lifetime_for(&info, mode);
@@ -783,14 +783,14 @@ impl<'a> InterfaceGenerator<'a> {
fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) { fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
let info = self.info(id); let info = self.info(id);
let name = name.to_upper_camel_case(); let name = to_rust_upper_camel_case(name);
self.rustdoc(docs); self.rustdoc(docs);
self.push_str("#[derive(wasmtime::component::ComponentType)]\n"); self.push_str("#[derive(wasmtime::component::ComponentType)]\n");
self.push_str("#[derive(wasmtime::component::Lift)]\n"); self.push_str("#[derive(wasmtime::component::Lift)]\n");
self.push_str("#[derive(wasmtime::component::Lower)]\n"); self.push_str("#[derive(wasmtime::component::Lower)]\n");
self.push_str("#[component(enum)]\n"); self.push_str("#[component(enum)]\n");
self.push_str("#[derive(Clone, Copy, PartialEq, Eq)]\n"); self.push_str("#[derive(Clone, Copy, PartialEq, Eq)]\n");
self.push_str(&format!("pub enum {} {{\n", name.to_upper_camel_case())); self.push_str(&format!("pub enum {} {{\n", name));
for case in enum_.cases.iter() { for case in enum_.cases.iter() {
self.rustdoc(&case.docs); self.rustdoc(&case.docs);
self.push_str(&format!("#[component(name = \"{}\")]", case.name)); self.push_str(&format!("#[component(name = \"{}\")]", case.name));
@@ -953,7 +953,6 @@ impl<'a> InterfaceGenerator<'a> {
fn generate_add_to_linker(&mut self, id: InterfaceId, name: &str) { fn generate_add_to_linker(&mut self, id: InterfaceId, name: &str) {
let iface = &self.resolve.interfaces[id]; let iface = &self.resolve.interfaces[id];
let camel = name.to_upper_camel_case();
let owner = TypeOwner::Interface(id); let owner = TypeOwner::Interface(id);
if self.gen.opts.async_ { if self.gen.opts.async_ {
@@ -961,16 +960,16 @@ impl<'a> InterfaceGenerator<'a> {
} }
// Generate the `pub trait` which represents the host functionality for // Generate the `pub trait` which represents the host functionality for
// this import. // this import.
uwriteln!(self.src, "pub trait {camel}: Sized {{"); uwriteln!(self.src, "pub trait Host: Sized {{");
for (_, func) in iface.functions.iter() { for (_, func) in iface.functions.iter() {
self.generate_function_trait_sig(owner, func); self.generate_function_trait_sig(owner, func);
} }
uwriteln!(self.src, "}}"); uwriteln!(self.src, "}}");
let where_clause = if self.gen.opts.async_ { let where_clause = if self.gen.opts.async_ {
format!("T: Send, U: {camel} + Send") format!("T: Send, U: Host + Send")
} else { } else {
format!("U: {camel}") format!("U: Host")
}; };
uwriteln!( uwriteln!(
self.src, self.src,

View File

@@ -368,6 +368,7 @@ pub trait RustGenerator<'a> {
} }
} }
/// Translate `name` to a Rust `snake_case` identifier.
pub fn to_rust_ident(name: &str) -> String { pub fn to_rust_ident(name: &str) -> String {
match name { match name {
// Escape Rust keywords. // Escape Rust keywords.
@@ -425,3 +426,13 @@ pub fn to_rust_ident(name: &str) -> String {
s => s.to_snake_case(), s => s.to_snake_case(),
} }
} }
/// Translate `name` to a Rust `UpperCamelCase` identifier.
pub fn to_rust_upper_camel_case(name: &str) -> String {
match name {
// We use `Host` as the name of the trait for host implementations
// to fill in, so rename it if "Host" is used as a regular identifier.
"host" => "Host_".into(),
s => s.to_upper_camel_case(),
}
}

View File

@@ -97,7 +97,7 @@ mod one_import {
hit: bool, hit: bool,
} }
impl foo::Foo for MyImports { impl foo::Host for MyImports {
fn foo(&mut self) -> Result<()> { fn foo(&mut self) -> Result<()> {
self.hit = true; self.hit = true;
Ok(()) Ok(())

View File

@@ -60,7 +60,7 @@ mod empty_error {
#[derive(Default)] #[derive(Default)]
struct MyImports {} struct MyImports {}
impl imports::Imports for MyImports { impl imports::Host for MyImports {
fn empty_error(&mut self, a: f64) -> Result<Result<f64, ()>, Error> { fn empty_error(&mut self, a: f64) -> Result<Result<f64, ()>, Error> {
if a == 0.0 { if a == 0.0 {
Ok(Ok(a)) Ok(Ok(a))
@@ -171,7 +171,7 @@ mod string_error {
#[derive(Default)] #[derive(Default)]
struct MyImports {} struct MyImports {}
impl imports::Imports for MyImports { impl imports::Host for MyImports {
fn string_error(&mut self, a: f64) -> Result<Result<f64, String>, Error> { fn string_error(&mut self, a: f64) -> Result<Result<f64, String>, Error> {
if a == 0.0 { if a == 0.0 {
Ok(Ok(a)) Ok(Ok(a))
@@ -313,7 +313,7 @@ mod enum_error {
#[derive(Default)] #[derive(Default)]
struct MyImports {} struct MyImports {}
impl imports::Imports for MyImports { impl imports::Host for MyImports {
fn enum_error(&mut self, a: f64) -> Result<f64, imports::TrappableE1> { fn enum_error(&mut self, a: f64) -> Result<f64, imports::TrappableE1> {
if a == 0.0 { if a == 0.0 {
Ok(a) Ok(a)
@@ -440,7 +440,7 @@ mod record_error {
#[derive(Default)] #[derive(Default)]
struct MyImports {} struct MyImports {}
impl imports::Imports for MyImports { impl imports::Host for MyImports {
fn record_error(&mut self, a: f64) -> Result<f64, imports::TrappableE2> { fn record_error(&mut self, a: f64) -> Result<f64, imports::TrappableE2> {
if a == 0.0 { if a == 0.0 {
Ok(a) Ok(a)
@@ -576,7 +576,7 @@ mod variant_error {
#[derive(Default)] #[derive(Default)]
struct MyImports {} struct MyImports {}
impl imports::Imports for MyImports { impl imports::Host for MyImports {
fn variant_error(&mut self, a: f64) -> Result<f64, imports::TrappableE3> { fn variant_error(&mut self, a: f64) -> Result<f64, imports::TrappableE3> {
if a == 0.0 { if a == 0.0 {
Ok(a) Ok(a)