| // 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() {} |