about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRémy Rakic <remy.rakic+github@gmail.com>2025-06-26 15:27:23 +0000
committerRémy Rakic <remy.rakic+github@gmail.com>2025-08-08 15:14:51 +0000
commit48ebae9cef6fdb1af495e692a0811634f308e447 (patch)
tree6a81a8aca8f742dd4e61e454479b32264d0fffa5
parentb172980d5c0de4a917e0f28ebd118f20889e6036 (diff)
downloadrust-48ebae9cef6fdb1af495e692a0811634f308e447.tar.gz
rust-48ebae9cef6fdb1af495e692a0811634f308e447.zip
add NLL-like imprecision example
This test showcases the same imprecision as NLLs, unlike the datalog
implementation, when using reachability as a liveness approximation.
-rw-r--r--tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr36
-rw-r--r--tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr36
-rw-r--r--tests/ui/nll/polonius/flow-sensitive-invariance.rs34
3 files changed, 106 insertions, 0 deletions
diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr b/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr
new file mode 100644
index 00000000000..5756148f4eb
--- /dev/null
+++ b/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr
@@ -0,0 +1,36 @@
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:17
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                 ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:45
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                                             ^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr b/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr
new file mode 100644
index 00000000000..5756148f4eb
--- /dev/null
+++ b/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr
@@ -0,0 +1,36 @@
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:17
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                 ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:45
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                                             ^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.rs b/tests/ui/nll/polonius/flow-sensitive-invariance.rs
new file mode 100644
index 00000000000..c5571f131da
--- /dev/null
+++ b/tests/ui/nll/polonius/flow-sensitive-invariance.rs
@@ -0,0 +1,34 @@
+// An example (from @steffahn) of reachability as an approximation of liveness where the polonius
+// alpha analysis shows the same imprecision as NLLs, unlike the datalog implementation.
+
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius legacy
+//@ [polonius] compile-flags: -Z polonius=next
+//@ [legacy] check-pass
+//@ [legacy] compile-flags: -Z polonius=legacy
+
+use std::cell::Cell;
+
+struct Invariant<'l>(Cell<&'l ()>);
+
+fn create_invariant<'l>() -> Invariant<'l> {
+    Invariant(Cell::new(&()))
+}
+
+fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+    let returned_value = create_invariant();
+    if choice { Ok(returned_value) } else { Err(returned_value) }
+    //[nll]~^ ERROR lifetime may not live long enough
+    //[nll]~| ERROR lifetime may not live long enough
+    //[polonius]~^^^ ERROR lifetime may not live long enough
+    //[polonius]~| ERROR lifetime may not live long enough
+}
+
+fn use_it_but_its_the_same_region<'a: 'b, 'b: 'a>(
+    choice: bool,
+) -> Result<Invariant<'a>, Invariant<'b>> {
+    let returned_value = create_invariant();
+    if choice { Ok(returned_value) } else { Err(returned_value) }
+}
+
+fn main() {}