MendyBerger opened issue #8764:
Currently, if you wanna implement the traits generated by
component::bindgen
in a library that other's are gonna use with custom types, you can't do it onT: YourTrait
, you have to implement it ondyn YourTrait
. At least that's what I gather from what wasi-http is doing.I'm working on wasi-webgpu, where we'd really like one of our methods to be generic, but generics are not object-safe. Is there any way we can do that?
alexcrichton commented on issue #8764:
Heh I was actually just talking with others about possibly changing some parts about wasi-http about this.
For your use case would something like this work?
pub struct MyWebgpuWrapper<T>(pub T); pub trait MyWebgpuView { /* ... */ } impl<T: MyWebgpuView> bindings::wasi::webgpu::interface::Host for MyWebgpuWrapper<T> { /* ... */ } pub fn add_to_linker<T: MyWebgpuView>(linker: &mut Linker<T>) -> Result<()> { /* ... */ }
Basically having a newtype wrapper locally which is used internally in
add_to_linker
as a temporary value?
MendyBerger commented on issue #8764:
Not sure I understand how this would work.
Wouldn't this require the consumer of the wasi-webgpu library to implementHost
manually? Or do you mean that all of this would be in library code?
alexcrichton commented on issue #8764:
Oh the wasi-webgpu library would have impls that look like
impl<T: MyWebgpuView> bindings::wasi::webgpu::interface::Host for MyWebgpuWrapper<T>
so users wouldn't need to implement
Host
themselves. They only need to constructMyWebgpuWrapper<T>
which is probablyMyWebgpuWrapper(&mut my_stuff)
Also, to confirm, you're looking to provide a small trait of methods and then from that small trait of methods all other methods are implemented? That's what wasmtime-wasi/wasmtime-wasi-http are doing but if you're not leap frogging traits like this then most of this infrastructure isn't necessary
MendyBerger commented on issue #8764:
Oh! I think I see it now!
Host
is implemented for a concrete type. And the concrete implementation won't conflict with the auto generated&mut T
implementations because of the wrapper. Brilliant idea!
Let me check if I can get this to work.
MendyBerger commented on issue #8764:
@alexcrichton I was able to get it to work, thanks for the help!
I modeled it like wasi-http which seems to be doing the same thing.
It took me a couple of hours to figure this out though. Would it be possible for
bindgen!
to generate all the plumbing, and just expose a ready to useWasiFooImpl
andadd_to_linker
?
Figuring out exactly what needs to go in theadd_to_linker
like thetype_annotate
, as well as the requirement to implementWasiFooView
onWasiFooImpl
,&mut T: WasiFooView
, andBox<T: WasiFooView>
is a lot of work.
alexcrichton commented on issue #8764:
Hm unfortuantely I don't think so. The
WasiView
trait is a handwritten trait and has no means of being automatically derived. Furthermore all implementations of theHost
traits are implemented in terms ofWasiView
and additionally can't be auto-derived. For the same reasons nothing can auto-derive the impls and such too.I'll also reiterate though that none of this is ideally necessary. I'd much rather have, for example
Host for WasiCtx
for all of WASI or something like:pub struct WasiTemp<'a> { pub table: &'a mut ResourceTable, pub ctx: &'a mut WasiCtx, } impl Host for WasiTemp<'_> { /* ... */ }
Or put another way I'd much rather to have
Host
for concrete types. The only reasonWasiView
exists is to mirror the design ofWasiHttpView
and the only reason that exists is the various trait methods it has for customizing how a request is dispatched for example. If you can get away with it I'd recommend not using a*View
triat entirely and instead using a configuration context of some kind and everything is implemented in terms of that context.
pchickey commented on issue #8764:
I think historically
WasiView
came beforeWasiHttpView
, opposite of what your example is, but no matter. The real unfortunate necessity for all of this machinery is that all* bindings implementations on a store need to share the sameResourceTable
, but have their own Ctx type for "everything else": WasiCtx, WasiHttpCtx, WebGpuCtx etc. The best way we came up with in wasmtime-wasi and wasmtime-wasi-http is to have a trait where you can borrow either the ctx or the table mutably, but it would work just as well with a struct like Alex describes where each of those mut borrows is a member of the struct.
- well, technically only bindings implementations that have resource types in common, but in practice everything of nontrivial complexity needs a pollable or stream at some point, so effectively its all bindings
alexcrichton commented on issue #8764:
Ah yes true! One thing I'll also point out is that we haven't historically done something like
WasiTemp<'a>
because that wasn't possible until https://github.com/bytecodealliance/wasmtime/pull/8448 landed. Now with that we could in theory move all WASI bits, but the customization bits that use a trait still necessitate otherwise.That being said a better yet design from what we have now, perhaps for wasi-http, would be to have
WasiHttpCtx<T>
whereT: WasiHttpImplTrait
where it's not the same asWasiView
but just the customization methods. That way we could in fact useWasiTemp<'a>
or something similar.
alexcrichton closed issue #8764:
Currently, if you wanna implement the traits generated by
component::bindgen
in a library that other's are gonna use with custom types, you can't do it onT: YourTrait
, you have to implement it ondyn YourTrait
. At least that's what I gather from what wasi-http is doing.I'm working on wasi-webgpu, where we'd really like one of our methods to be generic, but generics are not object-safe. Is there any way we can do that?
alexcrichton commented on issue #8764:
I think this has been answered now so I'm going to close this, but if there are any lingering questions/clarifications feel free to comment and/or open a new issue.
Last updated: Dec 23 2024 at 12:05 UTC