I have a struct defined as:
use nalgebra::{
allocator::Allocator, DefaultAllocator, Dim, DimName, MatrixN, RowVectorN, VectorN, U1,
}; // 0.22.0
pub struct Filter<Order: Dim + DimName>
where
DefaultAllocator:
Allocator<f64, Order, Order> + Allocator<f64, Order> + Allocator<f64, U1, Order>,
{
a: MatrixN<f64, Order>,
b: VectorN<f64, Order>,
c: RowVectorN<f64, Order>,
d: f64,
x: VectorN<f64, Order>,
}
In my unit test module, I want to construct an instance of Filter
:
mod tests {
use super::*;
use nalgebra::U2;
fn a_filter() -> Filter<U2> {
let a: MatrixN<f64, U2> = MatrixN::from_iterator([1., -0., 1., 0.].into_iter());
Filter {
a,
b: VectorN::zeros(),
c: RowVectorN::zeros(),
d: 0.,
x: VectorN::zeros()
}
}
}
The call to MatrixN::from_iterator()
results in compile errors. Similar errors occur in the calls to ::zeros()
:
error[E0034]: multiple applicable items in scope --> src/lib.rs:22:44 | 22 | let a: MatrixN<f64, U2> = MatrixN::from_iterator([1., -0., 1., 0.].into_iter()); | ^^^^^^^^^^^^^ multiple `from_iterator` found | = note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>` = note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>` = note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>` = note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>` error[E0034]: multiple applicable items in scope --> src/lib.rs:26:25 | 26 | b: VectorN::zeros(), | ^^^^^ multiple `zeros` found | = note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>` = note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>` = note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>` = note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>` error[E0034]: multiple applicable items in scope --> src/lib.rs:27:28 | 27 | c: RowVectorN::zeros(), | ^^^^^ multiple `zeros` found | = note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>` = note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>` = note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>` = note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>` error[E0034]: multiple applicable items in scope --> src/lib.rs:29:25 | 29 | x: VectorN::zeros(), | ^^^^^ multiple `zeros` found | = note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>` = note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>` = note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>` = note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>`
It is not clear to me why Rust is unable to figure out the correct from_iterator
to use. Is it because I've had to specify DefaultAllocator
in the definition of Filter
? If so, what's the cleanest workaround for this?
TL; DR; A workaround for your code:
You have to specify the order in the call of
zeros()
instead of guessing it from the return type.The
from_iterator
has the additional problem thatarray::into_iter()
does not return an iterator over the values but over references to the values, just likeiter()
(yes, is is perplexing, and there is a lint for that, IIRC), so you need to add acopied()
to get the proper iterator type.This is the minimum code that shows your error (playground):
The error is:
If you look careful at the candidates, they are just a the full names of:
So they have something to do with that
Dynamic
thing... If you look at the documentation it is not very helpful, but if you look at the example in thezeros()
function it has a hint:Wait... didn't it take 0 arguments? Well, looking at the code, although the documentation does not say it, it looks like
zeros()
takes as many arguments as they haveDynamic
in the generic types. AndVector3<T>
is an alias forVector<T, U3>
,DVector<T>
is an alias forVector<T, Dynamic>
and so on.You may still think that the compiler could deduce the function anyway, because the return type and the argument numbers are different for each version of
zero()
, but that is not how the compiler works: there is no function overload in Rust. If a function name resolves to more than one function it is an error.Consider this much simpler code that shows a similar error:
Note that it doesn't matter if both functions return the same or different types, or even whether they have the same number of arguments, it is always a compiler error.
The workaround for my code is: