Idea: unwinding and linear types in async context

One of the biggest problems with Linear/Undroppable types is unwinding - you cannot drop that type, so if you unwind, you cannot go forward. Currently there are 2 ideas: first is to abort the process, second is to have some kind of "no unwind" effect.

I think a third approach is possible, for futures. When sync code panics, there is not much you can do, as control flow is not in your hands. But with async it is a little bit different. I think it may be useful if Future that panicked during the poll will become pending, i.e. always return Poll::Pending. Then, with a trigger from the panic hook, it may be cancelled in some way.

So, what if a future containing undroppable types will handle panics like that? And if undroppable type is not held across await points, store it in the Future anyways.

I made a proof of concept crate pending_unwind, but I think it may be possible to add another method for Future that will help recover from the panics with linear types present, maybe involving async Drop?

I can say with confidence that I don’t understand how this API is supposed to be used even after reading your whole post here, the API docs, and the included test cases.

Maybe a good, illustrative example could help?

All I can tell is that this NoUnwind<Fut>’s Future impl looks a lot like this goes against the general property/contract for well-behaved Futures that:

If the future is not able to complete yet, it returns Poll::Pending and arranges for the wake() function to be called when the Future is ready to make more progress.

IIUC: a future that panicked will never be able to make progress, so converting this into Pending-forever doesn’t violate the contract. The idea, I think, is that the panic hook would call nesting_depth and then alert the executor somehow if it is nonzero. The executor would then be charged with handling the situation.

2 Likes