blob: ae8cc78957fefca7c766eaf4b6a8955ba3f02476 [file] [log] [blame]
// Some sanity checks for lending iterators with GATs. This is just some non-regression tests
// ensuring the polonius alpha analysis, the datalog implementation, and NLLs agree in these common
// cases of overlapping yielded items.
//@ ignore-compare-mode-polonius (explicit revisions)
//@ revisions: nll polonius legacy
//@ [polonius] compile-flags: -Z polonius=next
//@ [legacy] compile-flags: -Z polonius=legacy
trait LendingIterator {
type Item<'a>
where
Self: 'a;
fn next(&mut self) -> Option<Self::Item<'_>>;
}
fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
let Some(i) = t.next() else { return None };
let Some(j) = t.next() else { return None };
//~^ ERROR cannot borrow `*t` as mutable more than once at a time
// `i` is obviously still (use-)live here, but we called `next` again to get `j`.
Some((i, j))
}
fn drop_live<T: LendingIterator>(t: &mut T) {
let i = t.next();
// Now `i` is use-dead here, but we don't know if the iterator items have a `Drop` impl, so it's
// still drop-live.
let j = t.next();
//~^ ERROR cannot borrow `*t` as mutable more than once at a time
}
// But we can still manually serialize the lifetimes with scopes (or preventing the destructor from
// being called), so they're not overlapping.
fn manually_non_overlapping<T: LendingIterator>(t: &mut T) {
{
let i = t.next();
}
let j = t.next(); // i is dead
drop(j);
let k = t.next(); // j is dead
let k = std::mem::ManuallyDrop::new(k);
let l = t.next(); // we told the compiler that k is not drop-live
}
// The cfg below is because there's a diagnostic ICE trying to explain the source of the error when
// using the datalog implementation. We're not fixing *that*, outside of removing the implementation
// in the future.
#[cfg(not(legacy))] // FIXME: remove this cfg when removing the datalog implementation
fn items_have_no_borrows<T: LendingIterator>(t: &mut T)
where
for<'a> T::Item<'a>: 'static,
{
let i = t.next();
let j = t.next();
}
fn items_are_copy<T: LendingIterator>(t: &mut T)
where
for<'a> T::Item<'a>: Copy,
{
let i = t.next();
let j = t.next();
}
fn main() {}