Repository: bevyengine/bevy
File: crates/bevy_math/src/common_traits.rs (Rust)

Code before:
/// [`TryStableInterpolate`] is more conservative, and doesn't automatically convert between
/// color spaces. This produces a color interpolation that is has more predictable performance.
///
/// [`Val::Px`]: https://docs.rs/bevy/latest/bevy/ui/enum.Val.html
/// [`Val::Percent`]: https://docs.rs/bevy/latest/bevy/ui/enum.Val.html
/// [`Val`]: https://docs.rs/bevy/latest/bevy/ui/struct.enum.html
/// [`Color`]: https://docs.rs/bevy/latest/bevy/color/enum.Color.html
pub trait TryStableInterpolate: Clone {
    /// Attempt to interpolate the value. This may fail if the two interpolation values have
    /// different units, or if the type is not interpolable.
    fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, InterpolationError>;
}

impl<T: StableInterpolate> TryStableInterpolate for T {
    fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, InterpolationError> {
        Ok(self.interpolate_stable(other, t))
    }
}

/// Boolean values can never be interpolated, but they can be animatable parameters (for things
/// like enabling and disabling lighting).
impl TryStableInterpolate for bool {
    fn try_interpolate_stable(&self, _other: &Self, _t: f32) -> Result<Self, InterpolationError> {
        Err(InterpolationError::NonContiguous)
    }
}

/// A type that has tangents.
pub trait HasTangent {
    /// The tangent type.
    type Tangent: VectorSpace;
}

/// A value with its derivative.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct WithDerivative<T>
where
    T: HasTangent,
{
    /// The underlying value.
    pub value: T,

    /// The derivative at `value`.
    pub derivative: T::Tangent,
}

/// A value together with its first and second derivatives.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]

Review comment (suggestion):
If this will always return an error, then I don't think it's an interpolate-able type.
```suggestion
```

Code after:
/// [`Color`]: https://docs.rs/bevy/latest/bevy/color/enum.Color.html
pub trait TryStableInterpolate: Clone {
    /// Error produced when the value cannot be interpolated.
    type Error;

    /// Attempt to interpolate the value. This may fail if the two interpolation values have
    /// different units, or if the type is not interpolable.
    fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, Self::Error>;
}

impl<T: StableInterpolate> TryStableInterpolate for T {
    type Error = Infallible;
    fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, Self::Error> {
        Ok(self.interpolate_stable(other, t))
    }
}

/// A type that has tangents.
pub trait HasTangent {
    /// The tangent type.
    type Tangent: VectorSpace;
}

/// A value with its derivative.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct WithDerivative<T>
where
    T: HasTangent,
{
    /// The underlying value.
    pub value: T,

    /// The derivative at `value`.
    pub derivative: T::Tangent,
}

/// A value together with its first and second derivatives.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct WithTwoDerivatives<T>
where
    T: HasTangent,
{
    /// The underlying value.
    pub value: T,

    /// The derivative at `value`.
    pub derivative: T::Tangent,