Skip to content

Undefined behavior from poll_fn + futures::join! / std::future::join! #3780

Closed
@jplatte

Description

@jplatte

Recently, when working on a library for observables, I found new miri test failures (I had been getting them on a specific test before, but didn't investigate after ensuring it wasn't my own UB). This lead to a bug report to tokio where Alice Ryhl showed that it didn't actually require tokio::spawn (which I had failed to get rid of in minimizing the issue), and the same issue was reproducible with join! + futures_executor.

I have now reduced the example much further, to this (works with the nightly std::future::join!, or futures::join!; playground):

#![feature(future_join)]

use std::{
    future::{join, poll_fn, Future},
    pin::pin,
    sync::Arc,
    task::{Context, Poll, Wake},
};

fn main() {
    let mut fut = pin!(async {
        let mut thing = "hello".to_owned();
        let fut1 = async move {
            poll_fn(|_| {
                thing += ", world";
                Poll::<()>::Pending
            })
            .await;
        };

        let fut2 = async {};

        join!(fut1, fut2).await;
    });

    let waker = Arc::new(DummyWaker).into();
    let mut ctx = Context::from_waker(&waker);
    _ = fut.as_mut().poll(&mut ctx);
    _ = fut.as_mut().poll(&mut ctx);
}

struct DummyWaker;

impl Wake for DummyWaker {
    fn wake(self: Arc<Self>) {}
}

Alice suggested that this may be an instance of rust-lang/rust#63818, is that correct? I was under the impression that the compiler for now doesn't implement alias restrictions for !Unpin types, but maybe this only applies to the LLVM backend, not miri?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions