Description
Consider this snippet:
#[derive(Debug)]
struct SomeStuff {}
fn main() {
let vec: Vec<SomeStuff> = vec![SomeStuff {}];
vec.extend([
SomeStuff {},
SomeStuff {},
].into_iter());
}
This fails because array.into_iter()
collapses to (&array).into_iter()
, which provides a slice iterator that emits references, but Vec::extend
wants values. This gives the following error:
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, SomeStuff> as std::iter::IntoIterator>::Item == SomeStuff`
--> src/main.rs:7:9
|
7 | vec.extend([
| ^^^^^^ expected reference, found struct `SomeStuff`
|
= note: expected reference `&SomeStuff`
found struct `SomeStuff`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0271`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
This error, read naturally, seems to indicate that we have values but are expecting references. This confused a team member of mine today who didn't realize that arrays aren't iterable by-move. To quote:
It seems to want a reference to the items but I can’t see why?
...
Why would extend want a reference to the item? The vec needs ownership of the item at the end of the extend call.
From that perspective, the intuition is that the vec wants values, the array iterator is providing values, so why is the error message reporting that something is expecting a reference?
Additionally, while not strictly speaking part of the diagnostic, the first example in the docs (which is shown inline by rust-analyzer) looks like this:
This seems to show a slice being used without issue to extend something without explict copying or cloning. The disconnect is that String: Extend<&char>
, but in this particular case it seemed to reinforce the idea that slices may be used to extend something by-move.
Meta
This issue was originally reported in rust 1.46.0:
rustc 1.46.0 (04488afe3 2020-08-24)
binary: rustc
commit-hash: 04488afe34512aa4c33566eb16d8c912a3ae04f9
commit-date: 2020-08-24
host: x86_64-apple-darwin
release: 1.46.0
LLVM version: 10.0
However, I've also reproduced it in current stable:
rustc 1.47.0 (18bf6b4f0 2020-10-07)
binary: rustc
commit-hash: 18bf6b4f01a6feaf7259ba7cdae58031af1b7b39
commit-date: 2020-10-07
host: x86_64-apple-darwin
release: 1.47.0
LLVM version: 11.0
and current nightly:
rustc 1.49.0-nightly (31530e5d1 2020-10-20)
binary: rustc
commit-hash: 31530e5d132ebcc3654baf2e5460599681520af0
commit-date: 2020-10-20
host: x86_64-apple-darwin
release: 1.49.0-nightly
LLVM version: 11.0