about summary refs log tree commit diff
diff options
context:
space:
mode:
-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`.