diff --git a/crates/rust/src/interface.rs b/crates/rust/src/interface.rs index d8a601dbc..5c44bcefa 100644 --- a/crates/rust/src/interface.rs +++ b/crates/rust/src/interface.rs @@ -1113,6 +1113,30 @@ macro_rules! {macro_name} {{ } fn print_ty(&mut self, ty: &Type, mode: TypeMode) { + // If we have a typedef of a string or a list, the typedef is an alias + // for `String` or `Vec`. If this is a borrow, instead of borrowing + // them as `&String` or `&Vec`, use `&str` or `&[T]` so that callers + // don't need to create owned copies. + if let Type::Id(id) = ty { + let id = dealias(self.resolve, *id); + let typedef = &self.resolve.types[id]; + match &typedef.kind { + TypeDefKind::Type(Type::String) => { + if let Some(lt) = mode.lifetime { + self.print_borrowed_str(lt); + return; + } + } + TypeDefKind::List(element) => { + if mode.lifetime.is_some() { + self.print_list(element, mode); + return; + } + } + _ => {} + } + } + match ty { Type::Id(t) => self.print_tyid(*t, mode), Type::Bool => self.push_str("bool"), diff --git a/crates/rust/tests/codegen.rs b/crates/rust/tests/codegen.rs index b5757b3df..ad2310e3c 100644 --- a/crates/rust/tests/codegen.rs +++ b/crates/rust/tests/codegen.rs @@ -82,6 +82,58 @@ mod strings { } } +/// Like `strings` but with a type alias. +mod aliased_strings { + wit_bindgen::generate!({ + inline: " + package my:strings; + + world not-used-name { + import cat: interface { + type my-string = string; + foo: func(x: my-string); + bar: func() -> my-string; + } + } + ", + }); + + #[allow(dead_code)] + fn test() { + // Test the argument is `&str`. + cat::foo("hello"); + + // Test the return type is `String`. + let _t: String = cat::bar(); + } +} + +/// Like `aliased_string` but with lists instead of strings. +mod aliased_lists { + wit_bindgen::generate!({ + inline: " + package my:strings; + + world not-used-name { + import cat: interface { + type my-list = list; + foo: func(x: my-list); + bar: func() -> my-list; + } + } + ", + }); + + #[allow(dead_code)] + fn test() { + // Test the argument is `&[u8]`. + cat::foo(b"hello"); + + // Test the return type is `Vec`. + let _t: Vec = cat::bar(); + } +} + mod run_ctors_once_workaround { wit_bindgen::generate!({ inline: " @@ -96,7 +148,7 @@ mod run_ctors_once_workaround { }); } -/// Like `strings` but with raw_strings`. +/// Like `strings` but with `raw_strings`. mod raw_strings { wit_bindgen::generate!({ inline: "