Why does this code compile:
pub fn main() {
let my_vec = vec!["b", "c", "d"];
let res = ["a"].iter()
.chain(my_vec.iter().map(|s| s))
.collect::<Vec<_>>();
println!("{:?}", res)
}
And this doesn't:
pub fn main() {
let my_vec = vec![(1, "b"), (2, "c"), (3, "d")];
let res = ["a"].iter()
.chain(my_vec.iter().map(|s| s.1))
.collect::<Vec<_>>();
println!("{:?}", res)
}
Is there a way to make it compile?
Background
I am trying to refactor my code that was constructing a vector by appending elements to it. It looked something like this:
pub fn main() {
let my_vec = vec![(1, "b"), (2, "c"), (3, "d")];
let mut res = Vec::new();
res.push("a");
for (_, s) in &my_vec {
res.push(s);
}
println!("{:?}", res)
}
I changed it into something that will collect this vector from a chain of iterators without modifying a mutable instance in place:
pub fn main() {
let my_vec = vec![(1, "b"), (2, "c"), (3, "d")];
let res = ["a"].iter()
.chain(my_vec.iter().map(|s| s.1))
.collect::<Vec<_>>();
println!("{:?}", res)
}
The construction I came up with doesn't compile:
error[E0271]: type mismatch resolving `<[closure@iter.rs:5:34: 5:41] as std::ops::FnOnce<(&({integer}, &str),)>>::Output == &&str`
--> iter.rs:5:10
|
5 | .chain(my_vec.iter().map(|s| s.1))
| ^^^^^ expected `str`, found `&str`
|
= note: expected reference `&str`
found reference `&&str`
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<std::slice::Iter<'_, ({integer}, &str)>, [closure@iter.rs:5:34: 5:41]>`
error[E0599]: no method named `collect` found for struct `std::iter::Chain<std::slice::Iter<'_, &str>, std::iter::Map<std::slice::Iter<'_, ({integer}, &str)>, [closure@iter.rs:5:34: 5:41]>>` in the current scope
--> iter.rs:6:10
|
6 | .collect::<Vec<_>>();
| ^^^^^^^ method not found in `std::iter::Chain<std::slice::Iter<'_, &str>, std::iter::Map<std::slice::Iter<'_, ({integer}, &str)>, [closure@iter.rs:5:34: 5:41]>>`
|
= note: the method `collect` exists but the following trait bounds were not satisfied:
`<std::iter::Map<std::slice::Iter<'_, ({integer}, &str)>, [closure@iter.rs:5:34: 5:41]> as std::iter::Iterator>::Item = &&str`
which is required by `std::iter::Chain<std::slice::Iter<'_, &str>, std::iter::Map<std::slice::Iter<'_, ({integer}, &str)>, [closure@iter.rs:5:34: 5:41]>>: std::iter::Iterator`
`std::iter::Chain<std::slice::Iter<'_, &str>, std::iter::Map<std::slice::Iter<'_, ({integer}, &str)>, [closure@iter.rs:5:34: 5:41]>>: std::iter::Iterator`
which is required by `&mut std::iter::Chain<std::slice::Iter<'_, &str>, std::iter::Map<std::slice::Iter<'_, ({integer}, &str)>, [closure@iter.rs:5:34: 5:41]>>: std::iter::Iterator`
I tried adding and removing &
signs here and there but nothing helped. I also tried a simpler variant:
pub fn main() {
let my_vec = vec!["b", "c", "d"];
let res = ["a"].iter()
.chain(my_vec.iter().map(|s| s))
.collect::<Vec<_>>();
println!("{:?}", res)
}
This doesn't seem fundamentally different to me, but the compiler doesn't have a problem with it.
In my original problem, the result isn't a Vec<&str>
but a Vec<&T>
where T
is some other struct, but I simplified the example, and the error messages are pretty much identical.