diff options
Diffstat (limited to 'tests/ui/async-await/issue-105501.rs')
-rw-r--r-- | tests/ui/async-await/issue-105501.rs | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/tests/ui/async-await/issue-105501.rs b/tests/ui/async-await/issue-105501.rs new file mode 100644 index 000000000..f30d2a9d8 --- /dev/null +++ b/tests/ui/async-await/issue-105501.rs @@ -0,0 +1,165 @@ +// 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!() + } + } +} |