From 5fd6ec4fad777ef8326472b3ceec86d25c0187e8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 4 Jun 2025 16:01:50 -0600 Subject: [PATCH 1/2] update `future.{write,read}` ABIs This updates the Rust generator to use the new ABI defined in https://github.com/WebAssembly/component-model/pull/524. The C generator will need a similar update as well. - `future.write` now accepts its payload value as up to 4 flat parameters before spilling to linear memory. - `future.read` takes no payload pointer when it has no payload type - `{stream,future}.close-{readable,writable}` have been renamed to `{stream,future}.drop-{readable,writable}` I've tested this end-to-end with `wasip3-prototyping` and will soon post a corresponding PR there. Finally, `rustfmt` was complaining about using `gen` as a field name, so I took this opportunity to address that. Signed-off-by: Joel Dice --- Cargo.lock | 76 ++--- Cargo.toml | 27 +- crates/c/src/lib.rs | 312 +++++++++--------- crates/core/src/abi.rs | 14 +- crates/guest-rust/rt/src/async_support.rs | 8 +- .../rt/src/async_support/abi_buffer.rs | 14 +- .../rt/src/async_support/future_support.rs | 161 +++++---- .../rt/src/async_support/stream_support.rs | 38 +-- crates/rust/src/interface.rs | 310 +++++++++++++---- .../async/cancel-import/runner.c | 18 +- .../async/cancel-import/runner.rs | 2 +- .../runtime-async/async/cancel-import/test.c | 4 +- .../async/future-cancel-read/runner.c | 12 +- .../async/future-cancel-read/test.c | 12 +- .../async/future-cancel-write/runner.c | 16 +- .../async/future-cancel-write/runner.rs | 10 +- .../async/future-cancel-write/test.c | 8 +- .../async/future-cancel-write/test.rs | 2 +- .../async/future-cancel-write/test.wit | 2 +- .../async/pending-import/runner.c | 4 +- .../runtime-async/async/pending-import/test.c | 4 +- tests/runtime-async/async/ping-pong/runner.c | 12 +- tests/runtime-async/async/ping-pong/test.c | 12 +- .../async/simple-future/runner.c | 10 +- .../async/simple-future/runner.rs | 2 +- .../runtime-async/async/simple-future/test.c | 12 +- .../runtime-async/async/simple-future/test.rs | 2 +- .../async/simple-future/test.wit | 2 +- .../async/simple-stream-payload/runner.c | 4 +- .../async/simple-stream-payload/runner.rs | 4 +- .../async/simple-stream-payload/test.c | 2 +- .../async/simple-stream-payload/test.rs | 2 +- .../async/simple-stream/runner.c | 6 +- .../async/simple-stream/runner.rs | 2 +- .../runtime-async/async/simple-stream/test.c | 2 +- 35 files changed, 671 insertions(+), 457 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8983c61d6..a2d07b730 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -819,7 +819,7 @@ name = "test-helpers" version = "0.0.0" dependencies = [ "codegen-macro", - "wasm-encoder 0.232.0", + "wasm-encoder 0.233.0", "wit-bindgen-core", "wit-component", "wit-parser", @@ -1002,9 +1002,8 @@ checksum = "ddbd7f2a9e3635abe5d4df93b12cadc8d6818079785ee4fab3719ae3c85a064e" [[package]] name = "wasm-compose" -version = "0.232.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d529e2655cd5722a1d21754386461502bf0b3d7a36657b3f16554a416ce4d401" +version = "0.233.0" +source = "git+https://github.com/bytecodealliance/wasm-tools#95f36d27a71c91cd210dd50bd5a26001875c61a4" dependencies = [ "anyhow", "heck 0.4.1", @@ -1016,8 +1015,8 @@ dependencies = [ "serde_derive", "serde_yaml", "smallvec", - "wasm-encoder 0.232.0", - "wasmparser 0.232.0", + "wasm-encoder 0.233.0", + "wasmparser 0.233.0", "wat", ] @@ -1032,12 +1031,11 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.232.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a447e61e38d1226b57e4628edadff36d16760be24a343712ba236b5106c95156" +version = "0.233.0" +source = "git+https://github.com/bytecodealliance/wasm-tools#95f36d27a71c91cd210dd50bd5a26001875c61a4" dependencies = [ "leb128fmt", - "wasmparser 0.232.0", + "wasmparser 0.233.0", ] [[package]] @@ -1058,14 +1056,13 @@ dependencies = [ [[package]] name = "wasm-metadata" -version = "0.232.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71aba7991cf9922a097b2dcc4c36ba5bc207339bdcd3a515530fc2555f01e8eb" +version = "0.233.0" +source = "git+https://github.com/bytecodealliance/wasm-tools#95f36d27a71c91cd210dd50bd5a26001875c61a4" dependencies = [ "anyhow", "indexmap", - "wasm-encoder 0.232.0", - "wasmparser 0.232.0", + "wasm-encoder 0.233.0", + "wasmparser 0.233.0", ] [[package]] @@ -1081,9 +1078,8 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.232.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917739b33bb1eb0e9a49bcd2637a351931be4578d0cc4d37b908d7a797784fbb" +version = "0.233.0" +source = "git+https://github.com/bytecodealliance/wasm-tools#95f36d27a71c91cd210dd50bd5a26001875c61a4" dependencies = [ "bitflags", "hashbrown", @@ -1094,22 +1090,20 @@ dependencies = [ [[package]] name = "wast" -version = "232.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5a22bfb0c309f5cf4b0cfa4fae77801e52570e88bff1344c1b7673a9977954" +version = "233.0.0" +source = "git+https://github.com/bytecodealliance/wasm-tools#95f36d27a71c91cd210dd50bd5a26001875c61a4" dependencies = [ "bumpalo", "leb128fmt", "memchr", "unicode-width 0.2.0", - "wasm-encoder 0.232.0", + "wasm-encoder 0.233.0", ] [[package]] name = "wat" -version = "1.232.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2054d3da4289c8634a6ed0dd177e066518f45772c521b6959f5d6109f4c210" +version = "1.233.0" +source = "git+https://github.com/bytecodealliance/wasm-tools#95f36d27a71c91cd210dd50bd5a26001875c61a4" dependencies = [ "wast", ] @@ -1212,8 +1206,8 @@ dependencies = [ "clap", "heck 0.5.0", "indexmap", - "wasm-encoder 0.232.0", - "wasm-metadata 0.232.0", + "wasm-encoder 0.233.0", + "wasm-metadata 0.233.0", "wit-bindgen-core", "wit-component", ] @@ -1225,7 +1219,7 @@ dependencies = [ "anyhow", "clap", "env_logger", - "wasm-encoder 0.232.0", + "wasm-encoder 0.233.0", "wit-bindgen-c", "wit-bindgen-core", "wit-bindgen-csharp", @@ -1255,7 +1249,7 @@ dependencies = [ "clap", "heck 0.5.0", "indexmap", - "wasm-metadata 0.232.0", + "wasm-metadata 0.233.0", "wit-bindgen-core", "wit-component", "wit-parser", @@ -1305,7 +1299,7 @@ dependencies = [ "serde_json", "syn", "test-helpers", - "wasm-metadata 0.232.0", + "wasm-metadata 0.233.0", "wit-bindgen", "wit-bindgen-core", "wit-bindgen-rt", @@ -1343,8 +1337,8 @@ dependencies = [ "wac-types", "wasi-preview1-component-adapter-provider", "wasm-compose", - "wasm-encoder 0.232.0", - "wasmparser 0.232.0", + "wasm-encoder 0.233.0", + "wasmparser 0.233.0", "wat", "wit-bindgen-csharp", "wit-component", @@ -1353,9 +1347,8 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.232.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1d7a3444f5039b4461a66dc085d749a832e518a86e8c7498d6fdd9df776ed0" +version = "0.233.0" +source = "git+https://github.com/bytecodealliance/wasm-tools#95f36d27a71c91cd210dd50bd5a26001875c61a4" dependencies = [ "anyhow", "bitflags", @@ -1364,18 +1357,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.232.0", - "wasm-metadata 0.232.0", - "wasmparser 0.232.0", + "wasm-encoder 0.233.0", + "wasm-metadata 0.233.0", + "wasmparser 0.233.0", "wat", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.232.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00a0e031533e3f9082057b09b346f76d3af12a714feccbe8d32f926254319d86" +version = "0.233.0" +source = "git+https://github.com/bytecodealliance/wasm-tools#95f36d27a71c91cd210dd50bd5a26001875c61a4" dependencies = [ "anyhow", "id-arena", @@ -1386,5 +1378,5 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.232.0", + "wasmparser 0.233.0", ] diff --git a/Cargo.toml b/Cargo.toml index c65ed3738..b7f4b5307 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,13 +31,13 @@ prettyplease = "0.2.20" syn = { version = "2.0.89", features = ["printing"] } futures = "0.3.31" -wat = "1.232.0" -wasmparser = "0.232.0" -wasm-encoder = "0.232.0" -wasm-metadata = { version = "0.232.0", default-features = false } -wit-parser = "0.232.0" -wit-component = "0.232.0" -wasm-compose = "0.232.0" +wat = "1.233.0" +wasmparser = "0.233.0" +wasm-encoder = "0.233.0" +wasm-metadata = { version = "0.233.0", default-features = false } +wit-parser = "0.233.0" +wit-component = "0.233.0" +wasm-compose = "0.233.0" wit-bindgen-core = { path = 'crates/core', version = '0.42.1' } wit-bindgen-c = { path = 'crates/c', version = '0.42.1' } @@ -83,3 +83,16 @@ csharp = ['dep:wit-bindgen-csharp'] csharp-mono = ['csharp'] moonbit = ['dep:wit-bindgen-moonbit'] async = [] + +# TODO: remove this once +# https://github.com/bytecodealliance/wasm-tools/pull/2222 is included in a +# `wasm-tools` release: +[patch.crates-io] +wasmparser = { git = "https://github.com/bytecodealliance/wasm-tools" } +wat = { git = "https://github.com/bytecodealliance/wasm-tools" } +wast = { git = "https://github.com/bytecodealliance/wasm-tools" } +wasm-encoder = { git = "https://github.com/bytecodealliance/wasm-tools" } +wit-parser = { git = "https://github.com/bytecodealliance/wasm-tools" } +wit-component = { git = "https://github.com/bytecodealliance/wasm-tools" } +wasm-compose = { git = "https://github.com/bytecodealliance/wasm-tools" } +wasm-metadata = { git = "https://github.com/bytecodealliance/wasm-tools" } diff --git a/crates/c/src/lib.rs b/crates/c/src/lib.rs index 59efc99aa..c95319e4d 100644 --- a/crates/c/src/lib.rs +++ b/crates/c/src/lib.rs @@ -201,20 +201,20 @@ impl WorldGenerator for C { _files: &mut Files, ) -> Result<()> { let wasm_import_module = resolve.name_world_key(name); - let mut gen = self.interface(resolve, true, Some(&wasm_import_module)); - gen.interface = Some((id, name)); - gen.define_interface_types(id); + let mut r#gen = self.interface(resolve, true, Some(&wasm_import_module)); + r#gen.interface = Some((id, name)); + r#gen.define_interface_types(id); for (i, (_name, func)) in resolve.interfaces[id].functions.iter().enumerate() { if i == 0 { let name = resolve.name_world_key(name); - uwriteln!(gen.src.h_fns, "\n// Imported Functions from `{name}`"); - uwriteln!(gen.src.c_fns, "\n// Imported Functions from `{name}`"); + uwriteln!(r#gen.src.h_fns, "\n// Imported Functions from `{name}`"); + uwriteln!(r#gen.src.c_fns, "\n// Imported Functions from `{name}`"); } - gen.import(Some(name), func); + r#gen.import(Some(name), func); } - gen.gen.src.append(&gen.src); + r#gen.r#gen.src.append(&r#gen.src); Ok(()) } @@ -227,18 +227,18 @@ impl WorldGenerator for C { _files: &mut Files, ) { let name = &resolve.worlds[world].name; - let mut gen = self.interface(resolve, true, Some("$root")); - gen.define_function_types(funcs); + let mut r#gen = self.interface(resolve, true, Some("$root")); + r#gen.define_function_types(funcs); for (i, (_name, func)) in funcs.iter().enumerate() { if i == 0 { - uwriteln!(gen.src.h_fns, "\n// Imported Functions from `{name}`"); - uwriteln!(gen.src.c_fns, "\n// Imported Functions from `{name}`"); + uwriteln!(r#gen.src.h_fns, "\n// Imported Functions from `{name}`"); + uwriteln!(r#gen.src.c_fns, "\n// Imported Functions from `{name}`"); } - gen.import(None, func); + r#gen.import(None, func); } - gen.gen.src.append(&gen.src); + r#gen.r#gen.src.append(&r#gen.src); } fn export_interface( @@ -248,20 +248,20 @@ impl WorldGenerator for C { id: InterfaceId, _files: &mut Files, ) -> Result<()> { - let mut gen = self.interface(resolve, false, None); - gen.interface = Some((id, name)); - gen.define_interface_types(id); + let mut r#gen = self.interface(resolve, false, None); + r#gen.interface = Some((id, name)); + r#gen.define_interface_types(id); for (i, (_name, func)) in resolve.interfaces[id].functions.iter().enumerate() { if i == 0 { let name = resolve.name_world_key(name); - uwriteln!(gen.src.h_fns, "\n// Exported Functions from `{name}`"); - uwriteln!(gen.src.c_fns, "\n// Exported Functions from `{name}`"); + uwriteln!(r#gen.src.h_fns, "\n// Exported Functions from `{name}`"); + uwriteln!(r#gen.src.c_fns, "\n// Exported Functions from `{name}`"); } - gen.export(func, Some(name)); + r#gen.export(func, Some(name)); } - gen.gen.src.append(&gen.src); + r#gen.r#gen.src.append(&r#gen.src); Ok(()) } @@ -273,18 +273,18 @@ impl WorldGenerator for C { _files: &mut Files, ) -> Result<()> { let name = &resolve.worlds[world].name; - let mut gen = self.interface(resolve, false, None); - gen.define_function_types(funcs); + let mut r#gen = self.interface(resolve, false, None); + r#gen.define_function_types(funcs); for (i, (_name, func)) in funcs.iter().enumerate() { if i == 0 { - uwriteln!(gen.src.h_fns, "\n// Exported Functions from `{name}`"); - uwriteln!(gen.src.c_fns, "\n// Exported Functions from `{name}`"); + uwriteln!(r#gen.src.h_fns, "\n// Exported Functions from `{name}`"); + uwriteln!(r#gen.src.c_fns, "\n// Exported Functions from `{name}`"); } - gen.export(func, None); + r#gen.export(func, None); } - gen.gen.src.append(&gen.src); + r#gen.r#gen.src.append(&r#gen.src); Ok(()) } @@ -295,13 +295,13 @@ impl WorldGenerator for C { types: &[(&str, TypeId)], _files: &mut Files, ) { - let mut gen = self.interface(resolve, true, Some("$root")); + let mut r#gen = self.interface(resolve, true, Some("$root")); let mut live = LiveTypes::default(); for (_, id) in types { live.add_type_id(resolve, *id); } - gen.define_live_types(live); - gen.gen.src.append(&gen.src); + r#gen.define_live_types(live); + r#gen.r#gen.src.append(&r#gen.src); } fn finish(&mut self, resolve: &Resolve, id: WorldId, files: &mut Files) -> Result<()> { @@ -563,7 +563,7 @@ impl C { ) -> InterfaceGenerator<'a> { InterfaceGenerator { src: Source::default(), - gen: self, + r#gen: self, resolve, interface: None, in_import, @@ -750,7 +750,7 @@ typedef uint32_t {snake}_waitable_status_t; typedef enum {snake}_waitable_state {{ {shouty}_WAITABLE_COMPLETED, - {shouty}_WAITABLE_CLOSED, + {shouty}_WAITABLE_DROPPED, {shouty}_WAITABLE_CANCELLED, }} {snake}_waitable_state_t; @@ -1117,7 +1117,7 @@ pub fn c_func_name( struct InterfaceGenerator<'a> { src: Source, in_import: bool, - gen: &'a mut C, + r#gen: &'a mut C, resolve: &'a Resolve, interface: Option<(InterfaceId, &'a WorldKey)>, wasm_import_module: Option<&'a str>, @@ -1334,7 +1334,7 @@ extern {borrow} {ns}_borrow_{snake}({own} handle); // will be required to fill in. This is an empty struct. self.src.h_defs("\n"); self.src.h_defs("typedef struct "); - let ty_name = self.gen.type_names[&id].clone(); + let ty_name = self.r#gen.type_names[&id].clone(); self.src.h_defs(&ty_name); self.src.h_defs(" "); self.print_typedef_target(id); @@ -1387,7 +1387,7 @@ void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{ )); } - self.gen.resources.insert( + self.r#gen.resources.insert( id, ResourceInfo { own, @@ -1586,7 +1586,7 @@ impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a> let resource = match handle { Handle::Borrow(id) | Handle::Own(id) => id, }; - let info = &self.gen.resources[&dealias(self.resolve, *resource)]; + let info = &self.r#gen.resources[&dealias(self.resolve, *resource)]; match handle { Handle::Borrow(_) => self.src.h_defs(&info.borrow), Handle::Own(_) => self.src.h_defs(&info.own), @@ -1599,7 +1599,7 @@ impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a> self.src.h_defs("\ntypedef "); self.src.h_defs("struct {\n"); for (i, t) in ty.types.iter().enumerate() { - let ty = self.gen.type_name(t); + let ty = self.r#gen.type_name(t); uwriteln!(self.src.h_defs, "{ty} f{i};"); } self.src.h_defs("}"); @@ -1611,7 +1611,7 @@ impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a> self.src.h_defs("\ntypedef "); self.src.h_defs("struct {\n"); self.src.h_defs("bool is_some;\n"); - let ty = self.gen.type_name(ty); + let ty = self.r#gen.type_name(ty); uwriteln!(self.src.h_defs, "{ty} val;"); self.src.h_defs("}"); self.src.h_defs(" "); @@ -1630,11 +1630,11 @@ impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a> if ok_ty.is_some() || err_ty.is_some() { self.src.h_defs("union {\n"); if let Some(ok) = ok_ty { - let ty = self.gen.type_name(ok); + let ty = self.r#gen.type_name(ok); uwriteln!(self.src.h_defs, "{ty} ok;"); } if let Some(err) = err_ty { - let ty = self.gen.type_name(err); + let ty = self.r#gen.type_name(err); uwriteln!(self.src.h_defs, "{ty} err;"); } self.src.h_defs("} val;\n"); @@ -1647,7 +1647,7 @@ impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a> fn anonymous_type_list(&mut self, id: TypeId, ty: &Type, _docs: &Docs) { self.src.h_defs("\ntypedef "); self.src.h_defs("struct {\n"); - let ty = self.gen.type_name(ty); + let ty = self.r#gen.type_name(ty); uwriteln!(self.src.h_defs, "{ty} *ptr;"); self.src.h_defs("size_t len;\n"); self.src.h_defs("}"); @@ -1710,7 +1710,7 @@ impl InterfaceGenerator<'_> { fn define_live_types(&mut self, live: LiveTypes) { for ty in live.iter() { - if self.gen.type_names.contains_key(&ty) { + if self.r#gen.type_names.contains_key(&ty) { continue; } @@ -1718,7 +1718,7 @@ impl InterfaceGenerator<'_> { match info { CTypeNameInfo::Named { name } => { let typedef_name = format!("{}_{encoded}_t", self.owner_namespace(ty)); - let prev = self.gen.type_names.insert(ty, typedef_name.clone()); + let prev = self.r#gen.type_names.insert(ty, typedef_name.clone()); assert!(prev.is_none()); self.define_type(name, ty) @@ -1726,16 +1726,16 @@ impl InterfaceGenerator<'_> { CTypeNameInfo::Anonymous { is_prim } => { let (defined, name) = if is_prim { - let namespace = self.gen.world.to_snake_case(); + let namespace = self.r#gen.world.to_snake_case(); let name = format!("{namespace}_{encoded}_t"); - let new_prim = self.gen.prim_names.insert(name.clone()); + let new_prim = self.r#gen.prim_names.insert(name.clone()); (!new_prim, name) } else { let namespace = self.owner_namespace(ty); (false, format!("{namespace}_{encoded}_t")) }; - let prev = self.gen.type_names.insert(ty, name); + let prev = self.r#gen.type_names.insert(ty, name); assert!(prev.is_none()); if defined { @@ -1765,7 +1765,7 @@ impl InterfaceGenerator<'_> { let h_helpers_start = self.src.h_helpers.len(); let c_helpers_start = self.src.c_helpers.len(); - let name = self.gen.type_names[&id].clone(); + let name = self.r#gen.type_names[&id].clone(); let prefix = name.strip_suffix("_t").unwrap(); self.src @@ -1795,7 +1795,7 @@ impl InterfaceGenerator<'_> { self.src.c_helpers("size_t list_len = ptr->len;\n"); uwriteln!(self.src.c_helpers, "if (list_len > 0) {{"); let mut t_name = String::new(); - self.gen.push_type_name(t, &mut t_name); + self.r#gen.push_type_name(t, &mut t_name); self.src .c_helpers(&format!("{t_name} *list_ptr = ptr->ptr;\n")); self.src @@ -1853,18 +1853,18 @@ impl InterfaceGenerator<'_> { return; } self.src.c_helpers("}\n"); - self.gen.dtor_funcs.insert(id, format!("{prefix}_free")); + self.r#gen.dtor_funcs.insert(id, format!("{prefix}_free")); } fn free(&mut self, ty: &Type, expr: &str) { match ty { Type::Id(id) => { - if let Some(dtor) = self.gen.dtor_funcs.get(&id) { + if let Some(dtor) = self.r#gen.dtor_funcs.get(&id) { self.src.c_helpers(&format!("{dtor}({expr});\n")); } } Type::String => { - let snake = self.gen.world.to_snake_case(); + let snake = self.r#gen.world.to_snake_case(); self.src .c_helpers(&format!("{snake}_string_free({expr});\n")); } @@ -1888,21 +1888,21 @@ impl InterfaceGenerator<'_> { c_func_name( self.in_import, self.resolve, - &self.gen.world, + &self.r#gen.world, interface_id, func, - &self.gen.renamed_interfaces, + &self.r#gen.renamed_interfaces, ) } fn import(&mut self, interface_name: Option<&WorldKey>, func: &Function) { let async_ = self - .gen + .r#gen .opts .async_ .is_async(self.resolve, interface_name, func, true); if async_ { - self.gen.needs_async = true; + self.r#gen.needs_async = true; } self.docs(&func.docs, SourceType::HFns); @@ -1928,7 +1928,7 @@ impl InterfaceGenerator<'_> { func.name ); let name = self.c_func_name(interface_name, func); - let import_name = self.gen.names.tmp(&format!("__wasm_import_{name}",)); + let import_name = self.r#gen.names.tmp(&format!("__wasm_import_{name}",)); self.src.c_fns("extern "); match sig.results.len() { 0 => self.src.c_fns("void"), @@ -1972,12 +1972,12 @@ impl InterfaceGenerator<'_> { // construct optional adapters from maybe pointers to real optional // structs internally let mut optional_adapters = String::from(""); - if !self.gen.opts.no_sig_flattening { + if !self.r#gen.opts.no_sig_flattening { for (i, (_, param)) in c_sig.params.iter().enumerate() { let ty = &func.params[i].1; if let Type::Id(id) = ty { if let TypeDefKind::Option(_) = &self.resolve.types[*id].kind { - let ty = self.gen.type_name(ty); + let ty = self.r#gen.type_name(ty); uwrite!( optional_adapters, "{ty} {param}; @@ -2007,7 +2007,7 @@ impl InterfaceGenerator<'_> { } f.src.push_str(&optional_adapters); abi::call( - f.gen.resolve, + f.r#gen.resolve, AbiVariant::GuestImport, LiftLower::LowerArgsLiftResults, func, @@ -2050,9 +2050,9 @@ impl InterfaceGenerator<'_> { let mut f = FunctionBindgen::new(self, c_sig.clone(), "INVALID"); for (i, (_, ty)) in func.params.iter().enumerate() { let param = &c_sig.params[i].1; - params.extend(abi::lower_flat(f.gen.resolve, &mut f, param.clone(), ty)); + params.extend(abi::lower_flat(f.r#gen.resolve, &mut f, param.clone(), ty)); } - f.gen.src.c_adapters.push_str(&f.src); + f.r#gen.src.c_adapters.push_str(&f.src); } if func.result.is_some() { params.push(format!("(uint8_t*) {}", c_sig.params.last().unwrap().1)); @@ -2066,13 +2066,13 @@ impl InterfaceGenerator<'_> { fn export(&mut self, func: &Function, interface_name: Option<&WorldKey>) { let async_ = self - .gen + .r#gen .opts .async_ .is_async(self.resolve, interface_name, func, false); let (variant, prefix) = if async_ { - self.gen.needs_async = true; + self.r#gen.needs_async = true; (AbiVariant::GuestExportAsync, "[async-lift]") } else { (AbiVariant::GuestExport, "") @@ -2096,33 +2096,33 @@ impl InterfaceGenerator<'_> { "\n__attribute__((__export_name__(\"{prefix}{export_name}\")))" ); let name = self.c_func_name(interface_name, func); - let import_name = self.gen.names.tmp(&format!("__wasm_export_{name}")); + let import_name = self.r#gen.names.tmp(&format!("__wasm_export_{name}")); let mut f = FunctionBindgen::new(self, h_sig, &import_name); match sig.results.len() { - 0 => f.gen.src.c_adapters("void"), - 1 => f.gen.src.c_adapters(wasm_type(sig.results[0])), + 0 => f.r#gen.src.c_adapters("void"), + 1 => f.r#gen.src.c_adapters(wasm_type(sig.results[0])), _ => unimplemented!("multi-value return not supported"), } - f.gen.src.c_adapters(" "); - f.gen.src.c_adapters(&import_name); - f.gen.src.c_adapters("("); + f.r#gen.src.c_adapters(" "); + f.r#gen.src.c_adapters(&import_name); + f.r#gen.src.c_adapters("("); for (i, param) in sig.params.iter().enumerate() { if i > 0 { - f.gen.src.c_adapters(", "); + f.r#gen.src.c_adapters(", "); } let name = f.locals.tmp("arg"); - uwrite!(f.gen.src.c_adapters, "{} {}", wasm_type(*param), name); + uwrite!(f.r#gen.src.c_adapters, "{} {}", wasm_type(*param), name); f.params.push(name); } if sig.params.len() == 0 { - f.gen.src.c_adapters("void"); + f.r#gen.src.c_adapters("void"); } - f.gen.src.c_adapters(") {\n"); + f.r#gen.src.c_adapters(") {\n"); // Perform all lifting/lowering and append it to our src. abi::call( - f.gen.resolve, + f.r#gen.resolve, variant, LiftLower::LiftArgsLowerResults, func, @@ -2138,9 +2138,9 @@ impl InterfaceGenerator<'_> { self.src.c_adapters("}\n"); if async_ { - let snake = self.gen.world.to_snake_case(); + let snake = self.r#gen.world.to_snake_case(); let return_ty = match &func.result { - Some(ty) => format!("{} ret", self.gen.type_name(ty)), + Some(ty) => format!("{} ret", self.r#gen.type_name(ty)), None => "void".to_string(), }; let DeferredTaskReturn::Emitted { @@ -2217,7 +2217,7 @@ void {name}_return({return_ty}) {{ let mut f = FunctionBindgen::new(self, c_sig, &import_name); f.params = params; - abi::post_return(f.gen.resolve, func, &mut f); + abi::post_return(f.r#gen.resolve, func, &mut f); let FunctionBindgen { src, .. } = f; self.src.c_fns(&src); self.src.c_fns("}\n"); @@ -2234,7 +2234,7 @@ void {name}_return({return_ty}) {{ async_: bool, ) -> CSig { let name = self.c_func_name(interface_name, func); - self.gen.names.insert(&name).expect("duplicate symbols"); + self.r#gen.names.insert(&name).expect("duplicate symbols"); let start = self.src.h_fns.len(); let mut result_rets = false; @@ -2249,7 +2249,7 @@ void {name}_return({return_ty}) {{ self.classify_ret(func) }; if async_ { - let snake = self.gen.world.to_snake_case(); + let snake = self.r#gen.world.to_snake_case(); if self.in_import { uwrite!(self.src.h_fns, "{snake}_subtask_status_t"); } else { @@ -2328,7 +2328,7 @@ void {name}_return({return_ty}) {{ // optional param pointer sig_flattening let optional_type = if let Type::Id(id) = ty { if let TypeDefKind::Option(option_ty) = &self.resolve.types[*id].kind { - if !self.gen.opts.no_sig_flattening { + if !self.r#gen.opts.no_sig_flattening { Some(option_ty) } else { None @@ -2339,7 +2339,7 @@ void {name}_return({return_ty}) {{ } else { None }; - let (print_ty, print_name) = if !self.gen.opts.no_sig_flattening { + let (print_ty, print_name) = if !self.r#gen.opts.no_sig_flattening { if let Some(option_ty) = optional_type { (option_ty, format!("maybe_{}", to_c_ident(name))) } else { @@ -2382,7 +2382,7 @@ void {name}_return({return_ty}) {{ printed = true; let names = multiple .iter() - .map(|(name, ty)| (to_c_ident(name), self.gen.type_name(ty))) + .map(|(name, ty)| (to_c_ident(name), self.r#gen.type_name(ty))) .collect::>(); uwriteln!(self.src.h_defs, "typedef struct {c_func_name}_args {{"); for (name, ty) in names { @@ -2430,20 +2430,20 @@ void {name}_return({return_ty}) {{ match &func.result { None => ret.scalar = Some(Scalar::Void), Some(ty) => { - ret.return_single(self.resolve, ty, ty, !self.gen.opts.no_sig_flattening); + ret.return_single(self.resolve, ty, ty, !self.r#gen.opts.no_sig_flattening); } } return ret; } fn print_typedef_target(&mut self, id: TypeId) { - let name = &self.gen.type_names[&id]; + let name = &self.r#gen.type_names[&id]; self.src.h_defs(&name); self.src.h_defs(";\n"); } fn start_typedef_struct(&mut self, id: TypeId) { - let name = &self.gen.type_names[&id]; + let name = &self.r#gen.type_names[&id]; self.src.h_defs("typedef struct "); self.src.h_defs(&name); self.src.h_defs(" {\n"); @@ -2458,15 +2458,15 @@ void {name}_return({return_ty}) {{ owner_namespace( self.interface, self.in_import, - self.gen.world.clone(), + self.r#gen.world.clone(), self.resolve, id, - &self.gen.renamed_interfaces, + &self.r#gen.renamed_interfaces, ) } fn print_ty(&mut self, stype: SourceType, ty: &Type) { - self.gen + self.r#gen .push_type_name(ty, self.src.src(stype).as_mut_string()); } @@ -2484,7 +2484,7 @@ void {name}_return({return_ty}) {{ } fn autodrop_enabled(&self) -> bool { - self.gen.opts.autodrop_borrows == Enabled::Yes + self.r#gen.opts.autodrop_borrows == Enabled::Yes } fn contains_droppable_borrow(&self, ty: &Type) -> bool { @@ -2496,7 +2496,7 @@ void {name}_return({return_ty}) {{ Handle::Borrow(id) => { !self.in_import && matches!( - self.gen.resources[&dealias(self.resolve, *id)].direction, + self.r#gen.resources[&dealias(self.resolve, *id)].direction, Direction::Import ) } @@ -2599,12 +2599,12 @@ void {name}_return({return_ty}) {{ ty: TypeId, payload_type: Option<&Type>, ) { - if !self.gen.futures.insert(ty) { + if !self.r#gen.futures.insert(ty) { return; } - let ty = self.gen.type_name(&Type::Id(ty)); + let ty = self.r#gen.type_name(&Type::Id(ty)); let name = ty.strip_suffix("_t").unwrap(); - let snake = self.gen.world.to_snake_case(); + let snake = self.r#gen.world.to_snake_case(); let kind = match payload_for { PayloadFor::Future => "future", PayloadFor::Stream => "stream", @@ -2617,7 +2617,7 @@ void {name}_return({return_ty}) {{ match (payload_for, payload_type) { (PayloadFor::Future, None) => ("".to_string(), "NULL", "".to_string(), "NULL"), (PayloadFor::Future, Some(ty)) => { - let ty = self.gen.type_name(ty); + let ty = self.r#gen.type_name(ty); ( format!(", {ty} *buf"), "(uint8_t*) buf", @@ -2632,7 +2632,7 @@ void {name}_return({return_ty}) {{ "NULL, amt", ), (PayloadFor::Stream, Some(ty)) => { - let ty = self.gen.type_name(ty); + let ty = self.r#gen.type_name(ty); ( format!(", {ty} *buf, size_t amt"), "(uint8_t*) buf, amt", @@ -2655,8 +2655,8 @@ typedef uint32_t {name}_writer_t; {snake}_waitable_status_t {name}_write({name}_writer_t writer{write_arg_ty}); {snake}_waitable_status_t {name}_cancel_read({ty} reader); {snake}_waitable_status_t {name}_cancel_write({name}_writer_t writer); -void {name}_close_readable({ty} reader);{empty} -void {name}_close_writable({name}_writer_t writer); +void {name}_drop_readable({ty} reader);{empty} +void {name}_drop_writable({name}_writer_t writer); "#, ); uwriteln!( @@ -2672,10 +2672,10 @@ __attribute__((__import_module__("{module}"), __import_name__("[{kind}-cancel-re extern uint32_t {name}__cancel_read(uint32_t); __attribute__((__import_module__("{module}"), __import_name__("[{kind}-cancel-write-{index}]{func_name}"))) extern uint32_t {name}__cancel_write(uint32_t); -__attribute__((__import_module__("{module}"), __import_name__("[{kind}-close-readable-{index}]{func_name}"))) -extern void {name}__close_readable(uint32_t); -__attribute__((__import_module__("{module}"), __import_name__("[{kind}-close-writable-{index}]{func_name}"))) -extern void {name}__close_writable(uint32_t); +__attribute__((__import_module__("{module}"), __import_name__("[{kind}-drop-readable-{index}]{func_name}"))) +extern void {name}__drop_readable(uint32_t); +__attribute__((__import_module__("{module}"), __import_name__("[{kind}-drop-writable-{index}]{func_name}"))) +extern void {name}__drop_writable(uint32_t); {ty} {name}_new({name}_writer_t *writer) {{ uint64_t packed = {name}__new(); @@ -2699,12 +2699,12 @@ extern void {name}__close_writable(uint32_t); return {name}__cancel_write(writer); }} -void {name}_close_readable({ty} reader){empty} {{ - {name}__close_readable(reader); +void {name}_drop_readable({ty} reader){empty} {{ + {name}__drop_readable(reader); }} -void {name}_close_writable({name}_writer_t writer) {{ - {name}__close_writable(writer); +void {name}_drop_writable({name}_writer_t writer) {{ + {name}__drop_writable(writer); }} "#, ); @@ -2722,7 +2722,7 @@ struct DroppableBorrow { } struct FunctionBindgen<'a, 'b> { - gen: &'a mut InterfaceGenerator<'b>, + r#gen: &'a mut InterfaceGenerator<'b>, locals: Ns, src: wit_bindgen_core::Source, sig: CSig, @@ -2801,7 +2801,7 @@ enum DeferredTaskReturn { impl<'a, 'b> FunctionBindgen<'a, 'b> { fn new( - gen: &'a mut InterfaceGenerator<'b>, + r#gen: &'a mut InterfaceGenerator<'b>, sig: CSig, func_to_call: &'a str, ) -> FunctionBindgen<'a, 'b> { @@ -2810,7 +2810,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> { locals.insert(name).unwrap(); } FunctionBindgen { - gen, + r#gen, sig, locals, src: Default::default(), @@ -2889,9 +2889,9 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> { } fn assert_no_droppable_borrows(&self, context: &str, ty: &Type) { - if !self.gen.in_import - && self.gen.autodrop_enabled() - && self.gen.contains_droppable_borrow(ty) + if !self.r#gen.in_import + && self.r#gen.autodrop_enabled() + && self.r#gen.contains_droppable_borrow(ty) { panic!( "Unable to autodrop borrows in `{}` values, please disable autodrop", @@ -2905,7 +2905,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { type Operand = String; fn sizes(&self) -> &SizeAlign { - &self.gen.gen.sizes + &self.r#gen.r#gen.sizes } fn push_block(&mut self) { @@ -2924,15 +2924,16 @@ impl Bindgen for FunctionBindgen<'_, '_> { // Use a stack-based return area for imports, because exports need // their return area to be live until the post-return call. - if self.gen.in_import { + if self.r#gen.in_import { self.import_return_pointer_area_size = self.import_return_pointer_area_size.max(size); self.import_return_pointer_area_align = self.import_return_pointer_area_align.max(align); uwriteln!(self.src, "uint8_t *{} = (uint8_t *) &ret_area;", ptr); } else { - self.gen.gen.return_pointer_area_size = self.gen.gen.return_pointer_area_size.max(size); - self.gen.gen.return_pointer_area_align = - self.gen.gen.return_pointer_area_align.max(align); + self.r#gen.r#gen.return_pointer_area_size = + self.r#gen.r#gen.return_pointer_area_size.max(size); + self.r#gen.r#gen.return_pointer_area_align = + self.r#gen.r#gen.return_pointer_area_align.max(align); // Declare a statically-allocated return area. uwriteln!(self.src, "uint8_t *{} = (uint8_t *) &RET_AREA;", ptr); } @@ -3000,7 +3001,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::Bitcasts { casts } => { for (cast, op) in casts.iter().zip(operands) { - let op = self.gen.gen.perform_cast(op, cast); + let op = self.r#gen.r#gen.perform_cast(op, cast); results.push(op); } } @@ -3016,10 +3017,10 @@ impl Bindgen for FunctionBindgen<'_, '_> { } } Instruction::RecordLift { ty, record, .. } => { - let name = self.gen.gen.type_name(&Type::Id(*ty)); + let name = self.r#gen.r#gen.type_name(&Type::Id(*ty)); let mut result = format!("({}) {{\n", name); for (field, op) in record.fields.iter().zip(operands.iter()) { - let field_ty = self.gen.gen.type_name(&field.ty); + let field_ty = self.r#gen.r#gen.type_name(&field.ty); uwriteln!(result, "({}) {},", field_ty, op); } result.push_str("}"); @@ -3033,10 +3034,10 @@ impl Bindgen for FunctionBindgen<'_, '_> { } } Instruction::TupleLift { ty, tuple, .. } => { - let name = self.gen.gen.type_name(&Type::Id(*ty)); + let name = self.r#gen.r#gen.type_name(&Type::Id(*ty)); let mut result = format!("({}) {{\n", name); for (ty, op) in tuple.types.iter().zip(operands.iter()) { - let ty = self.gen.gen.type_name(&ty); + let ty = self.r#gen.r#gen.type_name(&ty); uwriteln!(result, "({}) {},", ty, op); } result.push_str("}"); @@ -3051,7 +3052,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::HandleLift { handle, ty, .. } => match handle { Handle::Borrow(resource) if matches!( - self.gen.gen.resources[&dealias(resolve, *resource)].direction, + self.r#gen.r#gen.resources[&dealias(resolve, *resource)].direction, Direction::Export ) => { @@ -3059,21 +3060,21 @@ impl Bindgen for FunctionBindgen<'_, '_> { // it as a raw pointer rather than an opaque handle. let op = &operands[0]; let name = self - .gen - .gen + .r#gen + .r#gen .type_name(&Type::Id(dealias(resolve, *resource))); results.push(format!("(({name}*) {op})")) } _ => { let op = &operands[0]; - let name = self.gen.gen.type_name(&Type::Id(*ty)); + let name = self.r#gen.r#gen.type_name(&Type::Id(*ty)); results.push(format!("({name}) {{ {op} }}")); if let Handle::Borrow(id) = handle { - if !self.gen.in_import && self.gen.autodrop_enabled() { + if !self.r#gen.in_import && self.r#gen.autodrop_enabled() { // Here we've received a borrow of an imported resource, which is the // kind we'll need to drop when the exported function is returning. - let ty = dealias(self.gen.resolve, *id); + let ty = dealias(self.r#gen.resolve, *id); let name = self.locals.tmp("borrow"); uwriteln!(self.borrow_decls, "int32_t {name} = 0;"); @@ -3091,7 +3092,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { results.push(operands.pop().unwrap()); } Int::U64 => { - let name = self.gen.gen.type_name(&Type::Id(*ty)); + let name = self.r#gen.r#gen.type_name(&Type::Id(*ty)); let tmp = self.locals.tmp("flags"); uwriteln!(self.src, "{name} {tmp} = {};", operands[0]); results.push(format!("{tmp} & 0xffffffff")); @@ -3104,7 +3105,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { results.push(operands.pop().unwrap()); } Int::U64 => { - let name = self.gen.gen.type_name(&Type::Id(*ty)); + let name = self.r#gen.r#gen.type_name(&Type::Id(*ty)); let op0 = &operands[0]; let op1 = &operands[1]; results.push(format!("(({name}) ({op0})) | ((({name}) ({op1})) << 32)")); @@ -3150,7 +3151,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { { uwriteln!(self.src, "case {}: {{", i); if let Some(ty) = case.ty.as_ref() { - let ty = self.gen.gen.type_name(ty); + let ty = self.r#gen.r#gen.type_name(ty); uwrite!( self.src, "const {} *{} = &({}).val", @@ -3178,7 +3179,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { .drain(self.blocks.len() - variant.cases.len()..) .collect::>(); - let ty = self.gen.gen.type_name(&Type::Id(*ty)); + let ty = self.r#gen.r#gen.type_name(&Type::Id(*ty)); let result = self.locals.tmp("variant"); uwriteln!(self.src, "{} {};", ty, result); uwriteln!(self.src, "{}.tag = {};", result, operands[0]); @@ -3226,7 +3227,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { } let op0 = &operands[0]; - let ty = self.gen.gen.type_name(payload); + let ty = self.r#gen.r#gen.type_name(payload); let bind_some = format!("const {ty} *{some_payload} = &({op0}).val;"); uwrite!( @@ -3247,7 +3248,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { assert!(some_results.len() == 1); let some_result = &some_results[0]; - let ty = self.gen.gen.type_name(&Type::Id(*ty)); + let ty = self.r#gen.r#gen.type_name(&Type::Id(*ty)); let result = self.locals.tmp("option"); uwriteln!(self.src, "{ty} {result};"); let op0 = &operands[0]; @@ -3302,13 +3303,13 @@ impl Bindgen for FunctionBindgen<'_, '_> { let op0 = &operands[0]; let bind_ok = if let Some(ok) = result.ok.as_ref() { - let ok_ty = self.gen.gen.type_name(ok); + let ok_ty = self.r#gen.r#gen.type_name(ok); format!("const {ok_ty} *{ok_payload} = &({op0}).val.ok;") } else { String::new() }; let bind_err = if let Some(err) = result.err.as_ref() { - let err_ty = self.gen.gen.type_name(err); + let err_ty = self.r#gen.r#gen.type_name(err); format!("const {err_ty} *{err_payload} = &({op0}).val.err;") } else { String::new() @@ -3354,7 +3355,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { String::new() }; - let ty = self.gen.gen.type_name(&Type::Id(*ty)); + let ty = self.r#gen.r#gen.type_name(&Type::Id(*ty)); uwriteln!(self.src, "{ty} {result_tmp};"); let op0 = &operands[0]; uwriteln!( @@ -3387,19 +3388,19 @@ impl Bindgen for FunctionBindgen<'_, '_> { Instruction::ListCanonLift { element, ty, .. } => { self.assert_no_droppable_borrows("list", &Type::Id(*ty)); - let list_name = self.gen.gen.type_name(&Type::Id(*ty)); - let elem_name = self.gen.gen.type_name(element); + let list_name = self.r#gen.r#gen.type_name(&Type::Id(*ty)); + let elem_name = self.r#gen.r#gen.type_name(element); results.push(format!( "({}) {{ ({}*)({}), ({}) }}", list_name, elem_name, operands[0], operands[1] )); } Instruction::StringLift { .. } => { - let list_name = self.gen.gen.type_name(&Type::String); + let list_name = self.r#gen.r#gen.type_name(&Type::String); results.push(format!( "({}) {{ ({}*)({}), ({}) }}", list_name, - self.gen.gen.char_type(), + self.r#gen.r#gen.char_type(), operands[0], operands[1] )); @@ -3415,8 +3416,8 @@ impl Bindgen for FunctionBindgen<'_, '_> { self.assert_no_droppable_borrows("list", &Type::Id(*ty)); let _body = self.blocks.pop().unwrap(); - let list_name = self.gen.gen.type_name(&Type::Id(*ty)); - let elem_name = self.gen.gen.type_name(element); + let list_name = self.r#gen.r#gen.type_name(&Type::Id(*ty)); + let elem_name = self.r#gen.r#gen.type_name(element); results.push(format!( "({}) {{ ({}*)({}), ({}) }}", list_name, elem_name, operands[0], operands[1] @@ -3457,14 +3458,15 @@ impl Bindgen for FunctionBindgen<'_, '_> { let ty = &func.params[i].1; if *byref { let name = self.locals.tmp("arg"); - let ty = self.gen.gen.type_name(ty); + let ty = self.r#gen.r#gen.type_name(ty); uwriteln!(self.src, "{} {} = {};", ty, name, op); args.push_str("&"); args.push_str(&name); } else { - if !self.gen.in_import { + if !self.r#gen.in_import { if let Type::Id(id) = ty { - if let TypeDefKind::Option(_) = &self.gen.resolve.types[*id].kind { + if let TypeDefKind::Option(_) = &self.r#gen.resolve.types[*id].kind + { uwrite!(args, "{op}.is_some ? &({op}.val) : NULL"); continue; } @@ -3475,7 +3477,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { } if *async_ { let ret = self.locals.tmp("ret"); - let snake = self.gen.gen.world.to_snake_case(); + let snake = self.r#gen.r#gen.world.to_snake_case(); uwriteln!( self.src, "{snake}_callback_code_t {ret} = {}({args});", @@ -3499,7 +3501,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { let mut retptrs = Vec::new(); for ty in self.sig.ret.retptrs.iter() { let name = self.locals.tmp("ret"); - let ty = self.gen.gen.type_name(ty); + let ty = self.r#gen.r#gen.type_name(ty); uwriteln!(self.src, "{} {};", ty, name); if args.len() > 0 { args.push_str(", "); @@ -3517,7 +3519,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { Some(Scalar::Type(_)) => { let ret = self.locals.tmp("ret"); let ty = func.result.unwrap(); - let ty = self.gen.gen.type_name(&ty); + let ty = self.r#gen.r#gen.type_name(&ty); uwriteln!(self.src, "{} {} = {}({});", ty, ret, self.sig.name, args); results.push(ret); } @@ -3529,11 +3531,11 @@ impl Bindgen for FunctionBindgen<'_, '_> { } args.push_str("&"); args.push_str(&val); - let payload_ty = self.gen.gen.type_name(ty); + let payload_ty = self.r#gen.r#gen.type_name(ty); uwriteln!(self.src, "{} {};", payload_ty, val); uwriteln!(self.src, "bool {} = {}({});", ret, self.sig.name, args); let ty = func.result.unwrap(); - let option_ty = self.gen.gen.type_name(&ty); + let option_ty = self.r#gen.r#gen.type_name(&ty); let option_ret = self.locals.tmp("ret"); uwrite!( self.src, @@ -3547,7 +3549,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { } Some(Scalar::ResultBool(ok, err)) => { let ty = &func.result.unwrap(); - let result_ty = self.gen.gen.type_name(ty); + let result_ty = self.r#gen.r#gen.type_name(ty); let ret = self.locals.tmp("ret"); let mut ret_iter = self.sig.ret.retptrs.iter(); uwriteln!(self.src, "{result_ty} {ret};"); @@ -3558,7 +3560,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwrite!(args, ", "); } uwrite!(args, "&{val}"); - let ty = self.gen.gen.type_name(ty); + let ty = self.r#gen.r#gen.type_name(ty); uwriteln!(self.src, "{} {};", ty, val); Some(val) } else { @@ -3573,7 +3575,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwrite!(args, ", ") } uwrite!(args, "&{val}"); - let ty = self.gen.gen.type_name(ty); + let ty = self.r#gen.r#gen.type_name(ty); uwriteln!(self.src, "{} {};", ty, val); Some(val) } else { @@ -3608,7 +3610,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { } } } - Instruction::Return { .. } if self.gen.in_import => match self.sig.ret.scalar { + Instruction::Return { .. } if self.r#gen.in_import => match self.sig.ret.scalar { None => { for op in operands.iter() { self.store_in_retptr(op); @@ -3669,7 +3671,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { self.src.append_src(&src); for DroppableBorrow { name, ty } in self.borrows.iter() { - let drop_fn = self.gen.gen.resources[ty].drop_fn.as_str(); + let drop_fn = self.r#gen.r#gen.resources[ty].drop_fn.as_str(); uwriteln!(self.src, "if ({name} != 0) {{"); uwriteln!(self.src, " {drop_fn}({name});"); uwriteln!(self.src, "}}"); @@ -3744,7 +3746,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { uwriteln!(self.src, "uint8_t *{ptr} = {};", operands[0]); let i = self.locals.tmp("i"); uwriteln!(self.src, "for (size_t {i} = 0; {i} < {len}; {i}++) {{"); - let size = self.gen.gen.sizes.size(element); + let size = self.r#gen.r#gen.sizes.size(element); uwriteln!( self.src, "uint8_t *base = {ptr} + {i} * {};", diff --git a/crates/core/src/abi.rs b/crates/core/src/abi.rs index 40f59ed5f..af4eb0a49 100644 --- a/crates/core/src/abi.rs +++ b/crates/core/src/abi.rs @@ -750,7 +750,7 @@ pub fn lower_to_memory( ty: &Type, ) { let mut generator = Generator::new(resolve, bindgen); - // TODO: make this configurable? Right this this function is only called for + // TODO: make this configurable? Right now this function is only called for // future/stream callbacks so it's appropriate to skip realloc here as it's // all "lower for wasm import", but this might get reused for something else // in the future. @@ -783,6 +783,18 @@ pub fn lift_from_memory( generator.stack.pop().unwrap() } +pub fn lift_flat( + resolve: &Resolve, + bindgen: &mut B, + src: Vec, + ty: &Type, +) -> B::Operand { + let mut generator = Generator::new(resolve, bindgen); + generator.stack = src; + generator.lift(ty); + generator.stack.pop().unwrap() +} + /// Used in a similar manner as the `Interface::call` function except is /// used to generate the `post-return` callback for `func`. /// diff --git a/crates/guest-rust/rt/src/async_support.rs b/crates/guest-rust/rt/src/async_support.rs index 86cfce10f..7acf62349 100644 --- a/crates/guest-rust/rt/src/async_support.rs +++ b/crates/guest-rust/rt/src/async_support.rs @@ -309,7 +309,7 @@ const STATUS_RETURNED_CANCELLED: u32 = 4; const BLOCKED: u32 = 0xffff_ffff; const COMPLETED: u32 = 0x0; -const CLOSED: u32 = 0x1; +const DROPPED: u32 = 0x1; const CANCELLED: u32 = 0x2; /// Return code of stream/future operations. @@ -319,9 +319,9 @@ enum ReturnCode { Blocked, /// The operation completed with the specified number of items. Completed(u32), - /// The other end is closed, but before that the specified number of items + /// The other end is dropped, but before that the specified number of items /// were transferred. - Closed(u32), + Dropped(u32), /// The operation was cancelled, but before that the specified number of /// items were transferred. Cancelled(u32), @@ -335,7 +335,7 @@ impl ReturnCode { let amt = val >> 4; match val & 0xf { COMPLETED => ReturnCode::Completed(amt), - CLOSED => ReturnCode::Closed(amt), + DROPPED => ReturnCode::Dropped(amt), CANCELLED => ReturnCode::Cancelled(amt), _ => panic!("unknown return code {val:#x}"), } diff --git a/crates/guest-rust/rt/src/async_support/abi_buffer.rs b/crates/guest-rust/rt/src/async_support/abi_buffer.rs index 04077fef4..1ceb30e25 100644 --- a/crates/guest-rust/rt/src/async_support/abi_buffer.rs +++ b/crates/guest-rust/rt/src/async_support/abi_buffer.rs @@ -207,7 +207,7 @@ mod tests { extern "C" fn cancel(_: u32) -> u32 { todo!() } - extern "C" fn close(_: u32) { + extern "C" fn drop(_: u32) { todo!() } extern "C" fn new() -> u64 { @@ -223,8 +223,8 @@ mod tests { static BLANK: StreamVtable = StreamVtable { cancel_read: cancel, cancel_write: cancel, - close_readable: close, - close_writable: close, + drop_readable: drop, + drop_writable: drop, dealloc_lists: None, lift: None, lower: None, @@ -299,8 +299,8 @@ mod tests { static OP: StreamVtable = StreamVtable { cancel_read: cancel, cancel_write: cancel, - close_readable: close, - close_writable: close, + drop_readable: drop, + drop_writable: drop, dealloc_lists: Some(|_ptr| {}), lift: Some(|ptr| unsafe { B(*ptr - 1) }), lower: Some(|b, ptr| unsafe { @@ -380,8 +380,8 @@ mod tests { static OP: StreamVtable = StreamVtable { cancel_read: cancel, cancel_write: cancel, - close_readable: close, - close_writable: close, + drop_readable: drop, + drop_writable: drop, dealloc_lists: Some(|ptr| { let prev = DEALLOCS.fetch_add(1, Relaxed); assert_eq!(unsafe { usize::from(*ptr) }, prev + 1); diff --git a/crates/guest-rust/rt/src/async_support/future_support.rs b/crates/guest-rust/rt/src/async_support/future_support.rs index 56e1d9f4e..1e6106d72 100644 --- a/crates/guest-rust/rt/src/async_support/future_support.rs +++ b/crates/guest-rust/rt/src/async_support/future_support.rs @@ -48,7 +48,7 @@ //! //! * A `write` hasn't even started yet. //! * A `write` was started and then cancelled. -//! * A `write` was started and then the other end closed the channel. +//! * A `write` was started and then the other end dropped the channel. //! * A `write` was started and then the other end received the value. //! //! In all of these situations regardless of the structure of `T` we can't leak @@ -90,7 +90,7 @@ //! ## Linear (exactly once) Writes //! //! The component model requires that a writable end of a future must be written -//! to before closing, otherwise the close operation traps. Ideally usage of +//! to before closing, otherwise the drop operation traps. Ideally usage of //! this API shouldn't result in traps so this is modeled in the Rust-level API //! to prevent this trap from occurring. Rust does not support linear types //! (types that must be used exactly once), instead it only has affine types @@ -127,6 +127,19 @@ use { }, }; +#[doc(hidden)] +#[derive(Clone, Copy)] +pub union CoreVal { + pub uninitialized: (), + pub as_i32: i32, + pub as_i64: i64, + pub as_f32: f32, + pub as_f64: f64, +} + +#[doc(hidden)] +pub type LoweredWrite = [CoreVal; 4]; + /// Function table used for [`FutureWriter`] and [`FutureReader`] /// /// Instances of this table are generated by `wit_bindgen::generate!`. This is @@ -140,13 +153,8 @@ pub struct FutureVtable { /// The Canonical ABI layout of `T` in-memory. pub layout: Layout, - /// A callback to consume a value of `T` and lower it to the canonical ABI - /// pointed to by `dst`. - /// - /// The `dst` pointer should have `self.layout`. This is used to convert - /// in-memory representations in Rust to their canonical representations in - /// the component model. - pub lower: unsafe fn(value: T, dst: *mut u8), + /// A callback to consume a value of `T` and lower it to the canonical ABI. + pub lower_write: unsafe fn(value: T, dst: &mut LoweredWrite) -> Option, /// A callback to deallocate any lists within the canonical ABI value `dst` /// provided. @@ -156,24 +164,35 @@ pub struct FutureVtable { /// has lists that are still owned by this component and must be /// deallocated. This is akin to a `post-return` callback for returns of /// exported functions. - pub dealloc_lists: unsafe fn(dst: *mut u8), + pub dealloc_lists: unsafe fn(dst: &LoweredWrite), /// A callback to lift a value of `T` from the canonical ABI representation /// provided. - pub lift: unsafe fn(dst: *mut u8) -> T, + /// + /// This is for lifting a value lowered as a `future.write` parameter. + pub lift_write: unsafe fn(dst: &LoweredWrite) -> T, - /// The raw `future.write` intrinsic. - pub start_write: unsafe extern "C" fn(future: u32, val: *const u8) -> u32, + /// A callback to lift a value of `T` from the canonical ABI representation + /// provided. + /// + /// This is for lifting a value lowered as a `future.read` result. + pub lift_read: unsafe fn(dst: *mut u8) -> T, + + /// A wrapper function for the raw `future.write` intrinsic. + /// + /// This will pass the specified lowered payload to the `future.write` + /// intrinsic. + pub start_write: unsafe extern "C" fn(future: u32, lowered: &LoweredWrite) -> u32, /// The raw `future.read` intrinsic. pub start_read: unsafe extern "C" fn(future: u32, val: *mut u8) -> u32, /// The raw `future.cancel-write` intrinsic. pub cancel_write: unsafe extern "C" fn(future: u32) -> u32, /// The raw `future.cancel-read` intrinsic. pub cancel_read: unsafe extern "C" fn(future: u32) -> u32, - /// The raw `future.close-writable` intrinsic. - pub close_writable: unsafe extern "C" fn(future: u32), - /// The raw `future.close-readable` intrinsic. - pub close_readable: unsafe extern "C" fn(future: u32), + /// The raw `future.drop-writable` intrinsic. + pub drop_writable: unsafe extern "C" fn(future: u32), + /// The raw `future.drop-readable` intrinsic. + pub drop_readable: unsafe extern "C" fn(future: u32), /// The raw `future.new` intrinsic. pub new: unsafe extern "C" fn() -> u64, } @@ -212,7 +231,7 @@ pub struct FutureWriter { /// Whether or not a value should be written during `drop`. /// /// This is set to `false` when a value is successfully written or when a - /// value is written but the future is witnessed as being closed. + /// value is written but the future is witnessed as being dropped. /// /// Note that this is set to `true` on construction to ensure that only /// location which actually witness a completed write set it to `false`. @@ -255,9 +274,9 @@ impl FutureWriter { /// * `Ok(())` - the `value` was sent and received. The `self` value was /// consumed along the way and will no longer be accessible. /// * `Err(FutureWriteError { value })` - an attempt was made to send - /// `value` but the other half of this [`FutureWriter`] was closed before + /// `value` but the other half of this [`FutureWriter`] was dropped before /// the value was received. This consumes `self` because the channel is - /// now closed, but `value` is returned in case the caller wants to reuse + /// now dropped, but `value` is returned in case the caller wants to reuse /// it. /// /// # Cancellation @@ -290,7 +309,7 @@ impl Drop for FutureWriter { // `false` to avoid infinite loops by accident. Once the task is spawned // we're done and the subtask's destructor of the closed-over // `FutureWriter` will be responsible for performing the - // `close-writable` call below. + // `drop-writable` call below. // // Note, though, that if `should_write_default_value` is `false` then a // write has already happened and we can go ahead and just synchronously @@ -308,8 +327,8 @@ impl Drop for FutureWriter { }); } else { unsafe { - rtdebug!("future.close-writable({})", self.handle); - (self.vtable.close_writable)(self.handle); + rtdebug!("future.drop-writable({})", self.handle); + (self.vtable.drop_writable)(self.handle); } } } @@ -326,7 +345,7 @@ struct FutureWriteOp(marker::PhantomData); enum WriteComplete { Written, - Closed(T), + Dropped(T), Cancelled(T), } @@ -335,7 +354,7 @@ where T: 'static, { type Start = (FutureWriter, T); - type InProgress = (FutureWriter, Option); + type InProgress = (FutureWriter, LoweredWrite, Option); type Result = (WriteComplete, FutureWriter); type Cancel = FutureWriteCancel; @@ -350,15 +369,21 @@ where // In lieu of that a dedicated location on the heap is created for the // lowering, and then `value`, as an owned value, is lowered into this // pointer to initialize it. - let (ptr, cleanup) = Cleanup::new(writer.vtable.layout); - // SAFETY: `ptr` is allocated with `vtable.layout` and should be - // safe to use here. - let code = unsafe { - (writer.vtable.lower)(value, ptr); - (writer.vtable.start_write)(writer.handle, ptr) + // + // SAFETY: `lower_write` and `start_write` will handle allocation (if + // needed), lowering, and union field access here according to the + // payload type. All we need to do is give it a `LoweredWrite` + // reference to work with. + let mut lowered = [CoreVal { uninitialized: () }; 4]; + let (code, cleanup) = unsafe { + let cleanup = (writer.vtable.lower_write)(value, &mut lowered); + ( + (writer.vtable.start_write)(writer.handle, &lowered), + cleanup, + ) }; - rtdebug!("future.write({}, {ptr:?}) = {code:#x}", writer.handle); - (code, (writer, cleanup)) + rtdebug!("future.write({}) = {code:#x}", writer.handle); + (code, (writer, lowered, cleanup)) } fn start_cancelled((writer, value): Self::Start) -> Self::Cancel { @@ -366,34 +391,28 @@ where } fn in_progress_update( - (mut writer, cleanup): Self::InProgress, + (mut writer, lowered, cleanup): Self::InProgress, code: u32, ) -> Result { - let ptr = cleanup - .as_ref() - .map(|c| c.ptr.as_ptr()) - .unwrap_or(ptr::null_mut()); match ReturnCode::decode(code) { - ReturnCode::Blocked => Err((writer, cleanup)), + ReturnCode::Blocked => Err((writer, lowered, cleanup)), - // The other end has closed its end. + // The other end has dropped its end. // - // The value was not received by the other end so `ptr` still has - // all of its resources intact. Use `lift` to construct a new + // The value was not received by the other end so `lowered` still + // has all of its resources intact. Use `lift` to construct a new // instance of `T` which takes ownership of pointers and resources - // and such. The allocation of `ptr` is then cleaned up naturally - // when `cleanup` goes out of scope. - c @ ReturnCode::Closed(0) | c @ ReturnCode::Cancelled(0) => { - // SAFETY: we're the ones managing `ptr` so we know it's safe to - // pass here. - let value = unsafe { (writer.vtable.lift)(ptr) }; - let status = if c == ReturnCode::Closed(0) { - // This writer has been witnessed to be closed, meaning that + // and such. + c @ ReturnCode::Dropped(0) | c @ ReturnCode::Cancelled(0) => { + // SAFETY: TODO + let value = unsafe { (writer.vtable.lift_write)(&lowered) }; + let status = if c == ReturnCode::Dropped(0) { + // This writer has been witnessed to be dropped, meaning that // `writer` is going to get destroyed soon as this return // value propagates up the stack. There's no need to write // the default value, so set this to `false`. writer.should_write_default_value = false; - WriteComplete::Closed(value) + WriteComplete::Dropped(value) } else { WriteComplete::Cancelled(value) }; @@ -402,21 +421,17 @@ where // This write has completed. // - // Here we need to clean up our allocations. The `ptr` exclusively + // Here we need to clean up our allocations. `lowered` exclusively // owns all of the value being sent and we notably need to cleanup - // the transitive list allocations present in this pointer. Use - // `dealloc_lists` for that (effectively a post-return lookalike). - // - // Afterwards the `cleanup` itself is naturally dropped and cleaned - // up. - ReturnCode::Completed(1) | ReturnCode::Closed(1) | ReturnCode::Cancelled(1) => { + // the transitive list allocations present. Use `dealloc_lists` for + // that (effectively a post-return lookalike). + ReturnCode::Completed(1) | ReturnCode::Dropped(1) | ReturnCode::Cancelled(1) => { // A value was written, so no need to write the default value. writer.should_write_default_value = false; - // SAFETY: we're the ones managing `ptr` so we know it's safe to - // pass here. + // SAFETY: TODO unsafe { - (writer.vtable.dealloc_lists)(ptr); + (writer.vtable.dealloc_lists)(&lowered); } Ok((WriteComplete::Written, writer)) } @@ -425,11 +440,11 @@ where } } - fn in_progress_waitable((writer, _): &Self::InProgress) -> u32 { + fn in_progress_waitable((writer, ..): &Self::InProgress) -> u32 { writer.handle } - fn in_progress_cancel((writer, _): &Self::InProgress) -> u32 { + fn in_progress_cancel((writer, ..): &Self::InProgress) -> u32 { // SAFETY: we're managing `writer` and all the various operational bits, // so this relies on `WaitableOperation` being safe. let code = unsafe { (writer.vtable.cancel_write)(writer.handle) }; @@ -446,7 +461,7 @@ where // The value was not sent because the other end either hung up or we // successfully cancelled. In both cases return back the value here // with the writer. - WriteComplete::Closed(val) => FutureWriteCancel::Closed(val), + WriteComplete::Dropped(val) => FutureWriteCancel::Dropped(val), WriteComplete::Cancelled(val) => FutureWriteCancel::Cancelled(val, writer), } } @@ -460,7 +475,7 @@ impl Future for FutureWrite { .poll_complete(cx) .map(|(result, _writer)| match result { WriteComplete::Written => Ok(()), - WriteComplete::Closed(value) | WriteComplete::Cancelled(value) => { + WriteComplete::Dropped(value) | WriteComplete::Cancelled(value) => { Err(FutureWriteError { value }) } }) @@ -478,7 +493,7 @@ impl FutureWrite { /// /// This method can be used to cancel a write-in-progress and re-acquire /// the writer and the value being sent. Note that the write operation may - /// succeed racily or the other end may also close racily, and these + /// succeed racily or the other end may also drop racily, and these /// outcomes are reflected in the returned value here. /// /// # Panics @@ -505,7 +520,7 @@ impl fmt::Debug for FutureWriteError { impl fmt::Display for FutureWriteError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "read end closed".fmt(f) + "read end dropped".fmt(f) } } @@ -519,11 +534,11 @@ pub enum FutureWriteCancel { /// available here as both are gone. AlreadySent, - /// The other end was closed before cancellation happened. + /// The other end was dropped before cancellation happened. /// /// In this case the original value is returned back to the caller but the /// writer itself is not longer accessible as it's no longer usable. - Closed(T), + Dropped(T), /// The pending write was successfully cancelled and the value being written /// is returned along with the writer to resume again in the future if @@ -592,8 +607,8 @@ impl Drop for FutureReader { return; }; unsafe { - rtdebug!("future.close-readable({handle})"); - (self.vtable.close_readable)(handle); + rtdebug!("future.drop-readable({handle})"); + (self.vtable.drop_readable)(handle); } } } @@ -651,7 +666,7 @@ where // The read has completed, so lift the value from the stored memory and // `cleanup` naturally falls out of scope after transferring ownership of // everything to the returned `value`. - ReturnCode::Completed(1) | ReturnCode::Closed(1) | ReturnCode::Cancelled(1) => { + ReturnCode::Completed(1) | ReturnCode::Dropped(1) | ReturnCode::Cancelled(1) => { let ptr = cleanup .as_ref() .map(|c| c.ptr.as_ptr()) @@ -659,7 +674,7 @@ where // SAFETY: we're the ones managing `ptr` so we know it's safe to // pass here. - let value = unsafe { (reader.vtable.lift)(ptr) }; + let value = unsafe { (reader.vtable.lift_read)(ptr) }; Ok((ReadComplete::Value(value), reader)) } diff --git a/crates/guest-rust/rt/src/async_support/stream_support.rs b/crates/guest-rust/rt/src/async_support/stream_support.rs index c8f1ca852..dee6b5081 100644 --- a/crates/guest-rust/rt/src/async_support/stream_support.rs +++ b/crates/guest-rust/rt/src/async_support/stream_support.rs @@ -56,10 +56,10 @@ pub struct StreamVtable { pub cancel_write: unsafe extern "C" fn(stream: u32) -> u32, /// The raw `stream.cancel-read` intrinsic. pub cancel_read: unsafe extern "C" fn(stream: u32) -> u32, - /// The raw `stream.close-writable` intrinsic. - pub close_writable: unsafe extern "C" fn(stream: u32), - /// The raw `stream.close-readable` intrinsic. - pub close_readable: unsafe extern "C" fn(stream: u32), + /// The raw `stream.drop-writable` intrinsic. + pub drop_writable: unsafe extern "C" fn(stream: u32), + /// The raw `stream.drop-readable` intrinsic. + pub drop_readable: unsafe extern "C" fn(stream: u32), /// The raw `stream.new` intrinsic. pub new: unsafe extern "C" fn() -> u64, } @@ -107,7 +107,7 @@ impl StreamWriter { /// The returned [`StreamWrite`] future returns a tuple of `(result, buf)`. /// The `result` can be `StreamResult::Complete(n)` meaning that `n` values /// were sent from `values` into this writer. A result of - /// `StreamResult::Closed` means that no values were sent and the other side + /// `StreamResult::Dropped` means that no values were sent and the other side /// has hung-up and sending values will no longer be possible. /// /// The `buf` returned is an [`AbiBuffer`] which retains ownership of the @@ -148,7 +148,7 @@ impl StreamWriter { /// expose cancellation for example. This will successively attempt to write /// all of `values` provided into this stream. Upon completion the same /// vector will be returned and any remaining elements in the vector were - /// not sent because the stream was closed. + /// not sent because the stream was dropped. pub async fn write_all(&mut self, values: Vec) -> Vec { // Perform an initial write which converts `values` into `AbiBuffer`. let (mut status, mut buf) = self.write(values).await; @@ -169,7 +169,7 @@ impl StreamWriter { // Return back any values that weren't written by shifting them to the // front of the returned vector. - assert!(buf.remaining() == 0 || matches!(status, StreamResult::Closed)); + assert!(buf.remaining() == 0 || matches!(status, StreamResult::Dropped)); buf.into_vec() } @@ -200,9 +200,9 @@ impl fmt::Debug for StreamWriter { impl Drop for StreamWriter { fn drop(&mut self) { - rtdebug!("stream.close-writable({})", self.handle); + rtdebug!("stream.drop-writable({})", self.handle); unsafe { - (self.vtable.close_writable)(self.handle); + (self.vtable.drop_writable)(self.handle); } } } @@ -223,8 +223,8 @@ pub enum StreamResult { /// For writes this is how many items were written, and for reads this is /// how many items were read. Complete(usize), - /// No values were written, the other end has closed its handle. - Closed, + /// No values were written, the other end has dropped its handle. + Dropped, /// No values were written, the operation was cancelled. Cancelled, } @@ -260,9 +260,9 @@ where ) -> Result { match ReturnCode::decode(code) { ReturnCode::Blocked => Err((writer, buf)), - ReturnCode::Closed(0) => Ok((StreamResult::Closed, buf)), + ReturnCode::Dropped(0) => Ok((StreamResult::Dropped, buf)), ReturnCode::Cancelled(0) => Ok((StreamResult::Cancelled, buf)), - ReturnCode::Completed(amt) | ReturnCode::Closed(amt) | ReturnCode::Cancelled(amt) => { + ReturnCode::Completed(amt) | ReturnCode::Dropped(amt) | ReturnCode::Cancelled(amt) => { let amt = amt.try_into().unwrap(); buf.advance(amt); Ok((StreamResult::Complete(amt), buf)) @@ -393,7 +393,7 @@ impl StreamReader { /// Reads all items from this stream and returns the list. /// /// This method will read all remaining items from this stream into a list - /// and await the stream to be closed. + /// and await the stream to be dropped. pub async fn collect(mut self) -> Vec { let mut ret = Vec::new(); loop { @@ -407,7 +407,7 @@ impl StreamReader { ret = buf; match status { StreamResult::Complete(_) => {} - StreamResult::Closed => break, + StreamResult::Dropped => break, StreamResult::Cancelled => unreachable!(), } } @@ -421,8 +421,8 @@ impl Drop for StreamReader { return; }; unsafe { - rtdebug!("stream.close-readable({})", handle); - (self.vtable.close_readable)(handle); + rtdebug!("stream.drop-readable({})", handle); + (self.vtable.drop_readable)(handle); } } } @@ -484,7 +484,7 @@ where ReturnCode::Blocked => Err((reader, buf, cleanup)), // Note that the `cleanup`, if any, is discarded here. - ReturnCode::Closed(0) => Ok((StreamResult::Closed, buf)), + ReturnCode::Dropped(0) => Ok((StreamResult::Dropped, buf)), // When an in-progress read is successfully cancelled then the // allocation that was being read into, if any, is just discarded. @@ -493,7 +493,7 @@ where // the read allocation? ReturnCode::Cancelled(0) => Ok((StreamResult::Cancelled, buf)), - ReturnCode::Completed(amt) | ReturnCode::Closed(amt) | ReturnCode::Cancelled(amt) => { + ReturnCode::Completed(amt) | ReturnCode::Dropped(amt) | ReturnCode::Cancelled(amt) => { let amt = usize::try_from(amt).unwrap(); let cur_len = buf.len(); assert!(amt <= buf.capacity() - cur_len); diff --git a/crates/rust/src/interface.rs b/crates/rust/src/interface.rs index 1b58a4af0..86a60bd3a 100644 --- a/crates/rust/src/interface.rs +++ b/crates/rust/src/interface.rs @@ -1,7 +1,7 @@ use crate::bindgen::{FunctionBindgen, POINTER_SIZE_EXPRESSION}; use crate::{ full_wit_type_name, int_repr, to_rust_ident, to_upper_camel_case, wasm_type, FnSig, Identifier, - InterfaceName, Ownership, RuntimeItem, RustFlagsRepr, RustWasm, TypeGeneration, + InterfaceName, Ownership, RuntimeItem, RustFlagsRepr, RustWasm, TypeGeneration, WasmType, }; use anyhow::Result; use heck::*; @@ -132,6 +132,32 @@ enum PayloadFor { Stream, } +fn from_core_val(ty: WasmType, val: &str) -> String { + match ty { + WasmType::I32 => format!("{val}.as_i32"), + WasmType::Pointer => format!("({val}.as_i32 as isize as *mut u8)"), + WasmType::Length => format!("({val}.as_i32 as isize as usize)"), + WasmType::I64 => format!("{val}.as_i64"), + WasmType::PointerOrI64 => { + format!("::core::mem::MaybeUninit::new({val}.as_i64 as u64)") + } + WasmType::F32 => format!("{val}.as_f32"), + WasmType::F64 => format!("{val}.as_f64"), + } +} + +fn to_core_val(ty: WasmType, val: &str) -> String { + match ty { + WasmType::I32 => format!("as_i32: {val}"), + WasmType::Pointer => format!("as_i32: {val} as isize as i32"), + WasmType::Length => format!("as_i32: {val} as isize as i32"), + WasmType::I64 => format!("as_i64: {val}"), + WasmType::PointerOrI64 => format!("as_i64: {val}.assume_init() as i64"), + WasmType::F32 => format!("as_f32: {val}"), + WasmType::F64 => format!("as_f64: {val}"), + } +} + impl<'i> InterfaceGenerator<'i> { pub(super) fn generate_exports<'a>( &mut self, @@ -536,6 +562,7 @@ macro_rules! {macro_name} {{ return; } let ordinal = map.len(); + let runtime = self.r#gen.runtime_path().to_owned(); let async_support = self.r#gen.async_support_path(); let (size, align) = if let Some(payload_type) = payload_type { ( @@ -553,23 +580,6 @@ macro_rules! {macro_name} {{ }; let size = size.size_wasm32(); let align = align.align_wasm32(); - let lift; - let lower; - let dealloc_lists; - if let Some(payload_type) = payload_type { - lift = self.lift_from_memory("ptr", &payload_type, &module); - dealloc_lists = self.deallocate_lists( - std::slice::from_ref(payload_type), - &["ptr".to_string()], - true, - &module, - ); - lower = self.lower_to_memory("ptr", "value", &payload_type, &module); - } else { - lift = format!("let _ = ptr;"); - lower = format!("let _ = (ptr, value);"); - dealloc_lists = format!("let _ = ptr;"); - } let import_prefix = match payload_for { PayloadFor::Future => "future", PayloadFor::Stream => "stream", @@ -578,42 +588,200 @@ macro_rules! {macro_name} {{ PayloadFor::Future => "Future", PayloadFor::Stream => "Stream", }; - let start_extra = match payload_for { - PayloadFor::Future => "", - PayloadFor::Stream => ", _: usize", - }; - let mut lift_fn = format!("unsafe fn lift(ptr: *mut u8) -> {name} {{ {lift} }}"); - let mut lower_fn = format!("unsafe fn lower(value: {name}, ptr: *mut u8) {{ {lower} }}"); - let mut dealloc_lists_fn = - format!("unsafe fn dealloc_lists(ptr: *mut u8) {{ {dealloc_lists} }}"); - let mut lift_arg = "lift"; - let mut lower_arg = "lower"; - let mut dealloc_lists_arg = "dealloc_lists"; - - if let PayloadFor::Stream = payload_for { - lift_arg = "lift: Some(lift)"; - lower_arg = "lower: Some(lower)"; - dealloc_lists_arg = "dealloc_lists: Some(dealloc_lists)"; - - let is_list_canonical = match payload_type { - Some(ty) => self.is_list_canonical(ty), - None => true, - }; + let mut dealloc_lists_fn; + let mut lift_fns; + let mut lower_fn; + let mut lift_args; + let mut lower_arg; + let mut dealloc_lists_arg; + let start_read_sig; + let start_write_sig; + match payload_for { + PayloadFor::Stream => { + let lift; + let lower; + let dealloc_lists; + if let Some(payload_type) = payload_type { + lift = self.lift_from_memory("ptr", &payload_type, &module); + dealloc_lists = self.deallocate_lists( + std::slice::from_ref(payload_type), + &["ptr".to_string()], + true, + &module, + ); + lower = self.lower_to_memory("ptr", "value", &payload_type, &module); + } else { + lift = format!("let _ = ptr;"); + lower = format!("let _ = (ptr, value);"); + dealloc_lists = format!("let _ = ptr;"); + } + + dealloc_lists_fn = + format!("unsafe fn dealloc_lists(ptr: *mut u8) {{ {dealloc_lists} }}"); + lift_fns = format!("unsafe fn lift(ptr: *mut u8) -> {name} {{ {lift} }}"); + lower_fn = format!("unsafe fn lower(value: {name}, ptr: *mut u8) {{ {lower} }}"); + lift_args = "lift: Some(lift)"; + lower_arg = "lower: Some(lower)"; + dealloc_lists_arg = "dealloc_lists: Some(dealloc_lists)"; + + let is_list_canonical = match payload_type { + Some(ty) => self.is_list_canonical(ty), + None => true, + }; + + if is_list_canonical { + lift_args = "lift: None"; + lower_arg = "lower: None"; + dealloc_lists_arg = "dealloc_lists: None"; + lift_fns = String::new(); + lower_fn = String::new(); + dealloc_lists_fn = String::new(); + } + + start_read_sig = "fn start_read(_: u32, _: *mut u8, _: usize) -> u32".to_owned(); + start_write_sig = + "fn start_write(_: u32, _: *const u8, _: usize) -> u32".to_owned(); + } + PayloadFor::Future => { + let lift_write; + let lift_read; + let lower; + let dealloc_lists; + let start_read; + let start_write; + if let Some(payload_type) = payload_type { + let sig = self.resolve.wasm_signature( + AbiVariant::GuestImportAsync, + &Function { + name: String::new(), + kind: FunctionKind::Freestanding, + params: vec![(String::new(), *payload_type)], + result: None, + docs: Default::default(), + stability: Stability::Unknown, + }, + ); + dealloc_lists = self.deallocate_lists( + std::slice::from_ref(payload_type), + &sig.params + .iter() + .enumerate() + .map(|(index, ty)| from_core_val(*ty, &format!("dst[{index}]"))) + .collect::>(), + sig.indirect_params, + &module, + ); + lift_read = self.lift_from_memory("src", &payload_type, &module); + start_read_sig = "fn future_read(_: u32, _: *mut u8) -> u32".to_owned(); + start_read = "unsafe extern \"C\" fn start_read(future: u32, dst: *mut u8) \ + -> u32 { future_read(future, dst) }" + .to_owned(); + if sig.indirect_params { + lift_write = self.lift_from_memory( + "(src[0].as_i32 as isize as *mut u8)", + &payload_type, + &module, + ); + let body = self.lower_to_memory("ptr", "value", &payload_type, &module); + lower = format!( + r#" + let (ptr, cleanup) = {runtime}::Cleanup::new( + ::std::alloc::Layout::from_size_align_unchecked({size}, {align}) + ); + {body} + dst[0] = {async_support}::CoreVal {{ as_i32: ptr as isize as i32 }}; + cleanup + "# + ); + start_write_sig = "fn future_write(_: u32, _: *const u8) -> u32".to_owned(); + start_write = format!( + "unsafe extern \"C\" fn start_write(future: u32, src: &{async_support}::LoweredWrite) \ + -> u32 {{ future_write(future, src[0].as_i32 as isize as *const u8) }}" + ); + } else { + lift_write = self.lift_flat( + sig.params + .iter() + .enumerate() + .map(|(index, ty)| from_core_val(*ty, &format!("src[{index}]"))) + .collect::>(), + &payload_type, + &module, + ); + let (body, results) = self.lower_flat("value", &payload_type, &module); + let moves = results + .into_iter() + .zip(&sig.params) + .enumerate() + .map(|(index, (result, ty))| { + format!( + "dst[{index}] = {async_support}::CoreVal {{ {} }};", + to_core_val(*ty, &result) + ) + }) + .collect::>() + .concat(); + lower = format!("unsafe {{ {body} {moves} None }}"); + let params = sig + .params + .iter() + .map(|ty| format!("_: {}", wasm_type(*ty))) + .collect::>() + .join(", "); + start_write_sig = format!("fn future_write(_: u32, {params}) -> u32"); + let args = sig + .params + .iter() + .enumerate() + .map(|(index, ty)| from_core_val(*ty, &format!("src[{index}]"))) + .collect::>() + .join(", "); + start_write = format!( + "unsafe extern \"C\" fn start_write(future: u32, src: &{async_support}::LoweredWrite) \ + -> u32 {{ future_write(future, {args}) }}" + ); + } + } else { + lift_write = format!("let _ = src;"); + lift_read = format!("let _ = src;"); + lower = format!("let _ = (dst, value); None"); + dealloc_lists = format!("let _ = dst;"); + start_read_sig = format!("fn future_read(_: u32) -> u32"); + start_write_sig = format!("fn future_write(_: u32) -> u32"); + start_read = format!( + "unsafe extern \"C\" fn start_read(future: u32, _: *mut u8) -> u32 {{ future_read(future) }}" + ); + start_write = format!( + "unsafe extern \"C\" fn start_write(future: u32, _: &{async_support}::LoweredWrite) \ + -> u32 {{ future_write(future) }}" + ); + } - if is_list_canonical { - lift_arg = "lift: None"; - lower_arg = "lower: None"; - dealloc_lists_arg = "dealloc_lists: None"; - lift_fn = String::new(); - lower_fn = String::new(); - dealloc_lists_fn = String::new(); + dealloc_lists_fn = format!( + "unsafe fn dealloc_lists(dst: &{async_support}::LoweredWrite) {{ {dealloc_lists} }}" + ); + lift_fns = format!( + "\ + unsafe fn lift_write(src: &{async_support}::LoweredWrite) -> {name} {{ {lift_write} }} \ + unsafe fn lift_read(src: *mut u8) -> {name} {{ {lift_read} }}\ + {start_read}\ + {start_write}\ + " + ); + lower_fn = format!( + "unsafe fn lower_write(value: {name}, dst: &mut {async_support}::LoweredWrite) \ + -> ::std::option::Option<{runtime}::Cleanup> {{ {lower} }}" + ); + lift_args = "lift_write, lift_read"; + lower_arg = "lower_write"; + dealloc_lists_arg = "dealloc_lists"; } } let code = format!( r#" #[doc(hidden)] -#[allow(unused_unsafe)] +#[allow(unused_unsafe, unused_parens)] pub mod vtable{ordinal} {{ #[cfg(not(target_arch = "wasm32"))] @@ -621,15 +789,15 @@ pub mod vtable{ordinal} {{ #[cfg(not(target_arch = "wasm32"))] unsafe extern "C" fn cancel_read(_: u32) -> u32 {{ unreachable!() }} #[cfg(not(target_arch = "wasm32"))] - unsafe extern "C" fn close_writable(_: u32) {{ unreachable!() }} + unsafe extern "C" fn drop_writable(_: u32) {{ unreachable!() }} #[cfg(not(target_arch = "wasm32"))] - unsafe extern "C" fn close_readable(_: u32) {{ unreachable!() }} + unsafe extern "C" fn drop_readable(_: u32) {{ unreachable!() }} #[cfg(not(target_arch = "wasm32"))] unsafe extern "C" fn new() -> u64 {{ unreachable!() }} #[cfg(not(target_arch = "wasm32"))] - unsafe extern "C" fn start_read(_: u32, _: *mut u8{start_extra}) -> u32 {{ unreachable!() }} + unsafe extern "C" {start_read_sig} {{ unreachable!() }} #[cfg(not(target_arch = "wasm32"))] - unsafe extern "C" fn start_write(_: u32, _: *const u8{start_extra}) -> u32 {{ unreachable!() }} + unsafe extern "C" {start_write_sig} {{ unreachable!() }} #[cfg(target_arch = "wasm32")] #[link(wasm_import_module = "{module}")] @@ -640,30 +808,30 @@ pub mod vtable{ordinal} {{ fn cancel_write(_: u32) -> u32; #[link_name = "[{import_prefix}-cancel-read-{index}]{func_name}"] fn cancel_read(_: u32) -> u32; - #[link_name = "[{import_prefix}-close-writable-{index}]{func_name}"] - fn close_writable(_: u32); - #[link_name = "[{import_prefix}-close-readable-{index}]{func_name}"] - fn close_readable(_: u32); + #[link_name = "[{import_prefix}-drop-writable-{index}]{func_name}"] + fn drop_writable(_: u32); + #[link_name = "[{import_prefix}-drop-readable-{index}]{func_name}"] + fn drop_readable(_: u32); #[link_name = "[async-lower][{import_prefix}-read-{index}]{func_name}"] - fn start_read(_: u32, _: *mut u8{start_extra}) -> u32; + {start_read_sig}; #[link_name = "[async-lower][{import_prefix}-write-{index}]{func_name}"] - fn start_write(_: u32, _: *const u8{start_extra}) -> u32; + {start_write_sig}; }} - {lift_fn} + {lift_fns} {lower_fn} {dealloc_lists_fn} pub static VTABLE: {async_support}::{camel}Vtable<{name}> = {async_support}::{camel}Vtable::<{name}> {{ cancel_write, cancel_read, - close_writable, - close_readable, + drop_writable, + drop_readable, {dealloc_lists_arg}, layout: unsafe {{ ::std::alloc::Layout::from_size_align_unchecked({size}, {align}) }}, - {lift_arg}, + {lift_args}, {lower_arg}, new, start_read, @@ -728,6 +896,12 @@ pub mod vtable{ordinal} {{ format!("unsafe {{ {} }}", String::from(f.src)) } + fn lower_flat(&mut self, value: &str, ty: &Type, module: &str) -> (String, Vec) { + let mut f = FunctionBindgen::new(self, Vec::new(), module, true); + let results = abi::lower_flat(f.r#gen.resolve, &mut f, value.into(), ty); + (String::from(f.src), results) + } + fn deallocate_lists( &mut self, types: &[Type], @@ -758,6 +932,12 @@ pub mod vtable{ordinal} {{ format!("unsafe {{ {}\n{result} }}", String::from(f.src)) } + fn lift_flat(&mut self, src: Vec, ty: &Type, module: &str) -> String { + let mut f = FunctionBindgen::new(self, Vec::new(), module, true); + let result = abi::lift_flat(f.r#gen.resolve, &mut f, src, ty); + format!("unsafe {{ {}\n{result} }}", String::from(f.src)) + } + fn generate_guest_import_body_sync( &mut self, module: &str, @@ -1744,7 +1924,7 @@ unsafe fn call_import(_params: Self::ParamsLower, _results: *mut u8) -> u32 {{ } Type::ErrorContext => { - let async_support = self.gen.async_support_path(); + let async_support = self.r#gen.async_support_path(); self.push_str(&format!("{async_support}::ErrorContext")); } } @@ -1921,7 +2101,7 @@ unsafe fn call_import(_params: Self::ParamsLower, _results: *mut u8) -> u32 {{ self.rustdoc(docs); let mut derives = BTreeSet::new(); if !self - .gen + .r#gen .opts .additional_derive_ignore .contains(&name.to_kebab_case()) @@ -2032,7 +2212,7 @@ unsafe fn call_import(_params: Self::ParamsLower, _results: *mut u8) -> u32 {{ self.rustdoc(docs); let mut derives = BTreeSet::new(); if !self - .gen + .r#gen .opts .additional_derive_ignore .contains(&name.to_kebab_case()) @@ -2193,7 +2373,7 @@ unsafe fn call_import(_params: Self::ParamsLower, _results: *mut u8) -> u32 {{ .additional_derive_ignore .contains(&name.to_kebab_case()) { - derives.extend(self.gen.opts.additional_derive_attributes.to_vec()); + derives.extend(self.r#gen.opts.additional_derive_attributes.to_vec()); } derives.extend( ["Clone", "Copy", "PartialEq", "Eq", "PartialOrd", "Ord"] diff --git a/tests/runtime-async/async/cancel-import/runner.c b/tests/runtime-async/async/cancel-import/runner.c index bfc7b476c..0eeb062ed 100644 --- a/tests/runtime-async/async/cancel-import/runner.c +++ b/tests/runtime-async/async/cancel-import/runner.c @@ -17,9 +17,9 @@ int main() { assert(RUNNER_SUBTASK_HANDLE(status) == 0); runner_waitable_status_t status2 = test_future_void_write(writer); - assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(status2) == 0); - test_future_void_close_writable(writer); + test_future_void_drop_writable(writer); } // One import in "started", one in "starting", then cancel both. @@ -52,19 +52,19 @@ int main() { assert(RUNNER_SUBTASK_HANDLE(status) == 0); // We still own the readable end of `reader2` and `writer2` since the - // subtask didn't actually start, so close it here. - test_future_void_close_readable(reader2); + // subtask didn't actually start, so drop it here. + test_future_void_drop_readable(reader2); - // Assert both read ends are closed from the POV of the write ends + // Assert both read ends are dropped from the POV of the write ends runner_waitable_status_t status2 = test_future_void_write(writer1); - assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(status2) == 0); - test_future_void_close_writable(writer1); + test_future_void_drop_writable(writer1); status2 = test_future_void_write(writer2); - assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(status2) == 0); - test_future_void_close_writable(writer2); + test_future_void_drop_writable(writer2); // reset the backpressure flag test_backpressure_set(false); diff --git a/tests/runtime-async/async/cancel-import/runner.rs b/tests/runtime-async/async/cancel-import/runner.rs index edf7422b3..7041d00ff 100644 --- a/tests/runtime-async/async/cancel-import/runner.rs +++ b/tests/runtime-async/async/cancel-import/runner.rs @@ -57,7 +57,7 @@ fn main() { backpressure_set(false); - // both channels should be closed + // both channels should be dropped tx1.write(()).await.unwrap_err(); tx2.write(()).await.unwrap_err(); }); diff --git a/tests/runtime-async/async/cancel-import/test.c b/tests/runtime-async/async/cancel-import/test.c index 0fffb8d58..c24768370 100644 --- a/tests/runtime-async/async/cancel-import/test.c +++ b/tests/runtime-async/async/cancel-import/test.c @@ -35,13 +35,13 @@ test_callback_code_t exports_test_async_pending_import_callback(test_event_t *ev } else { assert(event->event == TEST_EVENT_FUTURE_READ); assert(event->waitable == task->future); - assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_CLOSED); + assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_DROPPED); assert(TEST_WAITABLE_COUNT(event->code) == 1); exports_test_async_pending_import_return(); } test_waitable_join(task->future, 0); - exports_test_future_void_close_readable(task->future); + exports_test_future_void_drop_readable(task->future); test_waitable_set_drop(task->set); free(task); diff --git a/tests/runtime-async/async/future-cancel-read/runner.c b/tests/runtime-async/async/future-cancel-read/runner.c index 0683e633b..ae67b60f8 100644 --- a/tests/runtime-async/async/future-cancel-read/runner.c +++ b/tests/runtime-async/async/future-cancel-read/runner.c @@ -12,9 +12,9 @@ int main() { assert(status == RUNNER_SUBTASK_RETURNED); uint32_t value = 0; runner_waitable_status_t wstatus = test_future_u32_write(writer, &value); - assert(RUNNER_WAITABLE_STATE(wstatus) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(wstatus) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(wstatus) == 0); - test_future_u32_close_writable(writer); + test_future_u32_drop_writable(writer); } { @@ -26,9 +26,9 @@ int main() { uint32_t value = 0; runner_waitable_status_t wstatus = test_future_u32_write(writer, &value); - assert(RUNNER_WAITABLE_STATE(wstatus) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(wstatus) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(wstatus) == 0); - test_future_u32_close_writable(writer); + test_future_u32_drop_writable(writer); } { @@ -42,11 +42,11 @@ int main() { uint32_t to_write = 4; runner_waitable_status_t wstatus = test_future_u32_write(data_writer, &to_write); - assert(RUNNER_WAITABLE_STATE(wstatus) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(wstatus) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(wstatus) == 1); wstatus = test_future_void_write(signal_writer); - assert(RUNNER_WAITABLE_STATE(wstatus) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(wstatus) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(wstatus) == 1); runner_waitable_set_t set = runner_waitable_set_new(); diff --git a/tests/runtime-async/async/future-cancel-read/test.c b/tests/runtime-async/async/future-cancel-read/test.c index c524b7112..a4a21e583 100644 --- a/tests/runtime-async/async/future-cancel-read/test.c +++ b/tests/runtime-async/async/future-cancel-read/test.c @@ -6,7 +6,7 @@ // This is a test of a Rust-ism, nothing to do in C. test_callback_code_t exports_test_async_cancel_before_read(exports_test_future_u32_t x) { - exports_test_future_u32_close_readable(x); + exports_test_future_u32_drop_readable(x); exports_test_async_cancel_before_read_return(); return TEST_CALLBACK_CODE_EXIT; } @@ -23,7 +23,7 @@ test_callback_code_t exports_test_async_cancel_after_read(exports_test_future_u3 status = exports_test_future_u32_cancel_read(x); assert(status == TEST_WAITABLE_CANCELLED); - exports_test_future_u32_close_readable(x); + exports_test_future_u32_drop_readable(x); exports_test_async_cancel_after_read_return(); return TEST_CALLBACK_CODE_EXIT; @@ -65,17 +65,17 @@ test_callback_code_t exports_test_async_start_read_then_cancel_callback(test_eve struct start_read_then_cancel_state *state = test_context_get(); assert(event->event == TEST_EVENT_FUTURE_READ); assert(event->waitable == state->signal); - assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_CLOSED); + assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_DROPPED); assert(TEST_WAITABLE_COUNT(event->code) == 1); test_waitable_status_t status = exports_test_future_u32_cancel_read(state->data); - assert(TEST_WAITABLE_STATE(status) == TEST_WAITABLE_CLOSED); + assert(TEST_WAITABLE_STATE(status) == TEST_WAITABLE_DROPPED); assert(TEST_WAITABLE_COUNT(status) == 1); assert(state->result == 4); test_waitable_join(state->signal, 0); - exports_test_future_u32_close_readable(state->data); - exports_test_future_void_close_readable(state->signal); + exports_test_future_u32_drop_readable(state->data); + exports_test_future_void_drop_readable(state->signal); test_waitable_set_drop(state->set); exports_test_async_start_read_then_cancel_return(); diff --git a/tests/runtime-async/async/future-cancel-write/runner.c b/tests/runtime-async/async/future-cancel-write/runner.c index 1e4f3b592..46418264a 100644 --- a/tests/runtime-async/async/future-cancel-write/runner.c +++ b/tests/runtime-async/async/future-cancel-write/runner.c @@ -15,16 +15,16 @@ int main() { runner_waitable_status_t status = test_future_string_write(writer, &string); assert(status == RUNNER_WAITABLE_STATUS_BLOCKED); - test_take_then_close(reader); + test_take_then_drop(reader); runner_waitable_join(writer, set); runner_waitable_set_wait(set, &event); assert(event.event == RUNNER_EVENT_FUTURE_WRITE); assert(event.waitable == writer); - assert(event.code == RUNNER_WAITABLE_CLOSED); + assert(event.code == RUNNER_WAITABLE_DROPPED); runner_waitable_join(writer, 0); - test_future_string_close_writable(writer); + test_future_string_drop_writable(writer); } { @@ -38,12 +38,12 @@ int main() { assert(RUNNER_WAITABLE_STATE(status) == RUNNER_WAITABLE_CANCELLED); assert(RUNNER_WAITABLE_COUNT(status) == 0); - test_future_string_close_readable(reader); + test_future_string_drop_readable(reader); status = test_future_string_write(writer, &string); - assert(RUNNER_WAITABLE_STATE(status) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(status) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(status) == 0); - test_future_string_close_writable(writer); + test_future_string_drop_writable(writer); } { @@ -57,10 +57,10 @@ int main() { assert(status2 == RUNNER_SUBTASK_RETURNED); status = test_future_string_cancel_write(writer); - assert(RUNNER_WAITABLE_STATE(status) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(status) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(status) == 1); - test_future_string_close_writable(writer); + test_future_string_drop_writable(writer); } runner_waitable_set_drop(set); diff --git a/tests/runtime-async/async/future-cancel-write/runner.rs b/tests/runtime-async/async/future-cancel-write/runner.rs index 06103752d..9140768c6 100644 --- a/tests/runtime-async/async/future-cancel-write/runner.rs +++ b/tests/runtime-async/async/future-cancel-write/runner.rs @@ -1,6 +1,6 @@ include!(env!("BINDINGS")); -use crate::my::test::i::{read_and_drop, take_then_close}; +use crate::my::test::i::{read_and_drop, take_then_drop}; use futures::task::noop_waker_ref; use std::future::Future; use std::task::Context; @@ -11,7 +11,7 @@ fn main() { // cancel from the other end let (tx, rx) = wit_future::new(|| unreachable!()); let f1 = async { tx.write("hello".into()).await }; - let f2 = async { take_then_close(rx) }; + let f2 = async { take_then_drop(rx) }; let (result, ()) = futures::join!(f1, f2); assert_eq!(result.unwrap_err().value, "hello"); @@ -39,7 +39,7 @@ fn main() { _ => unreachable!(), }; - // cancel after we hit the intrinsic and then close the other end + // cancel after we hit the intrinsic and then drop the other end let (tx, rx) = wit_future::new::(|| unreachable!()); let mut future = Box::pin(tx.write("hello3".into())); assert!(future @@ -48,8 +48,8 @@ fn main() { .is_pending()); drop(rx); match future.as_mut().cancel() { - FutureWriteCancel::Closed(val) => assert_eq!(val, "hello3"), - other => panic!("expected closed, got: {other:?}"), + FutureWriteCancel::Dropped(val) => assert_eq!(val, "hello3"), + other => panic!("expected dropped, got: {other:?}"), }; // Start a write, wait for it to be pending, then go complete the write diff --git a/tests/runtime-async/async/future-cancel-write/test.c b/tests/runtime-async/async/future-cancel-write/test.c index bbb5ae0a9..7147e4465 100644 --- a/tests/runtime-async/async/future-cancel-write/test.c +++ b/tests/runtime-async/async/future-cancel-write/test.c @@ -3,17 +3,17 @@ #include #include -void exports_test_take_then_close(exports_test_future_string_t x) { - exports_test_future_string_close_readable(x); +void exports_test_take_then_drop(exports_test_future_string_t x) { + exports_test_future_string_drop_readable(x); } test_callback_code_t exports_test_async_read_and_drop(exports_test_future_string_t x) { test_string_t string; test_waitable_status_t status = exports_test_future_string_read(x, &string); - assert(TEST_WAITABLE_STATE(status) == TEST_WAITABLE_CLOSED); + assert(TEST_WAITABLE_STATE(status) == TEST_WAITABLE_DROPPED); assert(TEST_WAITABLE_COUNT(status) == 1); - exports_test_future_string_close_readable(x); + exports_test_future_string_drop_readable(x); test_string_free(&string); exports_test_async_read_and_drop_return(); diff --git a/tests/runtime-async/async/future-cancel-write/test.rs b/tests/runtime-async/async/future-cancel-write/test.rs index 673cb56c6..0a4e67475 100644 --- a/tests/runtime-async/async/future-cancel-write/test.rs +++ b/tests/runtime-async/async/future-cancel-write/test.rs @@ -7,7 +7,7 @@ struct Component; export!(Component); impl crate::exports::my::test::i::Guest for Component { - fn take_then_close(x: FutureReader) { + fn take_then_drop(x: FutureReader) { drop(x) } async fn read_and_drop(x: FutureReader) { diff --git a/tests/runtime-async/async/future-cancel-write/test.wit b/tests/runtime-async/async/future-cancel-write/test.wit index 17d824e48..d066bc3c4 100644 --- a/tests/runtime-async/async/future-cancel-write/test.wit +++ b/tests/runtime-async/async/future-cancel-write/test.wit @@ -1,7 +1,7 @@ package my:test; interface i { - take-then-close: func(x: future); + take-then-drop: func(x: future); read-and-drop: async func(x: future); } diff --git a/tests/runtime-async/async/pending-import/runner.c b/tests/runtime-async/async/pending-import/runner.c index e23ab2df8..29cc8baa1 100644 --- a/tests/runtime-async/async/pending-import/runner.c +++ b/tests/runtime-async/async/pending-import/runner.c @@ -13,9 +13,9 @@ int main() { assert(subtask != 0); runner_waitable_status_t status2 = test_future_void_write(writer); - assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(status2) == 1); - test_future_void_close_writable(writer); + test_future_void_drop_writable(writer); runner_waitable_set_t set = runner_waitable_set_new(); runner_waitable_join(subtask, set); diff --git a/tests/runtime-async/async/pending-import/test.c b/tests/runtime-async/async/pending-import/test.c index 4dc4ff9ef..4a666e889 100644 --- a/tests/runtime-async/async/pending-import/test.c +++ b/tests/runtime-async/async/pending-import/test.c @@ -26,12 +26,12 @@ test_callback_code_t exports_test_async_pending_import_callback(test_event_t *ev struct my_task *task = test_context_get(); assert(event->event == TEST_EVENT_FUTURE_READ); assert(event->waitable == task->future); - assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_CLOSED); + assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_DROPPED); assert(TEST_WAITABLE_COUNT(event->code) == 1); exports_test_async_pending_import_return(); test_waitable_join(task->future, 0); - exports_test_future_void_close_readable(task->future); + exports_test_future_void_drop_readable(task->future); test_waitable_set_drop(task->set); free(task); diff --git a/tests/runtime-async/async/ping-pong/runner.c b/tests/runtime-async/async/ping-pong/runner.c index 2dc33aa39..e86085eb6 100644 --- a/tests/runtime-async/async/ping-pong/runner.c +++ b/tests/runtime-async/async/ping-pong/runner.c @@ -20,9 +20,9 @@ int main() { runner_string_t string_tmp; runner_string_set(&string_tmp, "hello"); runner_waitable_status_t status2 = test_future_string_write(writer, &string_tmp); - assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(status2) == 1); - test_future_string_close_writable(writer); + test_future_string_drop_writable(writer); // Wait for the subtask to complete runner_waitable_set_t set = runner_waitable_set_new(); @@ -38,10 +38,10 @@ int main() { // Read the result from our future status2 = test_future_string_read(ping_result, &string_tmp); - assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(status2) == 1); assert(memcmp(string_tmp.ptr, "helloworld", string_tmp.len) == 0); - test_future_string_close_readable(ping_result); + test_future_string_drop_readable(ping_result); // Start the `pong` subtask runner_string_t pong_result; @@ -52,10 +52,10 @@ int main() { // Write our string to the "pong" subtask status2 = test_future_string_write(writer, &string_tmp); - assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(status2) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(status2) == 1); runner_string_free(&string_tmp); - test_future_string_close_writable(writer); + test_future_string_drop_writable(writer); // Wait for "pong" to complete runner_waitable_join(pong, set); diff --git a/tests/runtime-async/async/ping-pong/test.c b/tests/runtime-async/async/ping-pong/test.c index e0301066c..cd7cf7f85 100644 --- a/tests/runtime-async/async/ping-pong/test.c +++ b/tests/runtime-async/async/ping-pong/test.c @@ -45,10 +45,10 @@ test_callback_code_t exports_test_async_ping_callback(test_event_t *event) { // future. assert(event->event == TEST_EVENT_FUTURE_READ); assert(event->waitable == task->future); - assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_CLOSED); + assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_DROPPED); assert(TEST_WAITABLE_COUNT(event->code) == 1); test_waitable_join(task->future, 0); - exports_test_future_string_close_readable(task->future); + exports_test_future_string_drop_readable(task->future); task->future = 0; // Create a new future and start the return of our task with this future. @@ -83,10 +83,10 @@ test_callback_code_t exports_test_async_ping_callback(test_event_t *event) { // of the future. assert(event->event == TEST_EVENT_FUTURE_WRITE); assert(event->waitable == task->writer); - assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_CLOSED); + assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_DROPPED); assert(TEST_WAITABLE_COUNT(event->code) == 1); test_waitable_join(task->writer, 0); - exports_test_future_string_close_writable(task->writer); + exports_test_future_string_drop_writable(task->writer); task->writer = 0; // Drop our waitable set, it's no longer needed. @@ -134,12 +134,12 @@ test_callback_code_t exports_test_async_pong_callback(test_event_t *event) { // assert this event is a future read completion assert(event->event == TEST_EVENT_FUTURE_READ); assert(event->waitable == task->future); - assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_CLOSED); + assert(TEST_WAITABLE_STATE(event->code) == TEST_WAITABLE_DROPPED); assert(TEST_WAITABLE_COUNT(event->code) == 1); // deallocate/destroy our future test_waitable_join(task->future, 0); - exports_test_future_string_close_readable(task->future); + exports_test_future_string_drop_readable(task->future); task->future = 0; // deallocate/destroy our waitable set diff --git a/tests/runtime-async/async/simple-future/runner.c b/tests/runtime-async/async/simple-future/runner.c index aaf34511b..b02aafa45 100644 --- a/tests/runtime-async/async/simple-future/runner.c +++ b/tests/runtime-async/async/simple-future/runner.c @@ -20,10 +20,10 @@ int main() { runner_waitable_set_wait(set, &event); assert(event.event == RUNNER_EVENT_FUTURE_WRITE); assert(event.waitable == writer); - assert(RUNNER_WAITABLE_STATE(event.code) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(event.code) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(event.code) == 1); - test_future_void_close_writable(writer); + test_future_void_drop_writable(writer); runner_waitable_set_drop(set); } @@ -34,7 +34,7 @@ int main() { runner_waitable_status_t status = test_future_void_write(writer); assert(status == RUNNER_WAITABLE_STATUS_BLOCKED); - runner_subtask_status_t subtask = test_async_close_future(reader); + runner_subtask_status_t subtask = test_async_drop_future(reader); assert(RUNNER_SUBTASK_STATE(subtask) == RUNNER_SUBTASK_RETURNED); runner_waitable_set_t set = runner_waitable_set_new(); @@ -43,10 +43,10 @@ int main() { runner_waitable_set_wait(set, &event); assert(event.event == RUNNER_EVENT_FUTURE_WRITE); assert(event.waitable == writer); - assert(RUNNER_WAITABLE_STATE(event.code) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(event.code) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(event.code) == 0); - test_future_void_close_writable(writer); + test_future_void_drop_writable(writer); runner_waitable_set_drop(set); } } diff --git a/tests/runtime-async/async/simple-future/runner.rs b/tests/runtime-async/async/simple-future/runner.rs index ffddcef92..856b3a9ac 100644 --- a/tests/runtime-async/async/simple-future/runner.rs +++ b/tests/runtime-async/async/simple-future/runner.rs @@ -9,7 +9,7 @@ fn main() { assert!(res.is_ok()); let (tx, rx) = wit_future::new(|| unreachable!()); - let (res, ()) = futures::join!(tx.write(()), close_future(rx)); + let (res, ()) = futures::join!(tx.write(()), drop_future(rx)); assert!(res.is_err()); }); } diff --git a/tests/runtime-async/async/simple-future/test.c b/tests/runtime-async/async/simple-future/test.c index a04970033..38d20c2e7 100644 --- a/tests/runtime-async/async/simple-future/test.c +++ b/tests/runtime-async/async/simple-future/test.c @@ -5,9 +5,9 @@ test_subtask_status_t exports_test_async_read_future(exports_test_future_void_t future) { test_waitable_status_t status = exports_test_future_void_read(future); - assert(TEST_WAITABLE_STATE(status) == TEST_WAITABLE_CLOSED); + assert(TEST_WAITABLE_STATE(status) == TEST_WAITABLE_DROPPED); assert(TEST_WAITABLE_COUNT(status) == 1); - exports_test_future_void_close_readable(future); + exports_test_future_void_drop_readable(future); exports_test_async_read_future_return(); return TEST_CALLBACK_CODE_EXIT; } @@ -16,12 +16,12 @@ test_subtask_status_t exports_test_async_read_future_callback(test_event_t *even assert(0); } -test_subtask_status_t exports_test_async_close_future(exports_test_future_void_t future) { - exports_test_future_void_close_readable(future); - exports_test_async_close_future_return(); +test_subtask_status_t exports_test_async_drop_future(exports_test_future_void_t future) { + exports_test_future_void_drop_readable(future); + exports_test_async_drop_future_return(); return TEST_CALLBACK_CODE_EXIT; } -test_subtask_status_t exports_test_async_close_future_callback(test_event_t *event) { +test_subtask_status_t exports_test_async_drop_future_callback(test_event_t *event) { assert(0); } diff --git a/tests/runtime-async/async/simple-future/test.rs b/tests/runtime-async/async/simple-future/test.rs index d1261b08a..8de20af92 100644 --- a/tests/runtime-async/async/simple-future/test.rs +++ b/tests/runtime-async/async/simple-future/test.rs @@ -11,7 +11,7 @@ impl crate::exports::my::test::i::Guest for Component { x.await } - async fn close_future(x: FutureReader<()>) { + async fn drop_future(x: FutureReader<()>) { drop(x); } } diff --git a/tests/runtime-async/async/simple-future/test.wit b/tests/runtime-async/async/simple-future/test.wit index 401a8bbb1..adf71600f 100644 --- a/tests/runtime-async/async/simple-future/test.wit +++ b/tests/runtime-async/async/simple-future/test.wit @@ -2,7 +2,7 @@ package my:test; interface i { read-future: async func(x: future); - close-future: async func(x: future); + drop-future: async func(x: future); } world test { diff --git a/tests/runtime-async/async/simple-stream-payload/runner.c b/tests/runtime-async/async/simple-stream-payload/runner.c index 5153abd9b..209ef761a 100644 --- a/tests/runtime-async/async/simple-stream-payload/runner.c +++ b/tests/runtime-async/async/simple-stream-payload/runner.c @@ -43,12 +43,12 @@ int main() { runner_waitable_set_wait(set, &event); assert(event.event == RUNNER_EVENT_STREAM_WRITE); assert(event.waitable == writer); - assert(RUNNER_WAITABLE_STATE(event.code) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(event.code) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(event.code) == 2); // clean up the writer runner_waitable_join(writer, 0); - test_stream_u8_close_writable(writer); + test_stream_u8_drop_writable(writer); // wait for the subtask to complete runner_waitable_join(subtask, set); diff --git a/tests/runtime-async/async/simple-stream-payload/runner.rs b/tests/runtime-async/async/simple-stream-payload/runner.rs index 1c9e2829b..8719417a1 100644 --- a/tests/runtime-async/async/simple-stream-payload/runner.rs +++ b/tests/runtime-async/async/simple-stream-payload/runner.rs @@ -22,9 +22,9 @@ fn main() { assert_eq!(result, StreamResult::Complete(2)); assert_eq!(ret.remaining(), 0); - // write to a closed stream + // write to a dropped stream let (result, ret) = tx.write(vec![0]).await; - assert_eq!(result, StreamResult::Closed); + assert_eq!(result, StreamResult::Dropped); assert_eq!(ret.remaining(), 1); }; let ((), ()) = futures::join!(test, read_stream(rx)); diff --git a/tests/runtime-async/async/simple-stream-payload/test.c b/tests/runtime-async/async/simple-stream-payload/test.c index 6bac524bd..8b9649ebe 100644 --- a/tests/runtime-async/async/simple-stream-payload/test.c +++ b/tests/runtime-async/async/simple-stream-payload/test.c @@ -46,7 +46,7 @@ test_subtask_status_t exports_test_async_read_stream_callback(test_event_t *even // clean up resources test_waitable_join(STREAM, 0); - exports_test_stream_u8_close_readable(STREAM); + exports_test_stream_u8_drop_readable(STREAM); test_waitable_set_drop(SET); diff --git a/tests/runtime-async/async/simple-stream-payload/test.rs b/tests/runtime-async/async/simple-stream-payload/test.rs index ccc50fcfe..375b6f716 100644 --- a/tests/runtime-async/async/simple-stream-payload/test.rs +++ b/tests/runtime-async/async/simple-stream-payload/test.rs @@ -28,7 +28,7 @@ impl crate::exports::my::test::i::Guest for Component { assert_eq!(result, StreamResult::Complete(1)); assert_eq!(buf, [4]); - // close + // drop drop(x); } } diff --git a/tests/runtime-async/async/simple-stream/runner.c b/tests/runtime-async/async/simple-stream/runner.c index 984c50a18..9e7bfdfe9 100644 --- a/tests/runtime-async/async/simple-stream/runner.c +++ b/tests/runtime-async/async/simple-stream/runner.c @@ -31,18 +31,18 @@ int main() { assert(RUNNER_WAITABLE_STATE(status) == RUNNER_WAITABLE_COMPLETED); assert(RUNNER_WAITABLE_COUNT(status) == 2); - // write, but see it closed + // write, but see it dropped status = test_stream_void_write(writer, 2); assert(status == RUNNER_WAITABLE_STATUS_BLOCKED); runner_waitable_set_wait(set, &event); assert(event.event == RUNNER_EVENT_STREAM_WRITE); assert(event.waitable == writer); - assert(RUNNER_WAITABLE_STATE(event.code) == RUNNER_WAITABLE_CLOSED); + assert(RUNNER_WAITABLE_STATE(event.code) == RUNNER_WAITABLE_DROPPED); assert(RUNNER_WAITABLE_COUNT(event.code) == 0); // clean up the writer runner_waitable_join(writer, 0); - test_stream_void_close_writable(writer); + test_stream_void_drop_writable(writer); // wait for the subtask to complete runner_waitable_join(subtask, set); diff --git a/tests/runtime-async/async/simple-stream/runner.rs b/tests/runtime-async/async/simple-stream/runner.rs index 1cbd477da..7d04aa214 100644 --- a/tests/runtime-async/async/simple-stream/runner.rs +++ b/tests/runtime-async/async/simple-stream/runner.rs @@ -19,7 +19,7 @@ fn main() { // write two items again let (result, ret) = tx.write(vec![(), ()]).await; - assert_eq!(result, StreamResult::Closed); + assert_eq!(result, StreamResult::Dropped); assert_eq!(ret.remaining(), 2); }; let ((), ()) = futures::join!(test, read_stream(rx)); diff --git a/tests/runtime-async/async/simple-stream/test.c b/tests/runtime-async/async/simple-stream/test.c index 90f147722..e0c875a25 100644 --- a/tests/runtime-async/async/simple-stream/test.c +++ b/tests/runtime-async/async/simple-stream/test.c @@ -28,7 +28,7 @@ test_subtask_status_t exports_test_async_read_stream_callback(test_event_t *even assert(TEST_WAITABLE_COUNT(event->code) == 2); test_waitable_join(STREAM, 0); - exports_test_stream_void_close_readable(STREAM); + exports_test_stream_void_drop_readable(STREAM); test_waitable_set_drop(SET); From 060520a078f0ed791a6385fb8bc190497557ea03 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 6 Jun 2025 14:20:56 -0600 Subject: [PATCH 2/2] fix rust codegen build errors Signed-off-by: Joel Dice --- crates/rust/src/interface.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/rust/src/interface.rs b/crates/rust/src/interface.rs index 86a60bd3a..e916b128b 100644 --- a/crates/rust/src/interface.rs +++ b/crates/rust/src/interface.rs @@ -674,7 +674,7 @@ macro_rules! {macro_name} {{ lift_read = self.lift_from_memory("src", &payload_type, &module); start_read_sig = "fn future_read(_: u32, _: *mut u8) -> u32".to_owned(); start_read = "unsafe extern \"C\" fn start_read(future: u32, dst: *mut u8) \ - -> u32 { future_read(future, dst) }" + -> u32 { unsafe { future_read(future, dst) } }" .to_owned(); if sig.indirect_params { lift_write = self.lift_from_memory( @@ -686,7 +686,7 @@ macro_rules! {macro_name} {{ lower = format!( r#" let (ptr, cleanup) = {runtime}::Cleanup::new( - ::std::alloc::Layout::from_size_align_unchecked({size}, {align}) + unsafe {{ ::std::alloc::Layout::from_size_align_unchecked({size}, {align}) }} ); {body} dst[0] = {async_support}::CoreVal {{ as_i32: ptr as isize as i32 }}; @@ -696,7 +696,7 @@ macro_rules! {macro_name} {{ start_write_sig = "fn future_write(_: u32, _: *const u8) -> u32".to_owned(); start_write = format!( "unsafe extern \"C\" fn start_write(future: u32, src: &{async_support}::LoweredWrite) \ - -> u32 {{ future_write(future, src[0].as_i32 as isize as *const u8) }}" + -> u32 {{ unsafe {{ future_write(future, src[0].as_i32 as isize as *const u8) }} }}" ); } else { lift_write = self.lift_flat( @@ -738,7 +738,7 @@ macro_rules! {macro_name} {{ .join(", "); start_write = format!( "unsafe extern \"C\" fn start_write(future: u32, src: &{async_support}::LoweredWrite) \ - -> u32 {{ future_write(future, {args}) }}" + -> u32 {{ unsafe {{ future_write(future, {args}) }} }}" ); } } else { @@ -749,11 +749,12 @@ macro_rules! {macro_name} {{ start_read_sig = format!("fn future_read(_: u32) -> u32"); start_write_sig = format!("fn future_write(_: u32) -> u32"); start_read = format!( - "unsafe extern \"C\" fn start_read(future: u32, _: *mut u8) -> u32 {{ future_read(future) }}" + "unsafe extern \"C\" fn start_read(future: u32, _: *mut u8) \ + -> u32 {{ unsafe {{ future_read(future) }} }}" ); start_write = format!( "unsafe extern \"C\" fn start_write(future: u32, _: &{async_support}::LoweredWrite) \ - -> u32 {{ future_write(future) }}" + -> u32 {{ unsafe {{ future_write(future) }} }}" ); }