Skip to content

Commit 4f52883

Browse files
authored
fix a few stream/future issues (#1118)
- The generated lift/lower code for stream/future payloads was not always calculating module paths correctly when generating type names. - Also, we were moving raw pointers into `async move` blocks and returning them without capturing the pointed-to memory. This would have been caught by runtime tests, but we don't have those yet since the Wasmtime async PR hasn't been merged yet. Fortunately, it was easy enough to find and fix when I updated that PR to use the latest wit-bindgen. - The generated lift/lower code for reading and writing streams needs to return a `Box<dyn Future>` that captures the lifetimes of the parameters. Signed-off-by: Joel Dice <[email protected]>
1 parent e067c16 commit 4f52883

File tree

4 files changed

+74
-65
lines changed

4 files changed

+74
-65
lines changed

crates/guest-rust/rt/src/async_support/stream_support.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ fn ceiling(x: usize, y: usize) -> usize {
2828

2929
#[doc(hidden)]
3030
pub struct StreamVtable<T> {
31-
pub write: fn(future: u32, values: &[T]) -> Pin<Box<dyn Future<Output = Option<usize>>>>,
31+
pub write: fn(future: u32, values: &[T]) -> Pin<Box<dyn Future<Output = Option<usize>> + '_>>,
3232
pub read: fn(
3333
future: u32,
3434
values: &mut [MaybeUninit<T>],
35-
) -> Pin<Box<dyn Future<Output = Option<usize>>>>,
35+
) -> Pin<Box<dyn Future<Output = Option<usize>> + '_>>,
3636
pub cancel_write: fn(future: u32),
3737
pub cancel_read: fn(future: u32),
3838
pub close_writable: fn(future: u32),

crates/rust/src/bindgen.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
475475
.as_ref()
476476
.map(|ty| {
477477
self.gen
478-
.full_type_name_owned(ty, Identifier::StreamOrFuturePayload)
478+
.type_name_owned_with_id(ty, Identifier::StreamOrFuturePayload)
479479
})
480480
.unwrap_or_else(|| "()".into());
481481
let ordinal = self.gen.gen.future_payloads.get_index_of(&name).unwrap();
@@ -496,7 +496,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
496496
let op = &operands[0];
497497
let name = self
498498
.gen
499-
.full_type_name_owned(payload, Identifier::StreamOrFuturePayload);
499+
.type_name_owned_with_id(payload, Identifier::StreamOrFuturePayload);
500500
let ordinal = self.gen.gen.stream_payloads.get_index_of(&name).unwrap();
501501
let path = self.gen.path_to_root();
502502
results.push(format!(

crates/rust/src/interface.rs

Lines changed: 55 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,8 @@ macro_rules! {macro_name} {{
483483
}
484484

485485
fn generate_payloads(&mut self, prefix: &str, func: &Function, interface: Option<&WorldKey>) {
486+
let old_identifier = mem::replace(&mut self.identifier, Identifier::StreamOrFuturePayload);
487+
486488
for (index, ty) in func
487489
.find_futures_and_streams(self.resolve)
488490
.into_iter()
@@ -500,7 +502,7 @@ macro_rules! {macro_name} {{
500502
match &self.resolve.types[ty].kind {
501503
TypeDefKind::Future(payload_type) => {
502504
let name = if let Some(payload_type) = payload_type {
503-
self.full_type_name_owned(payload_type, Identifier::StreamOrFuturePayload)
505+
self.type_name_owned(payload_type)
504506
} else {
505507
"()".into()
506508
};
@@ -533,7 +535,7 @@ macro_rules! {macro_name} {{
533535
(String::new(), "let value = ();\n".into())
534536
};
535537

536-
let box_ = format!("super::super::{}", self.path_to_box());
538+
let box_ = self.path_to_box();
537539
let code = format!(
538540
r#"
539541
#[doc(hidden)]
@@ -545,7 +547,7 @@ pub mod vtable{ordinal} {{
545547
}}
546548
547549
#[cfg(target_arch = "wasm32")]
548-
{{
550+
{box_}::pin(async move {{
549551
#[repr(align({align}))]
550552
struct Buffer([::core::mem::MaybeUninit::<u8>; {size}]);
551553
let mut buffer = Buffer([::core::mem::MaybeUninit::uninit(); {size}]);
@@ -558,10 +560,8 @@ pub mod vtable{ordinal} {{
558560
fn wit_import(_: u32, _: *mut u8) -> u32;
559561
}}
560562
561-
{box_}::pin(async move {{
562-
unsafe {{ {async_support}::await_future_result(wit_import, future, address).await }}
563-
}})
564-
}}
563+
unsafe {{ {async_support}::await_future_result(wit_import, future, address).await }}
564+
}})
565565
}}
566566
567567
fn read(future: u32) -> ::core::pin::Pin<{box_}<dyn ::core::future::Future<Output = Option<{name}>>>> {{
@@ -571,7 +571,7 @@ pub mod vtable{ordinal} {{
571571
}}
572572
573573
#[cfg(target_arch = "wasm32")]
574-
{{
574+
{box_}::pin(async move {{
575575
struct Buffer([::core::mem::MaybeUninit::<u8>; {size}]);
576576
let mut buffer = Buffer([::core::mem::MaybeUninit::uninit(); {size}]);
577577
let address = buffer.0.as_mut_ptr() as *mut u8;
@@ -582,15 +582,13 @@ pub mod vtable{ordinal} {{
582582
fn wit_import(_: u32, _: *mut u8) -> u32;
583583
}}
584584
585-
{box_}::pin(async move {{
586-
if unsafe {{ {async_support}::await_future_result(wit_import, future, address).await }} {{
587-
{lift}
588-
Some(value)
589-
}} else {{
590-
None
591-
}}
592-
}})
593-
}}
585+
if unsafe {{ {async_support}::await_future_result(wit_import, future, address).await }} {{
586+
{lift}
587+
Some(value)
588+
}} else {{
589+
None
590+
}}
591+
}})
594592
}}
595593
596594
fn cancel_write(writer: u32) {{
@@ -691,8 +689,7 @@ pub mod vtable{ordinal} {{
691689
}
692690
}
693691
TypeDefKind::Stream(payload_type) => {
694-
let name =
695-
self.full_type_name_owned(payload_type, Identifier::StreamOrFuturePayload);
692+
let name = self.type_name_owned(payload_type);
696693

697694
if !self.gen.stream_payloads.contains_key(&name) {
698695
let ordinal = self.gen.stream_payloads.len();
@@ -747,19 +744,19 @@ for (index, dst) in values.iter_mut().take(count).enumerate() {{
747744
(address.clone(), lower, address, lift)
748745
};
749746

750-
let box_ = format!("super::super::{}", self.path_to_box());
747+
let box_ = self.path_to_box();
751748
let code = format!(
752749
r#"
753750
#[doc(hidden)]
754751
pub mod vtable{ordinal} {{
755-
fn write(stream: u32, values: &[{name}]) -> ::core::pin::Pin<{box_}<dyn ::core::future::Future<Output = Option<usize>>>> {{
752+
fn write(stream: u32, values: &[{name}]) -> ::core::pin::Pin<{box_}<dyn ::core::future::Future<Output = Option<usize>> + '_>> {{
756753
#[cfg(not(target_arch = "wasm32"))]
757754
{{
758755
unreachable!();
759756
}}
760757
761758
#[cfg(target_arch = "wasm32")]
762-
{{
759+
{box_}::pin(async move {{
763760
{lower_address}
764761
{lower}
765762
@@ -769,27 +766,25 @@ pub mod vtable{ordinal} {{
769766
fn wit_import(_: u32, _: *mut u8, _: u32) -> u32;
770767
}}
771768
772-
{box_}::pin(async move {{
773-
unsafe {{
774-
{async_support}::await_stream_result(
775-
wit_import,
776-
stream,
777-
address,
778-
u32::try_from(values.len()).unwrap()
779-
).await
780-
}}
781-
}})
782-
}}
769+
unsafe {{
770+
{async_support}::await_stream_result(
771+
wit_import,
772+
stream,
773+
address,
774+
u32::try_from(values.len()).unwrap()
775+
).await
776+
}}
777+
}})
783778
}}
784779
785-
fn read(stream: u32, values: &mut [::core::mem::MaybeUninit::<{name}>]) -> ::core::pin::Pin<{box_}<dyn ::core::future::Future<Output = Option<usize>>>> {{
780+
fn read(stream: u32, values: &mut [::core::mem::MaybeUninit::<{name}>]) -> ::core::pin::Pin<{box_}<dyn ::core::future::Future<Output = Option<usize>> + '_>> {{
786781
#[cfg(not(target_arch = "wasm32"))]
787782
{{
788783
unreachable!();
789784
}}
790785
791786
#[cfg(target_arch = "wasm32")]
792-
{{
787+
{box_}::pin(async move {{
793788
{lift_address}
794789
795790
#[link(wasm_import_module = "{module}")]
@@ -798,22 +793,20 @@ pub mod vtable{ordinal} {{
798793
fn wit_import(_: u32, _: *mut u8, _: u32) -> u32;
799794
}}
800795
801-
{box_}::pin(async move {{
802-
let count = unsafe {{
803-
{async_support}::await_stream_result(
804-
wit_import,
805-
stream,
806-
address,
807-
u32::try_from(values.len()).unwrap()
808-
).await
809-
}};
810-
#[allow(unused)]
811-
if let Some(count) = count {{
812-
{lift}
813-
}}
814-
count
815-
}})
816-
}}
796+
let count = unsafe {{
797+
{async_support}::await_stream_result(
798+
wit_import,
799+
stream,
800+
address,
801+
u32::try_from(values.len()).unwrap()
802+
).await
803+
}};
804+
#[allow(unused)]
805+
if let Some(count) = count {{
806+
{lift}
807+
}}
808+
count
809+
}})
817810
}}
818811
819812
fn cancel_write(writer: u32) {{
@@ -916,6 +909,8 @@ pub mod vtable{ordinal} {{
916909
_ => unreachable!(),
917910
}
918911
}
912+
913+
self.identifier = old_identifier;
919914
}
920915

921916
fn generate_guest_import(&mut self, func: &Function, interface: Option<&WorldKey>) {
@@ -1699,25 +1694,24 @@ pub mod vtable{ordinal} {{
16991694
}
17001695
}
17011696

1702-
pub(crate) fn full_type_name_owned(&mut self, ty: &Type, id: Identifier<'i>) -> String {
1703-
self.full_type_name(
1697+
pub(crate) fn type_name_owned_with_id(&mut self, ty: &Type, id: Identifier<'i>) -> String {
1698+
let old_identifier = mem::replace(&mut self.identifier, id);
1699+
let name = self.type_name_owned(ty);
1700+
self.identifier = old_identifier;
1701+
name
1702+
}
1703+
1704+
fn type_name_owned(&mut self, ty: &Type) -> String {
1705+
self.type_name(
17041706
ty,
17051707
TypeMode {
17061708
lifetime: None,
17071709
lists_borrowed: false,
17081710
style: TypeOwnershipStyle::Owned,
17091711
},
1710-
id,
17111712
)
17121713
}
17131714

1714-
fn full_type_name(&mut self, ty: &Type, mode: TypeMode, id: Identifier<'i>) -> String {
1715-
let old_identifier = mem::replace(&mut self.identifier, id);
1716-
let name = self.type_name(ty, mode);
1717-
self.identifier = old_identifier;
1718-
name
1719-
}
1720-
17211715
fn type_name(&mut self, ty: &Type, mode: TypeMode) -> String {
17221716
let old = mem::take(&mut self.src);
17231717
self.print_ty(ty, mode);

tests/codegen/streams.wit

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
package foo:foo;
22

3+
interface transmit {
4+
variant control {
5+
read-stream(string),
6+
read-future(string),
7+
write-stream(string),
8+
write-future(string),
9+
}
10+
11+
exchange: func(control: stream<control>,
12+
caller-stream: stream<string>,
13+
caller-future1: future<string>,
14+
caller-future2: future<string>) -> tuple<stream<string>, future<string>, future<string>>;
15+
}
16+
317
interface streams {
418
stream-u8-param: func(x: stream<u8>);
519
stream-u16-param: func(x: stream<u16>);
@@ -82,4 +96,5 @@ interface streams {
8296
world the-streams {
8397
import streams;
8498
export streams;
99+
export transmit;
85100
}

0 commit comments

Comments
 (0)