diff -r 1f19c6bbf07b -r 3868555d135c src/instance.rs --- a/src/instance.rs Sun Apr 27 20:29:43 2025 -0500 +++ b/src/instance.rs Fri May 15 14:46:30 2026 -0500 @@ -23,32 +23,252 @@ } } -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; + + /// Returns an owned instance or a reference to one. + fn cow_owned<'b>(self) -> MyCow<'b, Self::OwnedVariant> + where + Self: 'b; + + /// Returns an owned instance or a reference to one. + fn ref_cow_owned<'b>(&'b self) -> MyCow<'b, Self::OwnedVariant> + where + Self: 'b; +} + +impl<'a, X: Ownable> Ownable for &'a X { + type OwnedVariant = X::OwnedVariant; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { + X::clone_owned(self) + } + + #[inline] + fn clone_owned(&self) -> Self::OwnedVariant { + X::clone_owned(self) + } + #[inline] - pub fn into_owned(self) -> X where X : Clone { + fn cow_owned<'b>(self) -> MyCow<'b, Self::OwnedVariant> + where + Self: 'b, + { + X::ref_cow_owned(self) + } + + fn ref_cow_owned<'b>(&self) -> MyCow<'b, Self::OwnedVariant> + where + Self: 'b, + { + X::ref_cow_owned(self) + } +} + +impl<'a, X: Ownable> Ownable for &'a mut X { + type OwnedVariant = X::OwnedVariant; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { + X::clone_owned(self) + } + + #[inline] + fn clone_owned(&self) -> Self::OwnedVariant { + X::clone_owned(self) + } + + #[inline] + fn cow_owned<'b>(self) -> MyCow<'b, Self::OwnedVariant> + where + Self: 'b, + { + X::ref_cow_owned(self) + } + + fn ref_cow_owned<'b>(&'b self) -> MyCow<'b, Self::OwnedVariant> + where + Self: 'b, + { + X::ref_cow_owned(self) + } +} + +impl<'a, A, B> Ownable for EitherDecomp +where + A: Ownable, + B: Ownable, +{ + type OwnedVariant = A::OwnedVariant; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { match self { - EitherDecomp::Owned(x) => x, - EitherDecomp::Borrowed(x) => x.clone(), + EitherDecomp::Owned(a) => A::into_owned(a), + EitherDecomp::Borrowed(b) => B::into_owned(b), + } + } + + #[inline] + fn clone_owned(&self) -> Self::OwnedVariant { + match self { + EitherDecomp::Owned(a) => A::clone_owned(a), + EitherDecomp::Borrowed(b) => B::clone_owned(b), + } + } + + #[inline] + fn cow_owned<'b>(self) -> MyCow<'b, Self::OwnedVariant> + where + A: 'b, + B: 'b, + { + match self { + EitherDecomp::Owned(a) => A::cow_owned(a), + EitherDecomp::Borrowed(b) => B::cow_owned(b), + } + } + + #[inline] + fn ref_cow_owned<'b>(&'b self) -> MyCow<'b, Self::OwnedVariant> + where + Self: 'b, + { + match self { + EitherDecomp::Owned(a) => A::ref_cow_owned(a), + EitherDecomp::Borrowed(b) => B::ref_cow_owned(b), } } } +#[macro_export] +macro_rules! self_ownable { + ($type:ty where $($qual:tt)*) => { + impl<$($qual)*> $crate::instance::Ownable for $type { + type OwnedVariant = Self; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { + self + } + + fn clone_owned(&self) -> Self::OwnedVariant { + self.clone() + } + + fn cow_owned<'b>(self) -> $crate::instance::MyCow<'b, Self::OwnedVariant> + where + Self: 'b, + { + $crate::instance::MyCow::Owned(self) + } + + fn ref_cow_owned<'b>(&'b self) -> $crate::instance::MyCow<'b, Self::OwnedVariant> + where + Self: 'b, + { + $crate::instance::MyCow::Borrowed(self) + } + } + }; +} + +self_ownable!(Vec where T : Clone); + +impl<'a, T: Clone> Ownable for &'a [T] { + type OwnedVariant = Vec; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { + Vec::from(self) + } + + #[inline] + fn clone_owned(&self) -> Self::OwnedVariant { + Vec::from(*self) + } + + #[inline] + fn cow_owned<'b>(self) -> MyCow<'b, Self::OwnedVariant> + where + Self: 'b, + { + MyCow::Owned(Vec::from(self)) + } + + fn ref_cow_owned<'b>(&'b self) -> MyCow<'b, Self::OwnedVariant> + where + Self: 'b, + { + MyCow::Owned(Vec::from(*self)) + } +} + /// Trait for abitrary mathematical spaces. -pub trait Space : Instance { +pub trait Space: Ownable + Sized { + /// Principal, typically owned realisation of the space. + type Principal: ClosedSpace; + /// Default decomposition for the space - type Decomp : Decomposition; + 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 Principal = 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 + } + + #[inline] + fn cow_owned<'b>(self) -> MyCow<'b, Self::OwnedVariant> where Self : 'b { + MyCow::Owned(self) + } + + #[inline] + fn ref_cow_owned<'b>(&self) -> MyCow<'b, Self::OwnedVariant> where Self : 'b { + MyCow::Owned(*self) + } } }; } @@ -58,17 +278,21 @@ f32 f64); /// Marker type for decompositions to be used with [`Instance`]. -pub trait Decomposition : Sized { +pub trait Decomposition: Sized { /// Possibly owned form of the decomposition - type Decomposition<'b> : Instance where X : 'b; + type Decomposition<'b>: Instance + where + X: 'b; /// Unlikely owned form of the decomposition. /// Type for a lightweight intermediate conversion that does not own the original variable. /// Usually this is just a reference, but may also be a lightweight structure that /// contains references; see the implementation for [`crate::direct_product::Pair`]. - type Reference<'b> : Instance + Copy where X : 'b; + type Reference<'b>: Instance + Copy + where + X: 'b; - /// Left the lightweight reference type into a full decomposition type. - fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b>; + /// Lift the lightweight reference type into a full decomposition type. + fn lift<'b>(r: Self::Reference<'b>) -> Self::Decomposition<'b>; } /// Most common [`Decomposition`] (into `Either`) that allows working with owned @@ -76,12 +300,18 @@ #[derive(Copy, Clone, Debug)] pub struct BasicDecomposition; -impl Decomposition for BasicDecomposition { - type Decomposition<'b> = MyCow<'b, X> where X : 'b; - type Reference<'b> = &'b X where X : 'b; +impl Decomposition for BasicDecomposition { + type Decomposition<'b> + = MyCow<'b, X> + where + X: 'b; + type Reference<'b> + = &'b X + where + X: 'b; #[inline] - fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b> { + fn lift<'b>(r: Self::Reference<'b>) -> Self::Decomposition<'b> { MyCow::Borrowed(r) } } @@ -91,192 +321,225 @@ /// 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 where D : Decomposition { - /// Decomposes self according to `decomposer`. - fn decompose<'b>(self) -> D::Decomposition<'b> - where Self : 'b, X : 'b; - - /// Returns a lightweight instance of `self`. - fn ref_instance(&self) -> D::Reference<'_>; +pub trait Instance::Decomp>: Sized +where + X: Space, + D: Decomposition, +{ + /// Decomposes self according to `decomposer`, and evaluate `f` on the result. + /// Consumes self. + #[inline] + fn eval_decompose<'b, R>(self, f: impl FnOnce(D::Decomposition<'b>) -> R) -> R + where + X: 'b, + Self: 'b, + { + f(self.decompose()) + } + + /// Does a light decomposition of self `decomposer`, and evaluates `f` on the result. + /// Does not consume self. + fn eval_ref<'b, R>(&'b self, f: impl FnOnce(D::Reference<'b>) -> R) -> R + where + X: 'b, + Self: 'b; /// Returns an owned instance of `X`, cloning or converting non-true instances when necessary. - fn own(self) -> X; + fn own(self) -> X::Principal; - // ************** automatically implemented methods below from here ************** + fn decompose<'b>(self) -> D::Decomposition<'b> + where + Self: 'b; /// Returns an owned instance or reference to `X`, converting non-true instances when necessary. /// /// Default implementation uses [`Self::own`]. Consumes the input. - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b { - MyCow::Owned(self.own()) - } - + fn cow<'b>(self) -> MyCow<'b, X::Principal> + where + Self: 'b; + #[inline] /// Evaluates `f` on a reference to self. /// /// Default implementation uses [`Self::cow`]. Consumes the input. - fn eval<'b, R>(self, f : impl FnOnce(&X) -> R) -> R - where X : 'b, Self : 'b + fn eval<'b, R>(self, f: impl FnOnce(&X::Principal) -> R) -> R + where + X: 'b, + Self: 'b, { f(&*self.cow()) } - - #[inline] - /// Evaluates `f` or `g` depending on whether a reference or owned value is available. - /// - /// Default implementation uses [`Self::cow`]. Consumes the input. - fn either<'b, R>( - self, - f : impl FnOnce(X) -> R, - g : impl FnOnce(&X) -> R - ) -> R - where Self : 'b - { - match self.cow() { - EitherDecomp::Owned(x) => f(x), - EitherDecomp::Borrowed(x) => g(x), - } - } } - -impl Instance for X { +impl Instance for X { #[inline] - fn decompose<'b>(self) -> >::Decomposition<'b> - where Self : 'b, X : 'b + fn eval_ref<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R + where + X: 'b, + Self: 'b, { - MyCow::Owned(self) + f(self) } #[inline] - fn own(self) -> X { - self + fn own(self) -> X::Principal { + self.into_owned() + } + + #[inline] + fn cow<'b>(self) -> MyCow<'b, X::Principal> + where + Self: 'b, + { + self.cow_owned() } #[inline] - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b { + fn decompose<'b>(self) -> MyCow<'b, X> + where + Self: 'b, + { MyCow::Owned(self) } +} + +impl<'a, X: Space> Instance for &'a X { + #[inline] + fn eval_ref<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R + where + X: 'b, + Self: 'b, + { + f(*self) + } #[inline] - fn ref_instance(&self) -> >::Reference<'_> { - self + fn own(self) -> X::Principal { + self.into_owned() } -} -impl<'a, X : Space + Clone> Instance for &'a X { #[inline] - fn decompose<'b>(self) -> >::Decomposition<'b> - where Self : 'b, X : 'b + fn cow<'b>(self) -> MyCow<'b, X::Principal> + where + Self: 'b, + { + self.cow_owned() + } + + #[inline] + fn decompose<'b>(self) -> MyCow<'b, X> + where + Self: 'b, { MyCow::Borrowed(self) } +} +impl<'a, X: Space> Instance for &'a mut X { #[inline] - fn own(self) -> X { - self.clone() - } - - #[inline] - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b { - MyCow::Borrowed(self) + fn eval_ref<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R + where + X: 'b, + Self: 'b, + { + f(*self) } #[inline] - fn ref_instance(&self) -> >::Reference<'_> { - *self - } -} - -impl<'a, X : Space + Clone> Instance for &'a mut X { - #[inline] - fn decompose<'b>(self) -> >::Decomposition<'b> - where Self : 'b, X : 'b - { - EitherDecomp::Borrowed(self) + fn own(self) -> X::Principal { + self.into_owned() } #[inline] - fn own(self) -> X { - self.clone() + fn cow<'b>(self) -> MyCow<'b, X::Principal> + where + Self: 'b, + { + self.cow_owned() } #[inline] - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b, X : Clone { - EitherDecomp::Borrowed(self) - } - - #[inline] - fn ref_instance(&self) -> >::Reference<'_> { - *self + fn decompose<'b>(self) -> MyCow<'b, X> + where + Self: 'b, + { + MyCow::Borrowed(self) } } -impl<'a, X : Space + Clone> Instance for MyCow<'a, X> { - +impl<'a, X: Space> Instance for MyCow<'a, X> { #[inline] - fn decompose<'b>(self) -> >::Decomposition<'b> - where Self : 'b, X : 'b + fn eval_ref<'b, R>(&'b self, f: impl FnOnce(&'b X) -> R) -> R + where + X: 'b, + Self: 'b, { - self - } - - #[inline] - fn own(self) -> X { match self { - MyCow::Borrowed(a) => a.own(), - MyCow::Owned(b) => b.own() + MyCow::Borrowed(a) => f(a), + MyCow::Owned(b) => f(&b), } } #[inline] - fn cow<'b>(self) -> MyCow<'b, X> where Self : 'b { - match self { - MyCow::Borrowed(a) => a.cow(), - MyCow::Owned(b) => b.cow() - } + fn own(self) -> X::Principal { + self.into_owned() } #[inline] - fn ref_instance(&self) -> >::Reference<'_> { - match self { - MyCow::Borrowed(a) => a, - MyCow::Owned(b) => &b, - } + fn cow<'b>(self) -> MyCow<'b, X::Principal> + where + Self: 'b, + { + self.cow_owned() } -} - -/// Marker type for mutable decompositions to be used with [`InstanceMut`]. -pub trait DecompositionMut : Sized { - type ReferenceMut<'b> : InstanceMut where X : 'b; -} - -/// Helper trait for functions to work with mutable references. -pub trait InstanceMut::Decomp> : Sized where D : DecompositionMut { - /// Returns a mutable decomposition of self. - fn ref_instance_mut(&mut self) -> D::ReferenceMut<'_>; -} - -impl DecompositionMut for BasicDecomposition { - type ReferenceMut<'b> = &'b mut X where X : 'b; -} - -/// This impl may seem pointless, but allows throwaway mutable scratch variables -impl<'a, X : Space> InstanceMut for X { #[inline] - fn ref_instance_mut(&mut self) - -> >::ReferenceMut<'_> + fn decompose<'b>(self) -> MyCow<'b, X> + where + Self: 'b, { self } } -impl<'a, X : Space> InstanceMut for &'a mut X { +/// Marker type for mutable decompositions to be used with [`InstanceMut`]. +pub trait DecompositionMut: Sized { + type ReferenceMut<'b>: InstanceMut + where + X: 'b; +} + +/// Helper trait for functions to work with mutable references. +pub trait InstanceMut::Decomp>: Sized +where + D: DecompositionMut, +{ + /// Returns a mutable decomposition of self. + fn ref_instance_mut(&mut self) -> D::ReferenceMut<'_>; +} + +impl DecompositionMut for BasicDecomposition { + type ReferenceMut<'b> + = &'b mut X + where + X: 'b; +} + +/// This impl may seem pointless, but allows throwaway mutable scratch variables +impl<'a, X: Space> InstanceMut for X { #[inline] - fn ref_instance_mut(&mut self) - -> >::ReferenceMut<'_> - { + fn ref_instance_mut( + &mut self, + ) -> >::ReferenceMut<'_> { self } } + +impl<'a, X: Space> InstanceMut for &'a mut X { + #[inline] + fn ref_instance_mut( + &mut self, + ) -> >::ReferenceMut<'_> { + self + } +}