--- 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