about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2025-03-28 10:38:44 +0100
committerMara Bos <m-ou.se@m-ou.se>2025-03-29 08:10:15 +0100
commit163ea4acd0e93d5a45ea44b42a999abe39d0a93f (patch)
treefbcb5ffcb84108c32f42e1c32a20dad2dfd48f23
parent2848101ed585d93075013ab652ef82e1991b8a4d (diff)
downloadrust-163ea4acd0e93d5a45ea44b42a999abe39d0a93f.tar.gz
rust-163ea4acd0e93d5a45ea44b42a999abe39d0a93f.zip
Add more tests for pin!().
Co-authored-by: Daniel Henry-Mantilla <daniel.henry.mantilla@gmail.com>
-rw-r--r--library/coretests/tests/pin_macro.rs11
-rw-r--r--tests/ui/pin-macro/pin_move.rs26
-rw-r--r--tests/ui/pin-macro/pin_move.stderr38
3 files changed, 75 insertions, 0 deletions
diff --git a/library/coretests/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs
index 639eab740c0..3174c91a649 100644
--- a/library/coretests/tests/pin_macro.rs
+++ b/library/coretests/tests/pin_macro.rs
@@ -47,3 +47,14 @@ fn temp_lifetime() {
     }
     async fn foo(_: &mut usize) {}
 }
+
+#[test]
+fn transitive_extension() {
+    async fn temporary() {}
+
+    // `pin!` witnessed in the wild being used like this, even if it yields
+    // a `Pin<&mut &mut impl Unpin>`; it does work because `pin!`
+    // happens to transitively extend the lifespan of `temporary()`.
+    let p = pin!(&mut temporary());
+    let _use = p;
+}
diff --git a/tests/ui/pin-macro/pin_move.rs b/tests/ui/pin-macro/pin_move.rs
new file mode 100644
index 00000000000..0f6d34fad95
--- /dev/null
+++ b/tests/ui/pin-macro/pin_move.rs
@@ -0,0 +1,26 @@
+//@ edition:2024
+
+use core::marker::PhantomPinned;
+use core::pin::pin;
+
+fn a() {
+    struct NotCopy<T>(T);
+    #[allow(unused_mut)]
+    let mut pointee = NotCopy(PhantomPinned);
+    pin!(pointee);
+    let _moved = pointee;
+    //~^ ERROR use of moved value
+}
+
+fn b() {
+    struct NotCopy<T>(T);
+    let mut pointee = NotCopy(PhantomPinned);
+    pin!(*&mut pointee);
+    //~^ ERROR cannot move
+    let _moved = pointee;
+}
+
+fn main() {
+    a();
+    b();
+}
diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr
new file mode 100644
index 00000000000..c9b8ad9b202
--- /dev/null
+++ b/tests/ui/pin-macro/pin_move.stderr
@@ -0,0 +1,38 @@
+error[E0382]: use of moved value: `pointee`
+  --> $DIR/pin_move.rs:11:18
+   |
+LL |     let mut pointee = NotCopy(PhantomPinned);
+   |         ----------- move occurs because `pointee` has type `a::NotCopy<PhantomPinned>`, which does not implement the `Copy` trait
+LL |     pin!(pointee);
+   |          ------- value moved here
+LL |     let _moved = pointee;
+   |                  ^^^^^^^ value used here after move
+   |
+note: if `a::NotCopy<PhantomPinned>` implemented `Clone`, you could clone the value
+  --> $DIR/pin_move.rs:7:5
+   |
+LL |     struct NotCopy<T>(T);
+   |     ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+...
+LL |     pin!(pointee);
+   |          ------- you could clone this value
+
+error[E0507]: cannot move out of a mutable reference
+  --> $DIR/pin_move.rs:18:10
+   |
+LL |     pin!(*&mut pointee);
+   |          ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy<PhantomPinned>`, which does not implement the `Copy` trait
+   |
+note: if `b::NotCopy<PhantomPinned>` implemented `Clone`, you could clone the value
+  --> $DIR/pin_move.rs:16:5
+   |
+LL |     struct NotCopy<T>(T);
+   |     ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
+LL |     let mut pointee = NotCopy(PhantomPinned);
+LL |     pin!(*&mut pointee);
+   |          ------------- you could clone this value
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0382, E0507.
+For more information about an error, try `rustc --explain E0382`.