about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/drop/auxiliary/edition-2021-macros.rs8
-rw-r--r--tests/ui/drop/auxiliary/edition-2024-macros.rs9
-rw-r--r--tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr16
-rw-r--r--tests/ui/drop/tail-expr-drop-order-negative.rs17
-rw-r--r--tests/ui/drop/tail-expr-drop-order.rs108
-rw-r--r--tests/ui/feature-gates/feature-gate-shorter_tail_lifetimes.rs8
-rw-r--r--tests/ui/feature-gates/feature-gate-shorter_tail_lifetimes.stderr26
-rw-r--r--tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr26
-rw-r--r--tests/ui/lifetimes/refcell-in-tail-expr.rs16
-rw-r--r--tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr26
-rw-r--r--tests/ui/lifetimes/shorter-tail-expr-lifetime.rs15
-rw-r--r--tests/ui/lifetimes/tail-expr-in-nested-expr.rs9
-rw-r--r--tests/ui/lifetimes/tail-expr-in-nested-expr.stderr15
-rw-r--r--tests/ui/lifetimes/tail-expr-lock-poisoning.rs29
-rw-r--r--tests/ui/nll/issue-52534-1.rs4
15 files changed, 330 insertions, 2 deletions
diff --git a/tests/ui/drop/auxiliary/edition-2021-macros.rs b/tests/ui/drop/auxiliary/edition-2021-macros.rs
new file mode 100644
index 00000000000..8a6444f8614
--- /dev/null
+++ b/tests/ui/drop/auxiliary/edition-2021-macros.rs
@@ -0,0 +1,8 @@
+//@ edition:2021
+
+#[macro_export]
+macro_rules! edition_2021_block {
+    ($($c:tt)*) => {
+        { $($c)* }
+    }
+}
diff --git a/tests/ui/drop/auxiliary/edition-2024-macros.rs b/tests/ui/drop/auxiliary/edition-2024-macros.rs
new file mode 100644
index 00000000000..236340bfed4
--- /dev/null
+++ b/tests/ui/drop/auxiliary/edition-2024-macros.rs
@@ -0,0 +1,9 @@
+//@ edition:2024
+//@ compile-flags: -Zunstable-options
+
+#[macro_export]
+macro_rules! edition_2024_block {
+    ($($c:tt)*) => {
+        { $($c)* }
+    }
+}
diff --git a/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr b/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr
new file mode 100644
index 00000000000..75fc34e409b
--- /dev/null
+++ b/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/tail-expr-drop-order-negative.rs:11:15
+   |
+LL |     x.replace(std::cell::RefCell::new(123).borrow()).is_some()
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^                   - temporary value is freed at the end of this statement
+   |               |
+   |               creates a temporary value which is freed while still in use
+LL |
+LL | }
+   | - borrow might be used here, when `x` is dropped and runs the destructor for type `Option<Ref<'_, i32>>`
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/drop/tail-expr-drop-order-negative.rs b/tests/ui/drop/tail-expr-drop-order-negative.rs
new file mode 100644
index 00000000000..c570b3a1ee2
--- /dev/null
+++ b/tests/ui/drop/tail-expr-drop-order-negative.rs
@@ -0,0 +1,17 @@
+//@ revisions: edition2021 edition2024
+//@ [edition2024] compile-flags: -Zunstable-options
+//@ [edition2024] edition: 2024
+//@ [edition2021] check-pass
+
+#![feature(shorter_tail_lifetimes)]
+
+fn why_would_you_do_this() -> bool {
+    let mut x = None;
+    // Make a temporary `RefCell` and put a `Ref` that borrows it in `x`.
+    x.replace(std::cell::RefCell::new(123).borrow()).is_some()
+    //[edition2024]~^ ERROR: temporary value dropped while borrowed
+}
+
+fn main() {
+    why_would_you_do_this();
+}
diff --git a/tests/ui/drop/tail-expr-drop-order.rs b/tests/ui/drop/tail-expr-drop-order.rs
new file mode 100644
index 00000000000..5d87f980b15
--- /dev/null
+++ b/tests/ui/drop/tail-expr-drop-order.rs
@@ -0,0 +1,108 @@
+//@ aux-build:edition-2021-macros.rs
+//@ aux-build:edition-2024-macros.rs
+//@ compile-flags: -Z validate-mir -Zunstable-options
+//@ edition: 2024
+//@ run-pass
+
+#![feature(shorter_tail_lifetimes)]
+#![allow(unused_imports)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#[macro_use]
+extern crate edition_2021_macros;
+#[macro_use]
+extern crate edition_2024_macros;
+use std::cell::RefCell;
+use std::convert::TryInto;
+
+#[derive(Default)]
+struct DropOrderCollector(RefCell<Vec<u32>>);
+
+struct LoudDrop<'a>(&'a DropOrderCollector, u32);
+
+impl Drop for LoudDrop<'_> {
+    fn drop(&mut self) {
+        println!("{}", self.1);
+        self.0.0.borrow_mut().push(self.1);
+    }
+}
+
+impl DropOrderCollector {
+    fn option_loud_drop(&self, n: u32) -> Option<LoudDrop> {
+        Some(LoudDrop(self, n))
+    }
+
+    fn loud_drop(&self, n: u32) -> LoudDrop {
+        LoudDrop(self, n)
+    }
+
+    fn assert_sorted(&self, expected: usize) {
+        let result = self.0.borrow();
+        assert_eq!(result.len(), expected);
+        for i in 1..result.len() {
+            assert!(
+                result[i - 1] < result[i],
+                "inversion at {} ({} followed by {})",
+                i - 1,
+                result[i - 1],
+                result[i]
+            );
+        }
+    }
+}
+
+fn edition_2021_around_2021() {
+    let c = DropOrderCollector::default();
+    let _ = edition_2021_block! {
+        let a = c.loud_drop(1);
+        edition_2021_block! {
+            let b = c.loud_drop(0);
+            c.loud_drop(2).1
+        }
+    };
+    c.assert_sorted(3);
+}
+
+fn edition_2021_around_2024() {
+    let c = DropOrderCollector::default();
+    let _ = edition_2021_block! {
+        let a = c.loud_drop(2);
+        edition_2024_block! {
+            let b = c.loud_drop(1);
+            c.loud_drop(0).1
+        }
+    };
+    c.assert_sorted(3);
+}
+
+fn edition_2024_around_2021() {
+    let c = DropOrderCollector::default();
+    let _ = edition_2024_block! {
+        let a = c.loud_drop(2);
+        edition_2021_block! {
+            let b = c.loud_drop(0);
+            c.loud_drop(1).1
+        }
+    };
+    c.assert_sorted(3);
+}
+
+fn edition_2024_around_2024() {
+    let c = DropOrderCollector::default();
+    let _ = edition_2024_block! {
+        let a = c.loud_drop(2);
+        edition_2024_block! {
+            let b = c.loud_drop(1);
+            c.loud_drop(0).1
+        }
+    };
+    c.assert_sorted(3);
+}
+
+fn main() {
+    edition_2021_around_2021();
+    edition_2021_around_2024();
+    edition_2024_around_2021();
+    edition_2024_around_2024();
+}
diff --git a/tests/ui/feature-gates/feature-gate-shorter_tail_lifetimes.rs b/tests/ui/feature-gates/feature-gate-shorter_tail_lifetimes.rs
new file mode 100644
index 00000000000..5292c44bb2d
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-shorter_tail_lifetimes.rs
@@ -0,0 +1,8 @@
+fn f() -> usize {
+    let c = std::cell::RefCell::new("..");
+    c.borrow().len() //~ ERROR: `c` does not live long enough
+}
+
+fn main() {
+    let _ = f();
+}
diff --git a/tests/ui/feature-gates/feature-gate-shorter_tail_lifetimes.stderr b/tests/ui/feature-gates/feature-gate-shorter_tail_lifetimes.stderr
new file mode 100644
index 00000000000..648c3d5daa1
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-shorter_tail_lifetimes.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/feature-gate-shorter_tail_lifetimes.rs:3:5
+   |
+LL |     let c = std::cell::RefCell::new("..");
+   |         - binding `c` declared here
+LL |     c.borrow().len()
+   |     ^---------
+   |     |
+   |     borrowed value does not live long enough
+   |     a temporary with access to the borrow is created here ...
+LL | }
+   | -
+   | |
+   | `c` dropped here while still borrowed
+   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, &str>`
+   |
+   = note: the temporary is part of an expression at the end of a block;
+           consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
+help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
+   |
+LL |     let x = c.borrow().len(); x
+   |     +++++++                 +++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr b/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr
new file mode 100644
index 00000000000..858be42d540
--- /dev/null
+++ b/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `cell` does not live long enough
+  --> $DIR/refcell-in-tail-expr.rs:12:27
+   |
+LL |     let cell = std::cell::RefCell::new(0u8);
+   |         ---- binding `cell` declared here
+LL |
+LL |     if let Ok(mut byte) = cell.try_borrow_mut() {
+   |                           ^^^^-----------------
+   |                           |
+   |                           borrowed value does not live long enough
+   |                           a temporary with access to the borrow is created here ...
+...
+LL | }
+   | -
+   | |
+   | `cell` dropped here while still borrowed
+   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Result<RefMut<'_, u8>, BorrowMutError>`
+   |
+help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
+   |
+LL |     };
+   |      +
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/lifetimes/refcell-in-tail-expr.rs b/tests/ui/lifetimes/refcell-in-tail-expr.rs
new file mode 100644
index 00000000000..b1814c1e327
--- /dev/null
+++ b/tests/ui/lifetimes/refcell-in-tail-expr.rs
@@ -0,0 +1,16 @@
+//@ revisions: edition2021 edition2024
+//@ [edition2021] edition: 2021
+//@ [edition2024] edition: 2024
+//@ [edition2024] compile-flags: -Zunstable-options
+//@ [edition2024] check-pass
+
+#![cfg_attr(edition2024, feature(shorter_tail_lifetimes))]
+
+fn main() {
+    let cell = std::cell::RefCell::new(0u8);
+
+    if let Ok(mut byte) = cell.try_borrow_mut() {
+        //[edition2021]~^ ERROR: `cell` does not live long enough
+        *byte = 1;
+    }
+}
diff --git a/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr b/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr
new file mode 100644
index 00000000000..ad28ae2f80d
--- /dev/null
+++ b/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `c` does not live long enough
+  --> $DIR/shorter-tail-expr-lifetime.rs:10:5
+   |
+LL |     let c = std::cell::RefCell::new("..");
+   |         - binding `c` declared here
+LL |     c.borrow().len()
+   |     ^---------
+   |     |
+   |     borrowed value does not live long enough
+   |     a temporary with access to the borrow is created here ...
+LL | }
+   | -
+   | |
+   | `c` dropped here while still borrowed
+   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, &str>`
+   |
+   = note: the temporary is part of an expression at the end of a block;
+           consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
+help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
+   |
+LL |     let x = c.borrow().len(); x
+   |     +++++++                 +++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs b/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs
new file mode 100644
index 00000000000..0392b6c6d9a
--- /dev/null
+++ b/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs
@@ -0,0 +1,15 @@
+//@ revisions: edition2021 edition2024
+//@ [edition2024] compile-flags: -Zunstable-options
+//@ [edition2024] edition: 2024
+//@ [edition2024] run-pass
+
+#![cfg_attr(edition2024, feature(shorter_tail_lifetimes))]
+
+fn f() -> usize {
+    let c = std::cell::RefCell::new("..");
+    c.borrow().len() //[edition2021]~ ERROR: `c` does not live long enough
+}
+
+fn main() {
+    let _ = f();
+}
diff --git a/tests/ui/lifetimes/tail-expr-in-nested-expr.rs b/tests/ui/lifetimes/tail-expr-in-nested-expr.rs
new file mode 100644
index 00000000000..a8989f22f4b
--- /dev/null
+++ b/tests/ui/lifetimes/tail-expr-in-nested-expr.rs
@@ -0,0 +1,9 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+
+#![feature(shorter_tail_lifetimes)]
+
+fn main() {
+    let _ = { String::new().as_str() }.len();
+    //~^ ERROR temporary value dropped while borrowed
+}
diff --git a/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr b/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr
new file mode 100644
index 00000000000..f699d184bdb
--- /dev/null
+++ b/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr
@@ -0,0 +1,15 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/tail-expr-in-nested-expr.rs:7:15
+   |
+LL |     let _ = { String::new().as_str() }.len();
+   |               ^^^^^^^^^^^^^---------
+   |               |                    |
+   |               |                    temporary value is freed at the end of this statement
+   |               creates a temporary value which is freed while still in use
+   |               borrow later used here
+   |
+   = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/lifetimes/tail-expr-lock-poisoning.rs b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs
new file mode 100644
index 00000000000..69b8f286d77
--- /dev/null
+++ b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs
@@ -0,0 +1,29 @@
+//@ revisions: edition2021 edition2024
+//@ ignore-wasm no panic or subprocess support
+//@ [edition2024] compile-flags: -Zunstable-options
+//@ [edition2024] edition: 2024
+//@ run-pass
+#![cfg_attr(edition2024, feature(shorter_tail_lifetimes))]
+
+use std::sync::Mutex;
+
+struct PanicOnDrop;
+impl Drop for PanicOnDrop {
+    fn drop(&mut self) {
+        panic!()
+    }
+}
+
+fn f(m: &Mutex<i32>) -> i32 {
+    let _x = PanicOnDrop;
+    *m.lock().unwrap()
+}
+
+fn main() {
+    let m = Mutex::new(0);
+    let _ = std::panic::catch_unwind(|| f(&m));
+    #[cfg(edition2024)]
+    assert!(m.lock().is_ok());
+    #[cfg(edition2021)]
+    assert!(m.lock().is_err());
+}
diff --git a/tests/ui/nll/issue-52534-1.rs b/tests/ui/nll/issue-52534-1.rs
index d9ea3ae42c4..526b81bb2d0 100644
--- a/tests/ui/nll/issue-52534-1.rs
+++ b/tests/ui/nll/issue-52534-1.rs
@@ -17,14 +17,14 @@ fn foo(x: &u32) -> &u32 {
 fn baz(x: &u32) -> &&u32 {
     let x = 22;
     &&x
-//~^ ERROR cannot return value referencing local variable
+//~^ ERROR cannot return value referencing local variable `x`
 //~| ERROR cannot return reference to temporary value
 }
 
 fn foobazbar<'a>(x: u32, y: &'a u32) -> &'a u32 {
     let x = 22;
     &x
-//~^ ERROR cannot return reference to local variable
+//~^ ERROR cannot return reference to local variable `x`
 }
 
 fn foobar<'a>(x: &'a u32) -> &'a u32 {