So I still want this. Here’s the reason:
I have code that is generic between String and Cow<str> for the purpose of benchmarking the performance difference between them. I can run this code with each Rust version to see if either one had a performance regression (and in fact, there was one on Windows when Rust on Windows switched allocators).
The code in question looks like this:
//does the monoid operation on the slice of tuples if the closure evaluates to true
fn accumulate<'a, T: Monoid>(tuples: &[(&'a str, &Fn(i32) -> bool)], i: i32) -> T
where T: From<&'a str> + From<String> {
tuples.iter()
.filter(apply(second, i))
.map(first)
.cloned()
.map(<&str>::into)
.fold1(T::op)
.unwrap_or_else(|| i.to_string().into())
//op just concatenates, but String does not satisfy Add
}
See, I had to actually make my own Monoid trait in order to call .fold1() with T::op
Another idea was to do this:
trait MaybeCollect: Iterator {
fn maybe_collect<B>(self) -> Option<B> where B: FromIterator<Self::Item>;
}
impl<T> MaybeCollect for T where T: Iterator {
fn maybe_collect<B>(self) -> Option<B> where B: FromIterator<Self::Item> {
let mut iter = self.peekable();
if iter.peek().is_none() {
None
} else {
Some(iter.collect())
}
}
}
this works for String BUT my code is generic over String and Cow<str>
using .collect() on Cow<str> leads to allocations in the case where Cow<str> would just return a reference! Which means the performance benefits of using that type are eliminated.
I have to jump through extra hoops (making a new trait and having to use it to concatenate Strings) just because Add is not implemented on String already