diff --git a/Cargo.lock b/Cargo.lock index 1b4a4ac0a..ee0bb54e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,6 +94,12 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + [[package]] name = "cfg-if" version = "1.0.3" @@ -1338,6 +1344,7 @@ name = "wit-bindgen-rust" version = "0.48.1" dependencies = [ "anyhow", + "bytes", "clap", "futures", "heck", diff --git a/crates/rust/Cargo.toml b/crates/rust/Cargo.toml index ca96966ae..9b23b0c4d 100644 --- a/crates/rust/Cargo.toml +++ b/crates/rust/Cargo.toml @@ -34,6 +34,7 @@ wit-bindgen = { path = '../guest-rust', features = ['async'] } test-helpers = { path = '../test-helpers' } # For use with the custom attributes test serde_json = "1" +bytes = "1" [features] serde = ['dep:serde', 'wit-bindgen-core/serde'] diff --git a/crates/rust/src/bindgen.rs b/crates/rust/src/bindgen.rs index b83da0058..0e3007ab6 100644 --- a/crates/rust/src/bindgen.rs +++ b/crates/rust/src/bindgen.rs @@ -670,11 +670,15 @@ impl Bindgen for FunctionBindgen<'_, '_> { let val = format!("vec{}", tmp); let ptr = format!("ptr{}", tmp); let len = format!("len{}", tmp); + let vec = self.r#gen.path_to_vec(); if realloc.is_none() { self.push_str(&format!("let {} = {};\n", val, operands[0])); } else { let op0 = operands.pop().unwrap(); - self.push_str(&format!("let {} = ({}).into_boxed_slice();\n", val, op0)); + self.push_str(&format!( + "let {} = <_ as Into<{vec}<_>>>::into({}).into_boxed_slice();\n", + val, op0 + )); } self.push_str(&format!("let {} = {}.as_ptr().cast::();\n", ptr, val)); self.push_str(&format!("let {} = {}.len();\n", len, val)); @@ -691,7 +695,7 @@ impl Bindgen for FunctionBindgen<'_, '_> { self.push_str(&format!("let {} = {};\n", len, operands[1])); let vec = self.r#gen.path_to_vec(); let result = format!( - "{vec}::from_raw_parts({}.cast(), {1}, {1})", + "<_ as From<{vec}<_>>>::from({vec}::from_raw_parts({}.cast(), {1}, {1}))", operands[0], len ); results.push(result); diff --git a/crates/rust/src/lib.rs b/crates/rust/src/lib.rs index fd92b1953..99c14a740 100644 --- a/crates/rust/src/lib.rs +++ b/crates/rust/src/lib.rs @@ -432,7 +432,8 @@ impl RustWasm { } self.src.push_str("mod _rt {\n"); - self.src.push_str("#![allow(dead_code, clippy::all)]\n"); + self.src + .push_str("#![allow(dead_code, unused_imports, clippy::all)]\n"); let mut emitted = IndexSet::new(); while !self.rt_module.is_empty() { for item in mem::take(&mut self.rt_module) { diff --git a/crates/rust/tests/codegen.rs b/crates/rust/tests/codegen.rs index e84b4b368..346e21961 100644 --- a/crates/rust/tests/codegen.rs +++ b/crates/rust/tests/codegen.rs @@ -31,3 +31,140 @@ mod inline_and_path { generate_all, }); } + +#[allow(unused)] +mod newtyped_list { + use std::ops::Deref; + + wit_bindgen::generate!({ + inline: r#" + package test:newtyped-list; + + interface byte { + type typed-list-of-byte = list; + type newtyped-list-of-byte = list; + + record rec-of-lists { + l: list, + tl: typed-list-of-byte, + nl: newtyped-list-of-byte, + } + + use-list-of-byte: func(l: list) -> list; + use-typed-list-of-byte: func(tl: typed-list-of-byte) -> typed-list-of-byte; + use-newtyped-list-of-byte: func(nl: newtyped-list-of-byte) -> newtyped-list-of-byte; + use-rec-of-lists: func(t: rec-of-lists) -> rec-of-lists; + } + + interface noncopy-byte { + // this will be new-typed by a non-copy struct + type noncopy-byte = u8; + + type newtyped-list-of-noncopy-byte = list; + type typed-list-of-noncopy-byte = list; + + record rec-of-lists-of-noncopy-byte { + ntl: newtyped-list-of-noncopy-byte, + tl: typed-list-of-noncopy-byte, + l: list, + } + + use-newtyped-list-of-noncopy-byte: func(nl: newtyped-list-of-noncopy-byte) -> newtyped-list-of-noncopy-byte; + use-typed-list-of-noncopy-byte: func(tl: typed-list-of-noncopy-byte) -> typed-list-of-noncopy-byte; + use-list-of-noncopy-byte: func(l: list) -> list; + use-rec-of-lists-of-noncopy-byte: func(t: rec-of-lists-of-noncopy-byte) -> rec-of-lists-of-noncopy-byte; + } + + world test { + import byte; + export byte; + import noncopy-byte; + export noncopy-byte; + } + "#, + with: { + "test:newtyped-list/byte/newtyped-list-of-byte": crate::newtyped_list::NewtypedListOfByte, + "test:newtyped-list/noncopy-byte/noncopy-byte": crate::newtyped_list::NoncopyByte, + "test:newtyped-list/noncopy-byte/newtyped-list-of-noncopy-byte": crate::newtyped_list::NewtypedListofNoncopyByte, + } + }); + + #[derive(Debug, Clone)] + pub struct NewtypedListOfByte(Vec); + + impl From> for NewtypedListOfByte { + fn from(value: Vec) -> Self { + NewtypedListOfByte(value) + } + } + + impl From for Vec { + fn from(value: NewtypedListOfByte) -> Self { + value.0 + } + } + + impl Deref for NewtypedListOfByte { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + #[derive(Debug, Clone)] + pub struct NoncopyByte(u8); + + #[derive(Debug, Clone)] + pub struct NewtypedListofNoncopyByte(Vec); + + impl From> for NewtypedListofNoncopyByte { + fn from(value: Vec) -> Self { + NewtypedListofNoncopyByte(value) + } + } + + impl From for Vec { + fn from(value: NewtypedListofNoncopyByte) -> Self { + value.0 + } + } + + impl Deref for NewtypedListofNoncopyByte { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } +} +#[allow(unused)] +mod retyped_list { + use std::ops::Deref; + + wit_bindgen::generate!({ + inline: r#" + package test:retyped-list; + + interface bytes { + // this will be the `Bytes` type from the bytes crate + type retyped-list-as-bytes = list; + + record rec-bytes { + rl: retyped-list-as-bytes, + } + + use-retyped-list-as-bytes: func(ri: retyped-list-as-bytes) -> retyped-list-as-bytes; + use-rec-of-retyped-list-as-bytes: func(rl: retyped-list-as-bytes) -> retyped-list-as-bytes; + } + + world test { + import bytes; + export bytes; + } + "#, + with: { + "test:retyped-list/bytes/retyped-list-as-bytes": bytes::Bytes, + } + }); +}