Surprising soundness trouble around `PollFn`

For what it's worth: tokio::join! and futures::join! are unsound, but std::future::join! is not. tokio::join! moves the input futures into a lambda, similar to the original example, and so does futures::join! (whose implementation is more complicated). In contrast, std::future::join pins the input futures outside the lambda and only moves Pin<&mut T> objects into the lambda.

Here is a playground link, pieced together from some of the previous snippets, that triggers a Miri error using tokio::join! and no unsafe. If you change tokio::join! to futures::join! it also triggers an error.

And... here is a playground link that actually triggers a miscompilation using futures::join!. The code should print 44, but in release mode it prints 43. This doesn't work with tokio::join! simply because it generates more complicated control flow that confuses LLVM.

10 Likes