diff --git a/src/test/ui/async-await/issue-105501.rs b/src/test/ui/async-await/issue-105501.rs new file mode 100644 index 0000000000000..f30d2a9d81a6a --- /dev/null +++ b/src/test/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) -> Iter + where + I: IntoIterator, + { + todo!() + } + + pub trait Stream { + type Item; + + fn then(self, _: F) -> Then + where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + todo!() + } + + fn map(self, _: F) -> Map + where + F: FnMut(Self::Item) -> T, + Self: Sized, + { + todo!() + } + + fn buffered(self) -> Buffered + where + Self::Item: Future, + Self: Sized, + { + todo!() + } + + fn filter_map(self, _: F) -> FilterMap + where + F: FnMut(Self::Item) -> Fut, + Fut: Future>, + Self: Sized, + { + todo!() + } + + fn next(&mut self) -> Next<'_, Self> { + todo!() + } + } + + pub struct Iter { + __: I, + } + impl Stream for Iter + where + I: Iterator, + { + type Item = I::Item; + } + + pub struct Then { + __: (St, Fut, F), + } + impl Stream for Then + where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, + { + type Item = Fut::Output; + } + + pub struct Map { + __: (St, F), + } + impl Stream for Map + where + St: Stream, + F: FnMut1, + { + type Item = F::Output; + } + + pub trait FnMut1 { + type Output; + } + impl FnMut1 for T + where + T: FnMut(A) -> R, + { + type Output = R; + } + + pub struct Buffered + where + St: Stream, + St::Item: Future, + { + __: (St, St::Item), + } + impl Stream for Buffered + where + St: Stream, + St::Item: Future, + { + type Item = ::Output; + } + + pub struct FilterMap { + __: (St, Fut, F), + } + impl Stream for FilterMap + where + St: Stream, + F: FnMut1, + Fut: Future>, + { + type Item = T; + } + + pub struct Next<'a, St: ?Sized> { + __: &'a mut St, + } + impl Future for Next<'_, St> { + type Output = Option; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + todo!() + } + } +}