src/instance.rs

branch
dev
changeset 150
c4e394a9c84c
parent 133
2b13f8a0c8ba
child 152
dab30b331f49
child 153
829c07ea584d
--- a/src/instance.rs	Mon Sep 01 00:04:22 2025 -0500
+++ b/src/instance.rs	Mon Sep 01 13:51:03 2025 -0500
@@ -23,35 +23,117 @@
     }
 }
 
-impl<'b, X> MyCow<'b, X> {
+/// Trait for ownable-by-consumption objects
+pub trait Ownable {
+    type OwnedVariant: Clone;
+
+    /// Returns an owned instance, possibly consuming the original,
+    /// avoiding cloning when possible.
+    fn into_owned(self) -> Self::OwnedVariant;
+
+    /// Returns an owned instance of a reference.
+    fn clone_owned(&self) -> Self::OwnedVariant;
+}
+
+impl<'a, X: Ownable> Ownable for &'a X {
+    type OwnedVariant = X::OwnedVariant;
+
+    #[inline]
+    /// Returns an owned instance.
+    fn into_owned(self) -> Self::OwnedVariant {
+        self.clone_owned()
+    }
+
     #[inline]
-    pub fn into_owned(self) -> X
-    where
-        X: Clone,
-    {
+    /// Returns an owned instance.
+    fn clone_owned(&self) -> Self::OwnedVariant {
+        (*self).into_owned()
+    }
+}
+
+impl<'a, X: Ownable> Ownable for &'a mut X {
+    type OwnedVariant = X::OwnedVariant;
+
+    #[inline]
+    /// Returns an owned instance.
+    fn into_owned(self) -> Self::OwnedVariant {
+        self.clone_owned()
+    }
+
+    #[inline]
+    /// Returns an owned instance.
+    fn clone_owned(&self) -> Self::OwnedVariant {
+        (&**self).into_owned()
+    }
+}
+
+impl<'a, X: Ownable> Ownable for MyCow<'a, X> {
+    type OwnedVariant = X::OwnedVariant;
+
+    #[inline]
+    /// Returns an owned instance.
+    fn into_owned(self) -> Self::OwnedVariant {
         match self {
-            EitherDecomp::Owned(x) => x,
-            EitherDecomp::Borrowed(x) => x.clone(),
+            EitherDecomp::Owned(x) => x.into_owned(),
+            EitherDecomp::Borrowed(x) => x.into_owned(),
+        }
+    }
+
+    #[inline]
+    /// Returns an owned instance.
+    fn clone_owned(&self) -> Self::OwnedVariant {
+        match self {
+            EitherDecomp::Owned(x) => x.into_owned(),
+            EitherDecomp::Borrowed(x) => x.into_owned(),
         }
     }
 }
 
 /// Trait for abitrary mathematical spaces.
-pub trait Space: Instance<Self, Self::Decomp> {
+pub trait Space: Ownable<OwnedVariant = Self::OwnedSpace> + Sized {
+    type OwnedSpace: ClosedSpace;
+
     /// Default decomposition for the space
     type Decomp: Decomposition<Self>;
 }
 
+mod private {
+    pub trait Sealed {}
+}
+
+/// Helper trait for working with own types.
+pub trait Owned: Ownable<OwnedVariant = Self> + private::Sealed {}
+impl<X: Ownable<OwnedVariant = X>> private::Sealed for X {}
+impl<X: Ownable<OwnedVariant = X>> Owned for X {}
+
+/// Helper trait for working with closed spaces, operations in which should
+/// return members of the same space
+pub trait ClosedSpace: Space<OwnedSpace = Self> + Owned + Instance<Self> {}
+impl<X: Space<OwnedSpace = Self> + Owned + Instance<Self>> ClosedSpace for X {}
+
 #[macro_export]
 macro_rules! impl_basic_space {
-    ($($type:ty)*) => { $(
-        impl $crate::instance::Space for $type {
+    ($($type:ty)*) => {
+        $( $crate::impl_basic_space!($type where ); )*
+    };
+    ($type:ty where $($where:tt)*) => {
+        impl<$($where)*> $crate::instance::Space for $type {
+            type OwnedSpace = Self;
             type Decomp = $crate::instance::BasicDecomposition;
         }
-    )* };
-    ($type:ty where $($where:tt)*) => {
-        impl<$($where)*> $crate::instance::Space for $type {
-            type Decomp = $crate::instance::BasicDecomposition;
+
+        impl<$($where)*> $crate::instance::Ownable for $type {
+            type OwnedVariant = Self;
+
+            #[inline]
+            fn into_owned(self) -> Self::OwnedVariant {
+                self
+            }
+
+            #[inline]
+            fn clone_owned(&self) -> Self::OwnedVariant {
+                *self
+            }
         }
     };
 }
@@ -83,7 +165,7 @@
 #[derive(Copy, Clone, Debug)]
 pub struct BasicDecomposition;
 
-impl<X: Space + Clone> Decomposition<X> for BasicDecomposition {
+impl<X: Space> Decomposition<X> for BasicDecomposition {
     type Decomposition<'b>
         = MyCow<'b, X>
     where
@@ -104,8 +186,9 @@
 /// generalises [`std::borrow::ToOwned`], [`std::borrow::Borrow`], and [`std::borrow::Cow`].
 ///
 /// This is used, for example, by [`crate::mapping::Mapping::apply`].
-pub trait Instance<X: Space, D = <X as Space>::Decomp>: Sized
+pub trait Instance<X, D = <X as Space>::Decomp>: Sized + Ownable
 where
+    X: Space,
     D: Decomposition<X>,
 {
     /// Decomposes self according to `decomposer`, and evaluate `f` on the result.
@@ -164,7 +247,7 @@
     }
 }
 
-impl<X: Space + Clone> Instance<X, BasicDecomposition> for X {
+impl<X: Space> Instance<X, BasicDecomposition> for X {
     #[inline]
     fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R
     where
@@ -197,7 +280,7 @@
     }
 }
 
-impl<'a, X: Space + Clone> Instance<X, BasicDecomposition> for &'a X {
+impl<'a, X: Space> Instance<X, BasicDecomposition> for &'a X {
     #[inline]
     fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R
     where
@@ -218,7 +301,7 @@
 
     #[inline]
     fn own(self) -> X {
-        self.clone()
+        self.into_owned()
     }
 
     #[inline]
@@ -230,7 +313,7 @@
     }
 }
 
-impl<'a, X: Space + Clone> Instance<X, BasicDecomposition> for &'a mut X {
+impl<'a, X: Space> Instance<X, BasicDecomposition> for &'a mut X {
     #[inline]
     fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R
     where
@@ -251,20 +334,19 @@
 
     #[inline]
     fn own(self) -> X {
-        self.clone()
+        self.into_owned()
     }
 
     #[inline]
     fn cow<'b>(self) -> MyCow<'b, X>
     where
         Self: 'b,
-        X: Clone,
     {
         EitherDecomp::Borrowed(self)
     }
 }
 
-impl<'a, X: Space + Clone> Instance<X, BasicDecomposition> for MyCow<'a, X> {
+impl<'a, X: Space> Instance<X, BasicDecomposition> for MyCow<'a, X> {
     #[inline]
     fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R
     where

mercurial