1

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
....

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=e2c046f4d83051fadb2e51b32a7d3e08

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].

First_Strike
  • 1,029
  • 1
  • 10
  • 27

1 Answers1

0

Alright, it seems that all Copy types can use references as receivers. They just automatically deref it under that specific syntax

First_Strike
  • 1,029
  • 1
  • 10
  • 27