Stream: wit-bindgen

Topic: Owned vs borrowed resources in C and Rust bindings


view this post on Zulip Christof Petig (Jul 29 2023 at 11:00):

While implementing the C++ bindings for resources very similar to the Rust bindings I came across an interesting question:

Why does C use different types for owned and borrowed handles, thus saving on memory and creating type safety for calls while Rust uses a fused type with a bool distinguishing the handle type? I don't think the type is ever changed across the lifetime of the handle object.

If it is to easily enable borrowing from an owned handle, e.g. to call member functions, I think there might be another way … wrapping the shared handle type in the owned type and implementing Deref :ghost:

I feel getting rid of the if inside the destructor and the added type safety of the interface might be worth considering alternatives to the current implementation.

view this post on Zulip Joel Dice (Aug 01 2023 at 14:49):

I felt that generating a single type for Rust would result in the most idiomatic code, e.g. MyResource for owned values and &MyResource for borrowed ones. I agree that it's not ideal from a performance perspective. I'm not seeing what it lacks in type safety; perhaps you could elaborate on that? In any case, I'm open to alternatives (especially if someone else implements them :smile: ).

view this post on Zulip Christof Petig (Aug 02 2023 at 05:26):

If I guess correctly it will gladly pass a borrowed resource to a function expecting an owned resource (by value), given that the creating function returned an owned handle pointing to a borrowed resource (owned=false). Which might be not the usual way to design resource interfaces.

I fully get the single type usability benefit, perhaps I can come up with a viable alternative which also prevents the above described scenario at compile time. I will take a try in the coming days.

view this post on Zulip Christof Petig (Aug 02 2023 at 05:35):

And I clearly see that good usability gets a bit more tricky if you introduce two types.

view this post on Zulip Christof Petig (Aug 06 2023 at 13:19):

I took a try at implementing it and wanted to start with a test case, sadly I ran into https://github.com/bytecodealliance/wasmtime/blob/main/crates/wit-bindgen/src/lib.rs#L774 (wasmtime doesn't support resources on host side yet, issue #6722)

So I guess I need to replan to use my unfinished C++ host environment and WAMR.

view this post on Zulip Christof Petig (Aug 19 2023 at 15:24):

Alex was quicker doing this change for Rust https://github.com/bytecodealliance/wit-bindgen/pull/643 , thanks a lot!

I created a resource example implementation with C, C++, Rust guests and a WAMR based C++ host at https://github.com/cpetig/resource-demo/ .

But now the C binding feels a bit off, the most straightforward way of calling the functions results in double free/drop - and the distinction between owned and borrowed feels awkward compared to the Rust code.
https://github.com/cpetig/resource-demo/blob/main/guest-c/main.c

@Joel Dice do you see a good reason to keep both types in the C binding (a typedef might still document the own vs borrow information in the header but still enable calling functions on owned resources more easily).

No longer needed now that there's only one destructor function from #642
A demo showing WASM component model resources in various environments - GitHub - cpetig/resource-demo: A demo showing WASM component model resources in various environments

view this post on Zulip Joel Dice (Aug 21 2023 at 13:54):

I made the own and borrow types separate to help guard against using one where the other was expected (e.g. calling resource-drop-own with a borrow handle). Now that there's only one kind of resource-drop function, maybe that's not a factor anymore.

view this post on Zulip Joel Dice (Aug 21 2023 at 13:56):

As long as there's no chance of own/borrow type errors that would otherwise be caught at compile time, I'm fine with combining the types.


Last updated: Dec 23 2024 at 13:07 UTC