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.rs101
1 files changed, 35 insertions, 66 deletions
diff --git a/src/lib.rs b/src/lib.rs
index e87784d..fdefe7d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -84,7 +84,6 @@
 //! # use std::cell::Cell;
 //! #
 //! use selfref::Holder;
-//! use selfref::new_with_closure;
 //! # use selfref::opaque;
 //! #
 //! # struct MySelfRefStruct<'this> {
@@ -102,7 +101,7 @@
 //! fn main() {
 //!     // first, construct the struct
 //!     let holder = Box::pin(Holder::<'_, MySelfRefStructKey>::new_with(
-//!         new_with_closure::<MySelfRefStructKey, _>(|_| {
+//!         |foo| foo.build({
 //!             MySelfRefStruct {
 //!                 this: Cell::new(None)
 //!             }
@@ -131,7 +130,6 @@
 //! use core::pin::pin;
 //! 
 //! use selfref::Holder;
-//! use selfref::NewWith;
 //! use selfref::opaque;
 //!
 //! struct Foo<'a, 'b: 'a> {
@@ -147,23 +145,17 @@
 //! }
 //!
 //! fn main() {
-//!     // can't use real closure, "hand-roll" a closure.
-//!     struct FooBuilder<'b>(&'b str);
-//!     impl<'k, 'b: 'k> NewWith<'k, FooKey<'b>> for FooBuilder<'b> {
-//!         fn new_with<'a>(self) -> Foo<'a, 'b> where 'k: 'a {
-//!             Foo {
-//!                 foo: Default::default(),
-//!                 t: self.0,
-//!             }
-//!         }
-//!     }
-//!
 //!     // a non-'static &str
 //!     let stack_array: [u8; 5] = *b"hello";
 //!     let stack_str = core::str::from_utf8(&stack_array).unwrap();
 //!
 //!     // construct the struct
-//!     let holder = pin!(Holder::new_with(FooBuilder(stack_str)));
+//!     let holder = pin!(Holder::<'_, FooKey<'_>>::new_with(|foo| {
+//!         foo.build(Foo {
+//!             foo: Default::default(),
+//!             t: stack_str,
+//!         })
+//!     }));
 //!
 //!     holder.as_ref().operate_in(|foo| {
 //!         foo.foo.set(Some(foo.get_ref()));
@@ -427,7 +419,6 @@ macro_rules! opaque {
 /// use core::cell::Cell;
 /// 
 /// use selfref::Holder;
-/// use selfref::new_with_closure;
 /// use selfref::opaque;
 ///
 /// #[derive(Default)]
@@ -445,7 +436,7 @@ macro_rules! opaque {
 /// fn main() {
 ///     // We can use a closure here, but we need to give the compiler a hint.
 ///     let holder = Holder::<'_, FooKey>::new_with(
-///         new_with_closure::<FooKey, _>(|foo| Foo::default())
+///         |foo| foo.build(Foo::default())
 ///     );
 /// }
 /// ```
@@ -454,36 +445,23 @@ pub struct Holder<'k, T> where T: Opaque + 'k {
   inner: <T as Opaque>::Kind<'k>,
 }
 
-/// Helper trait for creating a [`Holder`].
+/// Helper for creating a [`Holder`].
 ///
 /// This is necessary because closures don't work properly here.
 ///
 /// See [`Holder::new_with`] for examples.
-pub trait NewWith<'k, T: Opaque + 'k> {
-    /// Creates a new `T::Kind` with an unbound lifetime.
-    fn new_with<'a>(self) -> T::Kind<'a> where 'k: 'a, T::Kind<'a>: Sized;
+pub struct Builder<'k, T: Opaque + 'k> where T::Kind<'k>: Sized {
+    inner: Option<T::Kind<'k>>,
 }
 
-impl<'k, T: Opaque + 'k, F> NewWith<'k, T> for F
-where
-    F: for<'a> FnOnce([&'a (); 0]) -> <T as Opaque>::Kind<'a>,
-{
-    fn new_with<'a>(self) -> T::Kind<'a> where 'k: 'a, T::Kind<'a>: Sized {
-        self([])
+impl<'k, T: Opaque + 'k> Builder<'k, T> where T::Kind<'k>: Sized {
+    /// Builds the [`Holder`].
+    #[inline]
+    pub fn build(&mut self, t: T::Kind<'k>) {
+        self.inner = Some(t);
     }
 }
 
-/// Helper for creating a [`Holder`] using a closure.
-///
-/// This only works if `K` is `'static`.
-pub fn new_with_closure<K: Opaque, F>(f: F) -> F
-where
-    F: for<'a> FnOnce([&'a (); 0]) -> <K as Opaque>::Kind<'a>,
-    for<'a> K::Kind<'a>: Sized,
-{
-    f
-}
-
 impl<'k, T> Holder<'k, T> where T: Opaque {
     /// Creates a new holder.
     ///
@@ -495,7 +473,6 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     /// use core::cell::Cell;
     /// 
     /// use selfref::Holder;
-    /// use selfref::new_with_closure;
     /// use selfref::opaque;
     ///
     /// #[derive(Default)]
@@ -513,7 +490,7 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     /// fn main() {
     ///     // We can use a closure here, but we need to help the compiler.
     ///     let holder = Holder::<'_, FooKey>::new_with(
-    ///         new_with_closure::<FooKey, _>(|foo| Foo::default())
+    ///         |foo| foo.build(Foo::default())
     ///     );
     /// }
     /// ```
@@ -525,7 +502,6 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     /// use core::marker::PhantomData;
     /// 
     /// use selfref::Holder;
-    /// use selfref::NewWith;
     /// use selfref::opaque;
     ///
     /// struct Foo<'a, 'b: 'a> {
@@ -541,28 +517,27 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     /// }
     ///
     /// fn main() {
-    ///     struct FooBuilder<'b>(&'b str);
-    ///     impl<'k, 'b: 'k> NewWith<'k, FooKey<'b>> for FooBuilder<'b> {
-    ///         fn new_with<'a>(self) -> Foo<'a, 'b> where 'k: 'a {
-    ///             Foo {
-    ///                 foo: Default::default(),
-    ///                 t: self.0,
-    ///             }
-    ///         }
-    ///     }
     ///     let stack_array: [u8; 5] = *b"hello";
     ///     // a non-'static &str
     ///     let stack_str = core::str::from_utf8(&stack_array).unwrap();
-    ///     let holder = Holder::new_with(FooBuilder(stack_str));
+    ///     let holder = Holder::<'_, FooKey<'_>>::new_with(|foo| {
+    ///         foo.build(Foo {
+    ///             foo: Default::default(),
+    ///             t: stack_str,
+    ///         });
+    ///     });
     /// }
     /// ```
     pub fn new_with<F>(f: F) -> Self
     where
-        F: NewWith<'k, T>,  T::Kind<'k>: Sized
+        F: for<'a> FnOnce(&mut Builder<'a, T>),
+        T::Kind<'k>: Sized,
     {
+        let mut builder = Builder { inner: None };
+        f(&mut builder);
         Self {
             // it is important that the constructor cannot observe 'k!
-            inner: f.new_with(),
+            inner: builder.inner.unwrap(),
             _pinned: PhantomPinned
         }
     }
@@ -600,7 +575,6 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     /// use core::pin::pin;
     /// 
     /// use selfref::Holder;
-    /// use selfref::new_with_closure;
     /// use selfref::opaque;
     ///
     /// #[derive(Default)]
@@ -617,7 +591,7 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     ///
     /// fn main() {
     ///     let holder = pin!(Holder::<'_, FooKey>::new_with(
-    ///         new_with_closure::<FooKey, _>(|foo| Foo::default())
+    ///         |foo| foo.build(Foo::default())
     ///     ));
     ///     // Actually making our Foo refer to itself.
     ///     holder.as_ref().operate_in(
@@ -639,7 +613,6 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     /// use core::pin::pin;
     /// 
     /// use selfref::Holder;
-    /// use selfref::NewWith;
     /// use selfref::opaque;
     ///
     /// struct Foo<'a, 'b: 'a> {
@@ -655,19 +628,15 @@ impl<'k, T> Holder<'k, T> where T: Opaque {
     /// }
     ///
     /// fn main() {
-    ///     struct FooBuilder<'b>(&'b str);
-    ///     impl<'k, 'b: 'k> NewWith<'k, FooKey<'b>> for FooBuilder<'b> {
-    ///         fn new_with<'a>(self) -> Foo<'a, 'b> where 'k: 'a {
-    ///             Foo {
-    ///                 foo: Default::default(),
-    ///                 t: self.0,
-    ///             }
-    ///         }
-    ///     }
     ///     let stack_array: [u8; 5] = *b"hello";
     ///     // a non-'static &str
     ///     let stack_str = core::str::from_utf8(&stack_array).unwrap();
-    ///     let holder = pin!(Holder::new_with(FooBuilder(stack_str)));
+    ///     let holder = pin!(Holder::<'_, FooKey<'_>>::new_with(|foo| {
+    ///         foo.build(Foo {
+    ///             foo: Default::default(),
+    ///             t: stack_str,
+    ///         });
+    ///     }));
     ///     // Actually making our Foo refer to itself.
     ///     holder.as_ref().operate_in(|foo| {
     ///         foo.foo.set(Some(foo.get_ref()));