Is there a way to resolve a branching statement, like an if, to a trait object without boxing, or are there plans to allow this?
My situation is this, I want to conditionally filter an iterator if I have Some(pos), otherwise I want to use the original iterator, then I want to consume the iterator in a while loop:
while let Some((pattern_index, pos_sub)) = if let Some(pos) = pos {
parent.positions.iter().filter(|(_, pos_sub)| *pos_sub == pos)
} else {
parent.positions.iter()
}.next() {
...
}
Here I get the error:
`if` and `else` have incompatible types
expected struct `std::iter::Filter`, found struct `std::collections::hash_set::Iter`
So a solution is to collect the iterator into a vector:
let candidates: Vec<_> = if let Some(pos) = pos {
parent.positions
.iter()
.filter(|(_pattern_index, pos_sub)| *pos_sub == pos)
.collect()
} else {
parent.positions.iter().collect()
};
while let Some((pattern_index, pos_sub)) = candidates.iter().next() {
...
}
or I could box the trait object and access that
let candidates: Box<dyn Iterator<Item=_>> = if let Some(pos) = pos {
Box::new(parent.positions.iter()
.filter(|(_pattern_index, pos_sub)| *pos_sub == pos))
} else {
Box::new(parent.positions.iter())
};
while let Some((pattern_index, pos_sub)) = candidates.next() {
...
}
But it seems like the compiler could figure that out by itself and permit the if statement to return different types, as long as the result only uses trait items common to both results.