diff -r 2f1798c65fd6 -r c4e394a9c84c src/instance.rs --- 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 { +pub trait Space: Ownable + Sized { + type OwnedSpace: ClosedSpace; + /// Default decomposition for the space type Decomp: Decomposition; } +mod private { + pub trait Sealed {} +} + +/// Helper trait for working with own types. +pub trait Owned: Ownable + private::Sealed {} +impl> private::Sealed for X {} +impl> Owned for X {} + +/// Helper trait for working with closed spaces, operations in which should +/// return members of the same space +pub trait ClosedSpace: Space + Owned + Instance {} +impl + Owned + Instance> 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 Decomposition for BasicDecomposition { +impl Decomposition 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::Decomp>: Sized +pub trait Instance::Decomp>: Sized + Ownable where + X: Space, D: Decomposition, { /// Decomposes self according to `decomposer`, and evaluate `f` on the result. @@ -164,7 +247,7 @@ } } -impl Instance for X { +impl Instance 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 for &'a X { +impl<'a, X: Space> Instance 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 for &'a mut X { +impl<'a, X: Space> Instance 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 for MyCow<'a, X> { +impl<'a, X: Space> Instance for MyCow<'a, X> { #[inline] fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R where