diff --git a/crates/component-macro/tests/codegen/function-new.wit b/crates/component-macro/tests/codegen/function-new.wit new file mode 100644 index 0000000000..fed79c6633 --- /dev/null +++ b/crates/component-macro/tests/codegen/function-new.wit @@ -0,0 +1,3 @@ +default world foo { + export new: func() +} diff --git a/crates/component-macro/tests/codegen/share-types.wit b/crates/component-macro/tests/codegen/share-types.wit new file mode 100644 index 0000000000..106ee70936 --- /dev/null +++ b/crates/component-macro/tests/codegen/share-types.wit @@ -0,0 +1,19 @@ +interface http-types{ + record request { + method: string + } + record response { + body: string + } +} + +default world http-interface { + export http-handler: interface { + use self.http-types.{request,response} + handle-request: func(request: request) -> response + } + import http-fetch: interface { + use self.http-types.{request,response} + fetch-request: func(request: request) -> response + } +} diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs index 3b01aad4aa..f08011fb55 100644 --- a/crates/wit-bindgen/src/lib.rs +++ b/crates/wit-bindgen/src/lib.rs @@ -101,7 +101,7 @@ impl Wasmtime { fn import(&mut self, resolve: &Resolve, name: &str, item: &WorldItem) { let snake = name.to_snake_case(); - let mut gen = InterfaceGenerator::new(self, resolve, TypeMode::Owned); + let mut gen = InterfaceGenerator::new(self, resolve); let import = match item { WorldItem::Function(func) => { gen.generate_function_trait_sig(TypeOwner::None, &func); @@ -139,7 +139,7 @@ impl Wasmtime { fn export(&mut self, resolve: &Resolve, name: &str, item: &WorldItem) { let snake = name.to_snake_case(); - let mut gen = InterfaceGenerator::new(self, resolve, TypeMode::AllBorrowed("'a")); + let mut gen = InterfaceGenerator::new(self, resolve); let (ty, getter) = match item { WorldItem::Function(func) => { gen.define_rust_guest_export(None, func); @@ -450,21 +450,15 @@ struct InterfaceGenerator<'a> { src: Source, gen: &'a mut Wasmtime, resolve: &'a Resolve, - default_param_mode: TypeMode, current_interface: Option, } impl<'a> InterfaceGenerator<'a> { - fn new( - gen: &'a mut Wasmtime, - resolve: &'a Resolve, - default_param_mode: TypeMode, - ) -> InterfaceGenerator<'a> { + fn new(gen: &'a mut Wasmtime, resolve: &'a Resolve) -> InterfaceGenerator<'a> { InterfaceGenerator { src: Source::default(), gen, resolve, - default_param_mode, current_interface: None, } } @@ -1159,7 +1153,7 @@ impl<'a> InterfaceGenerator<'a> { self.rustdoc(&func.docs); uwrite!( self.src, - "pub {async_} fn {}(&self, mut store: S, ", + "pub {async_} fn call_{}(&self, mut store: S, ", func.name.to_snake_case(), ); for (i, param) in func.params.iter().enumerate() { @@ -1351,10 +1345,6 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> { self.current_interface } - fn default_param_mode(&self) -> TypeMode { - self.default_param_mode - } - fn push_str(&mut self, s: &str) { self.src.push_str(s); } diff --git a/crates/wit-bindgen/src/rust.rs b/crates/wit-bindgen/src/rust.rs index bd936b0efc..7253106b3b 100644 --- a/crates/wit-bindgen/src/rust.rs +++ b/crates/wit-bindgen/src/rust.rs @@ -15,7 +15,6 @@ pub trait RustGenerator<'a> { fn push_str(&mut self, s: &str); fn info(&self, ty: TypeId) -> TypeInfo; - fn default_param_mode(&self) -> TypeMode; fn current_interface(&self) -> Option; fn print_ty(&mut self, ty: &Type, mode: TypeMode) { @@ -209,10 +208,10 @@ pub trait RustGenerator<'a> { fn modes_of(&self, ty: TypeId) -> Vec<(String, TypeMode)> { let info = self.info(ty); let mut result = Vec::new(); - if info.param { - result.push((self.param_name(ty), self.default_param_mode())); + if info.borrowed { + result.push((self.param_name(ty), TypeMode::AllBorrowed("'a"))); } - if info.result && (!info.param || self.uses_two_names(&info)) { + if info.owned && (!info.borrowed || self.uses_two_names(&info)) { result.push((self.result_name(ty), TypeMode::Owned)); } return result; @@ -358,13 +357,7 @@ pub trait RustGenerator<'a> { } fn uses_two_names(&self, info: &TypeInfo) -> bool { - info.has_list - && info.param - && info.result - && match self.default_param_mode() { - TypeMode::AllBorrowed(_) => true, - TypeMode::Owned => false, - } + info.has_list && info.borrowed && info.owned } fn lifetime_for(&self, info: &TypeInfo, mode: TypeMode) -> Option<&'static str> { diff --git a/crates/wit-bindgen/src/types.rs b/crates/wit-bindgen/src/types.rs index c449f513f9..4b2765f862 100644 --- a/crates/wit-bindgen/src/types.rs +++ b/crates/wit-bindgen/src/types.rs @@ -8,13 +8,14 @@ pub struct Types { #[derive(Default, Clone, Copy, Debug, PartialEq)] pub struct TypeInfo { - /// Whether or not this type is ever used (transitively) within the - /// parameter of a function. - pub param: bool, + /// Whether or not this type is ever used (transitively) within a borrowed + /// context, or a parameter to an export function. + pub borrowed: bool, - /// Whether or not this type is ever used (transitively) within the - /// result of a function. - pub result: bool, + /// Whether or not this type is ever used (transitively) within an owned + /// context, such as the result of an exported function or in the params or + /// results of an imported function. + pub owned: bool, /// Whether or not this type is ever used (transitively) within the /// error case in the result of a function. @@ -26,8 +27,8 @@ pub struct TypeInfo { impl std::ops::BitOrAssign for TypeInfo { fn bitor_assign(&mut self, rhs: Self) { - self.param |= rhs.param; - self.result |= rhs.result; + self.borrowed |= rhs.borrowed; + self.owned |= rhs.owned; self.error |= rhs.error; self.has_list |= rhs.has_list; } @@ -36,9 +37,14 @@ impl std::ops::BitOrAssign for TypeInfo { impl Types { pub fn analyze(&mut self, resolve: &Resolve, world: WorldId) { let world = &resolve.worlds[world]; - for (_, item) in world.imports.iter().chain(world.exports.iter()) { + for (import, (_, item)) in world + .imports + .iter() + .map(|i| (true, i)) + .chain(world.exports.iter().map(|i| (false, i))) + { match item { - WorldItem::Function(f) => self.type_info_func(resolve, f), + WorldItem::Function(f) => self.type_info_func(resolve, f, import), WorldItem::Interface(id) => { let iface = &resolve.interfaces[*id]; @@ -46,21 +52,26 @@ impl Types { self.type_id_info(resolve, *t); } for (_, f) in iface.functions.iter() { - self.type_info_func(resolve, f); + self.type_info_func(resolve, f, import); } } } } } - fn type_info_func(&mut self, resolve: &Resolve, func: &Function) { + fn type_info_func(&mut self, resolve: &Resolve, func: &Function, import: bool) { let mut live = LiveTypes::default(); for (_, ty) in func.params.iter() { self.type_info(resolve, ty); live.add_type(resolve, ty); } for id in live.iter() { - self.type_info.get_mut(&id).unwrap().param = true; + let info = self.type_info.get_mut(&id).unwrap(); + if import { + info.owned = true; + } else { + info.borrowed = true; + } } let mut live = LiveTypes::default(); for ty in func.results.iter_types() { @@ -68,7 +79,7 @@ impl Types { live.add_type(resolve, ty); } for id in live.iter() { - self.type_info.get_mut(&id).unwrap().result = true; + self.type_info.get_mut(&id).unwrap().owned = true; } for ty in func.results.iter_types() { diff --git a/tests/all/component_model/bindgen.rs b/tests/all/component_model/bindgen.rs index 8b41cb4854..ddadec8918 100644 --- a/tests/all/component_model/bindgen.rs +++ b/tests/all/component_model/bindgen.rs @@ -46,8 +46,8 @@ mod no_imports { let linker = Linker::new(&engine); let mut store = Store::new(&engine, ()); let (no_imports, _) = NoImports::instantiate(&mut store, &component, &linker)?; - no_imports.bar(&mut store)?; - no_imports.foo().foo(&mut store)?; + no_imports.call_bar(&mut store)?; + no_imports.foo().call_foo(&mut store)?; Ok(()) } } @@ -108,7 +108,7 @@ mod one_import { foo::add_to_linker(&mut linker, |f: &mut MyImports| f)?; let mut store = Store::new(&engine, MyImports::default()); let (one_import, _) = OneImport::instantiate(&mut store, &component, &linker)?; - one_import.bar(&mut store)?; + one_import.call_bar(&mut store)?; assert!(store.data().hit); Ok(()) } diff --git a/tests/all/component_model/bindgen/results.rs b/tests/all/component_model/bindgen/results.rs index 82e318948b..321eed9fdc 100644 --- a/tests/all/component_model/bindgen/results.rs +++ b/tests/all/component_model/bindgen/results.rs @@ -80,19 +80,22 @@ mod empty_error { assert_eq!( results - .empty_error(&mut store, 0.0) + .call_empty_error(&mut store, 0.0) .expect("no trap") .expect("no error returned"), 0.0 ); results - .empty_error(&mut store, 1.0) + .call_empty_error(&mut store, 1.0) .expect("no trap") .err() .expect("() error returned"); - let e = results.empty_error(&mut store, 2.0).err().expect("trap"); + let e = results + .call_empty_error(&mut store, 2.0) + .err() + .expect("trap"); assert_eq!( format!("{}", e.source().expect("trap message is stored in source")), "empty_error: trap" @@ -188,20 +191,23 @@ mod string_error { assert_eq!( results - .string_error(&mut store, 0.0) + .call_string_error(&mut store, 0.0) .expect("no trap") .expect("no error returned"), 0.0 ); let e = results - .string_error(&mut store, 1.0) + .call_string_error(&mut store, 1.0) .expect("no trap") .err() .expect("error returned"); assert_eq!(e, "string_error: error"); - let e = results.string_error(&mut store, 2.0).err().expect("trap"); + let e = results + .call_string_error(&mut store, 2.0) + .err() + .expect("trap"); assert_eq!( format!("{}", e.source().expect("trap message is stored in source")), "string_error: trap" @@ -328,7 +334,7 @@ mod enum_error { assert_eq!( results .foo() - .enum_error(&mut store, 0.0) + .call_enum_error(&mut store, 0.0) .expect("no trap") .expect("no error returned"), 0.0 @@ -336,7 +342,7 @@ mod enum_error { let e = results .foo() - .enum_error(&mut store, 1.0) + .call_enum_error(&mut store, 1.0) .expect("no trap") .err() .expect("error returned"); @@ -344,7 +350,7 @@ mod enum_error { let e = results .foo() - .enum_error(&mut store, 2.0) + .call_enum_error(&mut store, 2.0) .err() .expect("trap"); assert_eq!( @@ -458,7 +464,7 @@ mod record_error { assert_eq!( results .foo() - .record_error(&mut store, 0.0) + .call_record_error(&mut store, 0.0) .expect("no trap") .expect("no error returned"), 0.0 @@ -466,7 +472,7 @@ mod record_error { let e = results .foo() - .record_error(&mut store, 1.0) + .call_record_error(&mut store, 1.0) .expect("no trap") .err() .expect("error returned"); @@ -480,7 +486,7 @@ mod record_error { let e = results .foo() - .record_error(&mut store, 2.0) + .call_record_error(&mut store, 2.0) .err() .expect("trap"); assert_eq!( @@ -594,7 +600,7 @@ mod variant_error { assert_eq!( results .foo() - .variant_error(&mut store, 0.0) + .call_variant_error(&mut store, 0.0) .expect("no trap") .expect("no error returned"), 0.0 @@ -602,7 +608,7 @@ mod variant_error { let e = results .foo() - .variant_error(&mut store, 1.0) + .call_variant_error(&mut store, 1.0) .expect("no trap") .err() .expect("error returned"); @@ -616,7 +622,7 @@ mod variant_error { let e = results .foo() - .variant_error(&mut store, 2.0) + .call_variant_error(&mut store, 2.0) .err() .expect("trap"); assert_eq!(