//! 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>>, } 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()); }); }