Hi there. I’m working on a small library that does some matrix math and decided to make it more generic. Instead of having a Matrix4x4 type, I was hoping to build a Matrix<M, N> type and use associated constants to create the underlying array. It seemed like this should be straight forward, but I have not been able to make the compiler happy.
I tried a handful of permutations, but the errors are the same and make me think I’ve run into an edge case not supported by the compiler–or I’ve completely misunderstood something (more likely). Any insight into what I could do here?
Thanks!
pub trait Size {
const VALUE: usize; // Two warnings here...
}
pub struct One;
pub struct Two;
pub struct Three;
pub struct Four;
impl Size for One { const VALUE: usize = 1; }
impl Size for Two { const VALUE: usize = 2; }
impl Size for Three { const VALUE: usize = 3; }
impl Size for Four { const VALUE: usize = 4; }
pub struct Matrix<M: Size, N: Size> {
matrix: [f32; <M as Size>::VALUE * <N as Size>::VALUE], // Two errors here
m: std::marker::PhantomData<M>,
n: std::marker::PhantomData<N>,
}
impl<M: Size, N: Size> Matrix<M, N> {
pub fn is_square(&self) > bool {
// No errors, this works
<M as Size>::VALUE == <N as Size>::VALUE
}
pub fn size(&self) > f32 {
// No errors, this works
<M as Size>::VALUE * <N as Size>::VALUE
}
pub fn new() > Self {
// No errors, this works
let matrix = [0; <M as Size>::VALUE * <N as Size>::VALUE];
Self {
matrix,
m: std::marker::PhantomData,
n: std::marker::PhantomData,
}
}
}
impl<M: Size> Matrix<M, M> {
fn det(&self) > f32 {
42.
}
}
#[inline]
pub fn new_zero<M: Size, N: Size>() > Matrix<M, N> {
// This function appears to work...
let matrix = [0; <M as Size>::VALUE * <N as Size>::VALUE];
Matrix {
matrix,
m: std::marker::PhantomData,
n: std::marker::PhantomData,
}
}
type Matrix3x4 = Matrix<Three, Four>;
fn main() {
let matrix4x4 = new_zero::<Four, Four>();
let det = matrix4x4.det();
assert_eq!(det, 42.);
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `M: Size` is not satisfied
> src/main.rs:16:19

16  matrix: [f32; <M as Size>::VALUE * <N as Size>::VALUE], // Two errors here
 ^^^^^^^^^^^^^^^^^^ the trait `Size` is not implemented for `M`

= help: consider adding a `where M: Size` bound
note: required by `Size::VALUE`
> src/main.rs:2:5

2  const VALUE: usize; // Two warnings here...
 ^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `N: Size` is not satisfied
> src/main.rs:16:40

16  matrix: [f32; <M as Size>::VALUE * <N as Size>::VALUE], // Two errors here
 ^^^^^^^^^^^^^^^^^^ the trait `Size` is not implemented for `N`

= help: consider adding a `where N: Size` bound
note: required by `Size::VALUE`
> src/main.rs:2:5

2  const VALUE: usize; // Two warnings here...
 ^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc explain E0277`.
error: Could not compile `playground`.
To learn more, run the command again with verbose.