Here is the method signature of the array::map method in Rust
impl<T, const N: usize> [T; N] {
//...
pub fn map<F, U>(self, f: F) -> [U; N]
where
F: FnMut(T) -> U,
//...
}
https://doc.rust-lang.org/std/primitive.array.html#method.map
It clearly states that it will consume the array, not the array reference. However, the following code compiles just fine
fn test1() -> [i32;4] {
let a = [0;4];
let b = &a;
let c = b.map(|x| x+1);
// let c = <[i32;4]>::map(b, |x| x+1); // Explicit invocation fails compilation.
return a
}
Checking MIR output confirms that the self-consuming version of the method was invoked, no iterators were involved.
bb0: {
_1 = [const 0_i32; 4]; // scope 0 at src/lib.rs:4:13: 4:18
_2 = &_1; // scope 1 at src/lib.rs:5:13: 5:15
_3 = (*_2); // scope 2 at src/lib.rs:6:13: 6:27
_0 = array::<impl [i32; 4]>::map::<[closure@src/lib.rs:6:19: 6:26], i32>(move _3, move _4) -> bb1; // scope 2 at src/lib.rs:6:13: 6:27
....
The attempt to explicitly invoke the method fails, however
fn test1() -> [i32;4] {
let a = [0;4];
let b = &a;
let c = <[i32;4]>::map(b, |x| x+1);
// mismatched types
// expected array `[i32; 4]`, found `&[{integer}; 4]`
let d = <&[i32;4]>::map(b, |x| x+1);
// the following trait bounds were not satisfied because of the requirements of the
// implementation of `Iterator` for `_`:
// `&[i32; 4]: Iterator`
return a
}
What language mechanism was behind this phenomenon? I hadn't seen such behavior on other primitive types.
Related but different question
Why does the Iterator::filter method accept a mutable reference as self?
I don't think the same thing is going on here. I don't think &[T;N] can implements a concrete type [T;N].