Skip to content

Commit

Permalink
Auto merge of #106264 - Swatinem:higher-lifetime-regression, r=petroc…
Browse files Browse the repository at this point in the history
…henkov

Add regression test for #105501

The test was minified from the published crate `msf-ice:0.2.1` which failed in a crater run.

A faulty compiler was triggering a `higher-ranked lifetime error`:
> could not prove `[async block@...]: Send`

The testcase has some complexity, as it has a simplified subset of `futures::StreamExt` in it, but the error is only being triggered by a few layers of nesting. For example removing the noop `then` call would have been enough to make the error go away.
  • Loading branch information
bors committed Dec 30, 2022
2 parents e5e5fcb + 42e7df9 commit f6cc345
Showing 1 changed file with 165 additions and 0 deletions.
165 changes: 165 additions & 0 deletions src/test/ui/async-await/issue-105501.rs
Original file line number Diff line number Diff line change
@@ -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!()
}
}
}

0 comments on commit f6cc345

Please sign in to comment.