// check-pass
// edition:2018

// This is a regression test for https://github.com/rust-lang/rust/issues/105501.
// It was minified from the published `msf-ice:0.2.1` crate which failed in a crater run.
// A faulty compiler was triggering a `higher-ranked lifetime error`:
//
// > could not prove `[async block@...]: Send`

use mini_futures::Stream;

fn is_send(_: impl Send) {}

pub fn main() {
    let fut = async {
        let mut stream = mini_futures::iter([()])
            .then(|_| async {})
            .map(|_| async { None })
            .buffered()
            .filter_map(std::future::ready);

        stream.next().await
    };

    is_send(async move {
        let _: Option<()> = fut.await;
    });
}

// this is a simplified subset of `futures::StreamExt` and related types
mod mini_futures {
    use std::future::Future;
    use std::pin::Pin;
    use std::task::{Context, Poll};

    pub fn iter<I>(_: I) -> Iter<I::IntoIter>
    where
        I: IntoIterator,
    {
        todo!()
    }

    pub trait Stream {
        type Item;

        fn then<Fut, F>(self, _: F) -> Then<Self, Fut, F>
        where
            F: FnMut(Self::Item) -> Fut,
            Fut: Future,
            Self: Sized,
        {
            todo!()
        }

        fn map<T, F>(self, _: F) -> Map<Self, F>
        where
            F: FnMut(Self::Item) -> T,
            Self: Sized,
        {
            todo!()
        }

        fn buffered(self) -> Buffered<Self>
        where
            Self::Item: Future,
            Self: Sized,
        {
            todo!()
        }

        fn filter_map<Fut, T, F>(self, _: F) -> FilterMap<Self, Fut, F>
        where
            F: FnMut(Self::Item) -> Fut,
            Fut: Future<Output = Option<T>>,
            Self: Sized,
        {
            todo!()
        }

        fn next(&mut self) -> Next<'_, Self> {
            todo!()
        }
    }

    pub struct Iter<I> {
        __: I,
    }
    impl<I> Stream for Iter<I>
    where
        I: Iterator,
    {
        type Item = I::Item;
    }

    pub struct Then<St, Fut, F> {
        __: (St, Fut, F),
    }
    impl<St, Fut, F> Stream for Then<St, Fut, F>
    where
        St: Stream,
        F: FnMut(St::Item) -> Fut,
        Fut: Future,
    {
        type Item = Fut::Output;
    }

    pub struct Map<St, F> {
        __: (St, F),
    }
    impl<St, F> Stream for Map<St, F>
    where
        St: Stream,
        F: FnMut1<St::Item>,
    {
        type Item = F::Output;
    }

    pub trait FnMut1<A> {
        type Output;
    }
    impl<T, A, R> FnMut1<A> for T
    where
        T: FnMut(A) -> R,
    {
        type Output = R;
    }

    pub struct Buffered<St>
    where
        St: Stream,
        St::Item: Future,
    {
        __: (St, St::Item),
    }
    impl<St> Stream for Buffered<St>
    where
        St: Stream,
        St::Item: Future,
    {
        type Item = <St::Item as Future>::Output;
    }

    pub struct FilterMap<St, Fut, F> {
        __: (St, Fut, F),
    }
    impl<St, Fut, F, T> Stream for FilterMap<St, Fut, F>
    where
        St: Stream,
        F: FnMut1<St::Item, Output = Fut>,
        Fut: Future<Output = Option<T>>,
    {
        type Item = T;
    }

    pub struct Next<'a, St: ?Sized> {
        __: &'a mut St,
    }
    impl<St: ?Sized + Stream> Future for Next<'_, St> {
        type Output = Option<St::Item>;

        fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
            todo!()
        }
    }
}
