summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2022-12-11 18:44:00 -0300
committerSoniEx2 <endermoneymod@gmail.com>2022-12-11 18:44:00 -0300
commitf1e7d76c7ce610b6a1e9e66cdd6cfa78436ab511 (patch)
tree66183146b4ecb748ae5890da1330c7193f112775
parent72841de072c4a904983e9eb631b690a61d3e06ff (diff)
Add tests for moving the pin
-rw-r--r--tests/movable.rs58
1 files changed, 58 insertions, 0 deletions
diff --git a/tests/movable.rs b/tests/movable.rs
new file mode 100644
index 0000000..f702979
--- /dev/null
+++ b/tests/movable.rs
@@ -0,0 +1,58 @@
+//! Tests of "moving" a holder.
+//!
+//! We cannot move the actual holders themselves but we can move owned handles
+//! (Box, Rc, etc) to them.
+
+use std::cell::Cell;
+use std::rc::Rc;
+
+use selfref::Holder;
+use selfref::opaque;
+
+struct Foo<'this> {
+    foo: Cell<Option<&'this Foo<'this>>>,
+}
+
+struct FooKey;
+
+opaque! {
+    impl Opaque for FooKey {
+        type Kind<'this> = Foo<'this>;
+    }
+}
+
+fn create_holder() -> Holder<'static, FooKey> {
+    Holder::new_with(|builder| builder.build(Foo {
+        foo: Cell::new(None),
+    }))
+}
+
+#[test]
+fn move_box() {
+    // this is UB without the !Unpin hack
+    // same goes for any pinned container that has &mut's to it.
+    let b1 = Box::pin(create_holder());
+    b1.as_ref().operate_in(|foo| {
+        foo.foo.set(Some(foo.get_ref()));
+    });
+    let b2 = b1;
+    b2.as_ref().operate_in(|foo| {
+        // check that we can access the self-reference
+        assert!(foo.foo.get().unwrap().foo.get().is_some());
+    });
+}
+
+#[test]
+fn move_rc() {
+    // this is perfectly fine without the !Unpin hack!
+    // any container that behaves like a shared ref is fine for this.
+    let b1 = Rc::pin(create_holder());
+    b1.as_ref().operate_in(|foo| {
+        foo.foo.set(Some(foo.get_ref()));
+    });
+    let b2 = b1;
+    b2.as_ref().operate_in(|foo| {
+        // check that we can access the self-reference
+        assert!(foo.foo.get().unwrap().foo.get().is_some());
+    });
+}