summary refs log tree commit diff stats
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs88
1 files changed, 31 insertions, 57 deletions
diff --git a/src/lib.rs b/src/lib.rs
index b8a4f86..e87784d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -86,7 +86,6 @@
 //! use selfref::Holder;
 //! use selfref::new_with_closure;
 //! # use selfref::opaque;
-//! use selfref::operate_in_closure;
 //! #
 //! # struct MySelfRefStruct<'this> {
 //! #     this: Cell<Option<&'this MySelfRefStruct<'this>>>,
@@ -112,9 +111,9 @@
 //!
 //!     // then, build the self-reference
 //!     holder.as_ref().operate_in(
-//!         operate_in_closure::<MySelfRefStructKey, _, _>(|this| {
+//!         |this| {
 //!             this.this.set(Some(this.get_ref()));
-//!         })
+//!         }
 //!     );
 //! }
 //! ```
@@ -133,7 +132,6 @@
 //! 
 //! use selfref::Holder;
 //! use selfref::NewWith;
-//! use selfref::OperateIn;
 //! use selfref::opaque;
 //!
 //! struct Foo<'a, 'b: 'a> {
@@ -167,16 +165,9 @@
 //!     // construct the struct
 //!     let holder = pin!(Holder::new_with(FooBuilder(stack_str)));
 //!
-//!     // setup the self-reference
-//!     struct SetFooRef;
-//!     impl<'k, 'b: 'k> OperateIn<'k, FooKey<'b>> for SetFooRef {
-//!         type Out = ();
-//!         fn operate_in<'a>(self, foo: Pin<&'a Foo<'a, 'b>>)
-//!         where 'k: 'a {
-//!             foo.foo.set(Some(foo.get_ref()));
-//!         }
-//!     }
-//!     holder.as_ref().operate_in(SetFooRef);
+//!     holder.as_ref().operate_in(|foo| {
+//!         foo.foo.set(Some(foo.get_ref()));
+//!     });
 //! }
 //! ```
 //!
@@ -577,32 +568,19 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     }
 }
 
-/// Helper trait for working with a [`Holder`].
+/// Wrapper around a `Pin<&'k T::Kind<'k>>` for implied bounds.
 ///
-/// This is necessary because closures don't work properly here.
-///
-/// See [`Holder::operate_in`] for examples.
-pub trait OperateIn<'k, T: Opaque + 'k> {
-    /// The value returned by this operation.
-    type Out;
-    /// Do this operation.
-    fn operate_in<'a>(self, x: Pin<&'a T::Kind<'a>>) -> Self::Out where 'k: 'a;
+/// Derefs to `Pin<&'k T::Kind<'k>>`.
+pub struct OperateIn<'k, T> where T: Opaque + 'k {
+    inner: Pin<&'k T::Kind<'k>>,
 }
 
-impl<'k, T: Opaque + 'k, F, R> OperateIn<'k, T> for F
-where F: for<'a> FnOnce(Pin<&'a T::Kind<'a>>) -> R {
-    type Out = R;
-    fn operate_in<'a>(self, x: Pin<&'a T::Kind<'a>>) -> R where 'k: 'a {
-        self(x)
-    }
-}
+impl<'k, T> core::ops::Deref for OperateIn<'k, T> where T: Opaque {
+    type Target = Pin<&'k T::Kind<'k>>;
 
-/// Helper for working with a [`Holder`] using a closure.
-///
-/// This only works if `K` is `'static`.
-pub fn operate_in_closure<K: Opaque, F, R>(f: F) -> F 
-where F: for<'a> FnOnce(Pin<&'a <K as Opaque>::Kind<'a>>) -> R {
-    f
+    fn deref(&self) -> &Pin<&'k T::Kind<'k>> {
+        &self.inner
+    }
 }
 
 impl<'k, T> Holder<'k, T> where T: Opaque {
@@ -624,7 +602,6 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     /// use selfref::Holder;
     /// use selfref::new_with_closure;
     /// use selfref::opaque;
-    /// use selfref::operate_in_closure;
     ///
     /// #[derive(Default)]
     /// struct Foo<'a> {
@@ -644,9 +621,9 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     ///     ));
     ///     // Actually making our Foo refer to itself.
     ///     holder.as_ref().operate_in(
-    ///         operate_in_closure::<FooKey, _, _>(|foo| {
+    ///         |foo| {
     ///             foo.foo.set(Some(foo.get_ref()));
-    ///         })
+    ///         }
     ///     );
     /// }
     /// ```
@@ -663,7 +640,6 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     /// 
     /// use selfref::Holder;
     /// use selfref::NewWith;
-    /// use selfref::OperateIn;
     /// use selfref::opaque;
     ///
     /// struct Foo<'a, 'b: 'a> {
@@ -693,34 +669,32 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     ///     let stack_str = core::str::from_utf8(&stack_array).unwrap();
     ///     let holder = pin!(Holder::new_with(FooBuilder(stack_str)));
     ///     // Actually making our Foo refer to itself.
-    ///     struct SetFooRef;
-    ///     impl<'k, 'b: 'k> OperateIn<'k, FooKey<'b>> for SetFooRef {
-    ///         type Out = ();
-    ///         fn operate_in<'a>(self, foo: Pin<&'a Foo<'a, 'b>>)
-    ///         where 'k: 'a {
-    ///             foo.foo.set(Some(foo.get_ref()));
-    ///         }
-    ///     }
-    ///     holder.as_ref().operate_in(SetFooRef);
+    ///     holder.as_ref().operate_in(|foo| {
+    ///         foo.foo.set(Some(foo.get_ref()));
+    ///     });
     /// }
     /// ```
     pub fn operate_in<'i, F, R>(self: Pin<&'i Self>, f: F) -> R
     where 
-        F: OperateIn<'k, T, Out=R>
+        F: for<'x> FnOnce(OperateIn<'x, T>) -> R
     {
-        /// Converts Pin<&'a T::Kind<'k>> to Pin<&'b T::Kind<'b>>
+        /// Converts `Pin<&'a T::Kind<'k>>` to `Pin<&'b T::Kind<'b>>`.
+        ///
+        /// Not sure why this is called "upcast_dangling" since none of these
+        /// are actually dangling. But anyway.
         unsafe fn upcast_dangling<'a, 'b, 'c, T: Opaque + 'c>(
             x: Pin<&'a T::Kind<'c>>,
         ) -> Pin<&'b T::Kind<'b>>
         where T::Kind<'c>: 'a {
             mem::transmute(x)
         }
-
-        f.operate_in(unsafe {
-            upcast_dangling::<'i, 'k, '_, T>
-            (self.map_unchecked(|self_ref| {
-                &self_ref.inner
-            }))
+        f(OperateIn {
+            inner: unsafe {
+                upcast_dangling::<'i, 'k, '_, T>
+                (self.map_unchecked(|self_ref| {
+                    &self_ref.inner
+                }))
+            }
         })
     }
 }