Reputation: 379
I am running into the error when calling .partition()
on a vector iterator:
error[E0277]: the trait bound `std::vec::Vec<std::result::Result<std::collections::HashSet<&std::string::String>, std::boxed::Box<dyn std::error::Error>>>: std::iter::Extend<&std::result::Result<std::collections::HashSet<std::string::String>, std::boxed::Box<dyn std::error::Error>>>` is not satisfied
--> src/main.rs:9:24
|
9 | results.iter().partition(|r| r.is_ok());
| ^^^^^^^^^ the trait `std::iter::Extend<&std::result::Result<std::collections::HashSet<std::string::String>, std::boxed::Box<dyn std::error::Error>>>` is not implemented for `std::vec::Vec<std::result::Result<std::collections::HashSet<&std::string::String>, std::boxed::Box<dyn std::error::Error>>>`
|
= help: the following implementations were found:
<std::vec::Vec<T> as std::iter::Extend<&'a T>>
<std::vec::Vec<T> as std::iter::Extend<T>>
When running the following code:
use std::collections::HashSet;
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
fn main() {
let mut results: Vec<Result<HashSet<String>>> = Default::default();
let (okays, errors): (Vec<Result<HashSet<&String>>>, Vec<_>) =
results.iter().partition(|r| r.is_ok());
}
See playground for example.
Upvotes: 0
Views: 3913
Reputation: 431619
As the error message states (with namespacing removed):
the trait
Extend<&Result<HashSet<String>, Box<dyn Error>>>
is not implemented forVec<Result<HashSet<&String>, Box<dyn Error>>>
You can't extend a Vec<T>
with elements of type &T
because they aren't the same type.
Instead, you can do one of these:
Change the type of the destination collection to Vec<&Result<HashSet<String>>>
(or just Vec<_>
, like your second destination type, to allow the compiler to infer the inner type).
Convert the reference to an owned value, perhaps via clone
or to_owned
.
Don't iterate over references to start with, using into_iter
or drain
instead.
However, your current type will be very hard or expensive to achieve, as you state that you want an owned Result
with an owned HashMap
but a reference the String
.
I think the best thing is to use Itertools::partition_map
and into_iter
:
use itertools::Itertools; // 0.9.0
use std::collections::HashSet;
type Error = Box<dyn std::error::Error>;
type Result<T, E = Error> = std::result::Result<T, E>;
fn main() {
let mut results: Vec<Result<HashSet<String>>> = Default::default();
let (errors, okays): (Vec<_>, Vec<_>) = results.into_iter().partition_map(Into::into);
// let (errors, okays): (Vec<Error>, Vec<HashSet<String>>)
}
See also:
Upvotes: 1