Infer StableInterpolate on tuples (#15931)

# Objective

Make `StableInterpolate` "just work" on tuples whose parts are each
`StableInterpolate` types. These types arise notably through
`Curve::zip` (or just through explicit mapping of a similar form). It
would otherwise be kind of frustrating to stumble upon such a thing and
then realize that, e.g., automatic resampling just doesn't work, even
though there is a very "obvious" way to do it.

## Solution

Infer `StableInterpolate` on tuples of up to size 11. I can make that
number bigger, if desired. Unfortunately, I don't think that our
standard "fake variadics" tools actually work for this; the anonymous
field accessors of tuples are `:tt` for purposes of macro expansion,
which means that you can't simplify away the identifiers by doing
something clever like using recursion (which would work if they were
`:expr`). Maybe someone who knows some incredibly dark magic could chime
in with a better solution.

The expanded impls look like this:
```rust
impl<
        T0: StableInterpolate,
        T1: StableInterpolate,
        T2: StableInterpolate,
        T3: StableInterpolate,
        T4: StableInterpolate,
    > StableInterpolate for (T0, T1, T2, T3, T4)
{
    fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
        (
            <T0 as StableInterpolate>::interpolate_stable(&self.0, &other.0, t),
            <T1 as StableInterpolate>::interpolate_stable(&self.1, &other.1, t),
            <T2 as StableInterpolate>::interpolate_stable(&self.2, &other.2, t),
            <T3 as StableInterpolate>::interpolate_stable(&self.3, &other.3, t),
            <T4 as StableInterpolate>::interpolate_stable(&self.4, &other.4, t),
        )
    }
}
```

## Testing

Expanded macros; it compiles.

## Future

Make a version of the fake variadics workflow that supports this kind of
thing.
This commit is contained in:
Matty 2024-10-15 15:55:36 -04:00 committed by GitHub
parent c1a4b82762
commit a09104b62c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -309,3 +309,81 @@ impl StableInterpolate for Dir3A {
self.slerp(*other, t) self.slerp(*other, t)
} }
} }
macro_rules! impl_stable_interpolate_tuple {
($(($T:ident, $n:tt)),*) => {
impl<$($T: StableInterpolate),*> StableInterpolate for ($($T,)*) {
fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
(
$(
<$T as StableInterpolate>::interpolate_stable(&self.$n, &other.$n, t),
)*
)
}
}
};
}
// (See `macro_metavar_expr`, which might make this better.)
// This currently implements `StableInterpolate` for tuples of up to 11 elements.
impl_stable_interpolate_tuple!((T, 0));
impl_stable_interpolate_tuple!((T0, 0), (T1, 1));
impl_stable_interpolate_tuple!((T0, 0), (T1, 1), (T2, 2));
impl_stable_interpolate_tuple!((T0, 0), (T1, 1), (T2, 2), (T3, 3));
impl_stable_interpolate_tuple!((T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4));
impl_stable_interpolate_tuple!((T0, 0), (T1, 1), (T2, 2), (T3, 3), (T4, 4), (T5, 5));
impl_stable_interpolate_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6)
);
impl_stable_interpolate_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6),
(T7, 7)
);
impl_stable_interpolate_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6),
(T7, 7),
(T8, 8)
);
impl_stable_interpolate_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6),
(T7, 7),
(T8, 8),
(T9, 9)
);
impl_stable_interpolate_tuple!(
(T0, 0),
(T1, 1),
(T2, 2),
(T3, 3),
(T4, 4),
(T5, 5),
(T6, 6),
(T7, 7),
(T8, 8),
(T9, 9),
(T10, 10)
);