From ec3820a10dbf4976fa19a79bfac945dfee8dd20f Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Mon, 17 Mar 2025 17:24:02 -0300
Subject: [PATCH 1/3] Add .use block test

---
 tests/ui/ergonomic-clones/dotuse/block.rs | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 tests/ui/ergonomic-clones/dotuse/block.rs

diff --git a/tests/ui/ergonomic-clones/dotuse/block.rs b/tests/ui/ergonomic-clones/dotuse/block.rs
new file mode 100644
index 00000000000..2e423c67d02
--- /dev/null
+++ b/tests/ui/ergonomic-clones/dotuse/block.rs
@@ -0,0 +1,11 @@
+//@ check-pass
+
+#![feature(ergonomic_clones)]
+#![allow(incomplete_features)]
+
+fn use_block_test(x: i32) -> i32 {
+    let x = { let x = x + 1; x }.use;
+    x
+}
+
+fn main() {}

From c717c599604c50454933fe58f8a23aa0a0236b5b Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Mon, 17 Mar 2025 17:24:16 -0300
Subject: [PATCH 2/3] Add multiple closure use variants

---
 .../closure/multiple-use-variants.rs          | 35 +++++++++++++++++++
 .../closure/multiple-use-variants.stderr      | 13 +++++++
 2 files changed, 48 insertions(+)
 create mode 100644 tests/ui/ergonomic-clones/closure/multiple-use-variants.rs
 create mode 100644 tests/ui/ergonomic-clones/closure/multiple-use-variants.stderr

diff --git a/tests/ui/ergonomic-clones/closure/multiple-use-variants.rs b/tests/ui/ergonomic-clones/closure/multiple-use-variants.rs
new file mode 100644
index 00000000000..e2e9820a740
--- /dev/null
+++ b/tests/ui/ergonomic-clones/closure/multiple-use-variants.rs
@@ -0,0 +1,35 @@
+#![feature(ergonomic_clones)]
+#![allow(incomplete_features)]
+
+use std::clone::UseCloned;
+
+fn takes_val<T>(_: T) {}
+fn takes_ref<'a, T>(_: &'a T) {}
+
+#[derive(Clone)]
+struct Inner<'a, T>(&'a T);
+
+impl<'a, T> UseCloned for Inner<'a, T> where T: Clone {}
+
+fn main() {
+    let v = String::new();
+    let inner = Inner(&v);
+
+    let _ = use || {
+        takes_ref(inner.0);
+        takes_val(inner.0)
+    };
+    let _ = use || {
+        takes_ref(inner.0);
+        takes_val(inner.0);
+        takes_val(inner.0);
+        takes_val(inner)
+    };
+    let _ = use || {
+        takes_ref(inner.0);
+        takes_val(inner.0);
+        takes_val(inner);
+        takes_val(inner)
+        //~^ ERROR: use of moved value: `inner` [E0382]
+    };
+}
diff --git a/tests/ui/ergonomic-clones/closure/multiple-use-variants.stderr b/tests/ui/ergonomic-clones/closure/multiple-use-variants.stderr
new file mode 100644
index 00000000000..7b25ca9bba8
--- /dev/null
+++ b/tests/ui/ergonomic-clones/closure/multiple-use-variants.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `inner`
+  --> $DIR/multiple-use-variants.rs:32:19
+   |
+LL |         takes_val(inner);
+   |                   ----- value moved here
+LL |         takes_val(inner)
+   |                   ^^^^^ value used here after move
+   |
+   = note: move occurs because `inner` has type `Inner<'_, String>`, which does not implement the `Copy` trait
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.

From ca4a58241bee6e5cd42ac26a73747cc04a8316c5 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Mon, 17 Mar 2025 17:50:36 -0300
Subject: [PATCH 3/3] Add spawn thread test

---
 .../closure/spawn-thread.edition2018.stderr   | 28 +++++++++++
 .../ergonomic-clones/closure/spawn-thread.rs  | 50 +++++++++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100644 tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr
 create mode 100644 tests/ui/ergonomic-clones/closure/spawn-thread.rs

diff --git a/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr b/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr
new file mode 100644
index 00000000000..ac8e1c5fa85
--- /dev/null
+++ b/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr
@@ -0,0 +1,28 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/spawn-thread.rs:15:42
+   |
+LL |       let x = (Arc::new("foo".to_owned()), Arc::new(vec![1, 2, 3]), Arc::new(1));
+   |           - move occurs because `x` has type `(Arc<String>, Arc<Vec<i32>>, Arc<i32>)`, which does not implement the `Copy` trait
+LL |       for _ in 0..10 {
+   |       -------------- inside of this loop
+LL |           let handler = std::thread::spawn(use || {
+   |  __________________________________________-^^^^^
+LL | |
+LL | |             drop((x.0, x.1, x.2));
+   | |                   --- use occurs due to use in closure
+LL | |         });
+   | |_________- value moved here, in previous iteration of loop
+   |
+help: consider moving the expression out of the loop so it is only moved once
+   |
+LL ~     let mut value = std::thread::spawn(use || {
+LL +
+LL +             drop((x.0, x.1, x.2));
+LL +         });
+LL ~     for _ in 0..10 {
+LL ~         let handler = value;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/ergonomic-clones/closure/spawn-thread.rs b/tests/ui/ergonomic-clones/closure/spawn-thread.rs
new file mode 100644
index 00000000000..289d446c6e6
--- /dev/null
+++ b/tests/ui/ergonomic-clones/closure/spawn-thread.rs
@@ -0,0 +1,50 @@
+//@ revisions: edition2018 edition2024
+//@ [edition2018] edition: 2018
+//@ [edition2024] edition: 2024
+//@ [edition2024] check-pass
+
+#![feature(ergonomic_clones)]
+#![allow(incomplete_features)]
+
+use std::sync::Arc;
+
+fn foo() {
+    // The type is a tuple and doesn't implement UseCloned
+    let x = (Arc::new("foo".to_owned()), Arc::new(vec![1, 2, 3]), Arc::new(1));
+    for _ in 0..10 {
+        let handler = std::thread::spawn(use || {
+            //[edition2018]~^ ERROR use of moved value: `x` [E0382]
+            drop((x.0, x.1, x.2));
+        });
+        handler.join().unwrap();
+    }
+}
+
+fn bar() {
+    let x = Arc::new("foo".to_owned());
+    let y = Arc::new(vec![1, 2, 3]);
+    let z = Arc::new(1);
+
+    for _ in 0..10 {
+        let handler = std::thread::spawn(use || {
+            drop((x, y, z));
+        });
+        handler.join().unwrap();
+    }
+}
+
+fn baz() {
+    use std::sync::Arc;
+    use std::thread;
+
+    let five = Arc::new(5);
+
+    for _ in 0..10 {
+        let handler = thread::spawn(use || {
+            println!("{five:?}");
+        });
+        handler.join().unwrap();
+    }
+}
+
+fn main() {}