I'm willing to bet there's a bug involved in starting mutex.lock() futures only to drop them before they resolve?
I don't think this is the intended usage of tokio::sync::Mutex::lock(), but it shouldn't completely fail like this either? Like, the typical usage is to just grab one lock future, and poll it to completion, rather than creating a new lock future every time you poll. I bet some structure internal to Mutex is giving control to the old/dropped/failed lock future.
Certainly an interesting bug. I would highly recommend reporting to tokio!
If your goal here is to get working code though, I also recommend reusing the future produced by mutex.lock() multiple times rather than recreating it within poll_fn. It no longer locks if poll_fn is replaced with this:
let mut lock_fut = Box::pin(mutex.lock());
let _guard = poll_fn(move |cx| {
println!("poll_fn called");
lock_fut.as_mut().poll(cx)
})
.await;
Basically the issue is that you're recreating the future that waits for the lock to become available on every poll, and if it doesn't succeed, you throw it away. Since you threw the future away, you should not expect to be woken up by that future.