about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr28
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr28
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr26
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.rs71
4 files changed, 153 insertions, 0 deletions
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr
new file mode 100644
index 00000000000..fa201b89048
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr
@@ -0,0 +1,28 @@
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:19:19
+   |
+LL | fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
+   |                                    - let's call the lifetime of this reference `'1`
+LL |     let Some(i) = t.next() else { return None };
+   |                   - first mutable borrow occurs here
+LL |     let Some(j) = t.next() else { return None };
+   |                   ^ second mutable borrow occurs here
+...
+LL |     Some((i, j))
+   |     ------------ returning this value requires that `*t` is borrowed for `'1`
+
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:31:13
+   |
+LL |     let i = t.next();
+   |             - first mutable borrow occurs here
+...
+LL |     let j = t.next();
+   |             ^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `Option<<T as LendingIterator>::Item<'_>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr
new file mode 100644
index 00000000000..fa201b89048
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr
@@ -0,0 +1,28 @@
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:19:19
+   |
+LL | fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
+   |                                    - let's call the lifetime of this reference `'1`
+LL |     let Some(i) = t.next() else { return None };
+   |                   - first mutable borrow occurs here
+LL |     let Some(j) = t.next() else { return None };
+   |                   ^ second mutable borrow occurs here
+...
+LL |     Some((i, j))
+   |     ------------ returning this value requires that `*t` is borrowed for `'1`
+
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:31:13
+   |
+LL |     let i = t.next();
+   |             - first mutable borrow occurs here
+...
+LL |     let j = t.next();
+   |             ^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `Option<<T as LendingIterator>::Item<'_>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr
new file mode 100644
index 00000000000..bf8546b63bf
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr
@@ -0,0 +1,26 @@
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:19:19
+   |
+LL |     let Some(i) = t.next() else { return None };
+   |                   - first mutable borrow occurs here
+LL |     let Some(j) = t.next() else { return None };
+   |                   ^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `<T as LendingIterator>::Item<'_>`
+
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:31:13
+   |
+LL |     let i = t.next();
+   |             - first mutable borrow occurs here
+...
+LL |     let j = t.next();
+   |             ^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `Option<<T as LendingIterator>::Item<'_>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.rs b/tests/ui/nll/polonius/lending-iterator-sanity-checks.rs
new file mode 100644
index 00000000000..ae8cc78957f
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.rs
@@ -0,0 +1,71 @@
+// 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() {}