iter()とinto_iter()の違いとちょっとした落とし穴

説明したのでメモ。

# `iter()`と`into_iter()`の違い

色々な`iter()`と`into_iter()`について。公式[リファレンス][iter_reference]を見ればそれぞれの役割はわかります。

>There are three common methods which can create iterators from a collection:
>
>iter(), which iterates over &T.
>iter_mut(), which iterates over &mut T.
>into_iter(), which iterates over T.
>
>Various things in the standard library may implement one or more of the three, where appropriate.

少なくともstdライブラリでは`iter()`と`iter_mut()`で得られるIteratorは`&T`を、`into_iter()`では`T`を持っている感じでやりましょう、という慣習があるらしいです（昔の議論とか見てると元々はそうではなかったっぽいですが）。

以下に`Vector`を使った例を示します。（[Rust by Example][rust_by_example]より）

```rust
let vec1 = vec![1, 2, 3];
let vec2 = vec![4, 5, 6];
println!("2 in vec1: {}", vec1.iter()     .any(|&x| x == 2));
println!("2 in vec2: {}", vec2.into_iter().any(| x| x == 2));
```
`iter()`では参照が、`into_iter()`では値が渡されているのがわかりますね。

## `into_iter()`と`for`ループの関係

また、この中で`into_iter()`は`for`ループで使われます。これも[リファレンス][iter_reference]から引用しますが、

```rust
let values = vec![1, 2, 3, 4, 5];

for x in values {
    println!("{}", x);
}
```

これが、

```rust
let values = vec![1, 2, 3, 4, 5];
{
    let result = match IntoIterator::into_iter(values) {
        mut iter => loop {
            let next;
            match iter.next() {
                Some(val) => next = val,
                None => break,
            };
            let x = next;
            let () = { println!("{}", x); };
        },
    };
    result
}
```

これと同値らしいです。なので、`for x in values`すると`values`はmoveされてしまいます。

```rust
for x in values {
    println!("{}", x);
}
let y = values; // move error
```

初心者がよくつまづくところですね。これを回避するには、

```rust
for x in &values {
    println!("{}", x);
}
let y = values; // valid
```

こうやって、valuesの参照をとってからfor文に入れるんでしたね。何故こうするかは、`into_iter()`が[`IntoIterator`トレイト][intoiterator]で定義されていることがわかれば理解できます。`Vector`がどうやってimplしているか見てみます。

```rust
impl<T> IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>
```

`IntoIterator`が`&Vec`にもimplされています。こっちの`into_iter()`が呼ばれてたんですね。先ほどリファレンスの引用で、「`into_iter()`は`T`を返す」と書きましたが、この`T`が何かの参照ではない保証はどこにもないので理解が適当だと注意する必要があります。
ちなみに、`IntoIterator`はIteratorにもimplされているので、こういうことも可能です。

```rust
for x in values.iter() {
    println!("{}", x);
}
```

# `into_iter()`の変な挙動

ここで、ちょっとした落とし穴について。配列に対して`into_iter()`を呼び出してみます。

```rust
let array = [1, 2, 3];
println!("2 in array: {}", array.into_iter().any(|x| x == 2));
```

コンパイルエラーになりました。

```
error[E0277]: the trait bound `&{integer}: std::cmp::PartialEq<{integer}>` is not satisfied
  --> examples/1.rs:10:61
   |
10 |     println!("2 in array2: {}", array.into_iter().any(|x| x == 2));
   |                                                             ^^ can't compare `&{integer}` with `{integer}`
   |
   = help: the trait `std::cmp::PartialEq<{integer}>` is not implemented for `&{integer}`
```

お？
参照が返ってきてます。まさか・・？

```rust
let array = [1, 2, 3];
println!("2 in array: {}", array.into_iter().any(|&x| x == 2));
```

`|&x|`にしたら通りました。`into_iter()`を読んだのに`&T`が返ってきています。これはどういうことでしょうか。
[`Array`のリファレンス][array_reference]を見てみましょう。

> Arrays of sizes from 0 to 32 (inclusive) implement the following traits if the element type allows it:
> 
> * ...
> * IntoIterator (implemented for &[T; N] and &mut [T; N])
> * ...

`[T; N]`そのものは`IntoIterator`をimplしてしませんが、`&[T; N]`はしていると書いてありますね。これでわかりました。`array.into_iter()`の例では`into_iter()`が定義されていないため、自動で`&array.into_iter()`を呼んでくれていたんですね！わかりづらい

ちなみに、for文ではこれは起こらないのでコンパイルは通りません。

```rust
for i in array {} // compile error
```

以上、ちょっとした落とし穴でした。

## 実装はされるか?

配列に`IntoIterator`をimplしようという話は[昔から][array_into_issue]ありますが、まだ技術的に難しいようです。

* [`impl Trait`][impl_trait]がstableになるか、
* [`const generics`][const_generics]が実装される必要があるとか。

[iter_reference]: https://doc.rust-lang.org/std/iter/#the-three-forms-of-iteration
[intoiterator]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html
[rust_by_example]: https://rustbyexample.com/fn/closures/closure_examples/iter_find.html
[array_reference]: https://doc.rust-lang.org/std/primitive.array.html 
[array_into_issue]: https://github.com/rust-lang/rust/issues/25725 
[impl_trait]: https://github.com/rust-lang/rust/issues/34511
[const_generics]: https://github.com/rust-lang/rust/issues/44580