#Making async fn and `-> impl Trait` traits object-safe without Boxing.

8 messages · Page 1 of 1 (latest)

ancient flax
#

I have been toying with an approach to express async-fn traits in embedded no_std code, which implies no allocations and no boxing.

The code is here: https://gist.github.com/liarokapisv/3ceb5ebf64ed3149a8fc534c9f818916

It does use quite some unsafe blocks and I would like some feedback on the correctness.

Main idea is to use type_alias_impl_trait to extract the concrete types from async-fn methods.
Then we can embed the resulting Future to a wrapper container's uninitialized storage.

In order to wrap the async fn method, we store the result of the method within the uninitialized storage and then return
a reference to it. We use transmute to change the lifetime to 'static to store it.
In order to properly wrap the method call, we need to ensure that it will handle Drop correctly. This is achieved by wrapping
the reference to a wrapper that forwards the drop. We use mutable borrowing to ensure that we only expose the reference for the proper lifetime duration.

All of the above is handled by the LifetimeEraser, LifetimeEraserHandle structures. I /think/ that the approach is safe but I will not be surprised if I am wrong.

Since the handles are constant in alignment and memory, I also created a LifetimeErasedFutureHandle that basically transmutes the handles to type-erase them, which can then be used in object-safe trait signatures.

Any feedback is welcome!

Gist

Type erased statically-allocated Future. GitHub Gist: instantly share code, notes, and snippets.

swift junco
#

Maybe I'm misunderstanding what you're doing, but isn't this just a very roundabout way to implement &mut dyn Future yourself?

summer sinew
#

I haven't read through your code, but from your description you may find dungeon-cell interesting

ancient flax
#

For each async fn method you need to name the return type then for each method you need to embed a slot on a wrapper struct to keep the futures

#

Then you return basically a &mut dyn Future

#

But we need to also take care of actually dropping the future