auto merge of #15256 : erickt/rust/optimizations, r=alexcrichton
The bug #11084 causes `option::collect` and `result::collect` about twice as slower as it should because llvm is having some trouble optimizing away the scan closure. This gets rid of it so now those functions perform equivalent to a hand written version. This also adds an impl of `Default` for `Rc` along the way.
This commit is contained in:
commit
e25eb6b223
|
@ -27,6 +27,7 @@ use core::mem::transmute;
|
|||
use core::cell::Cell;
|
||||
use core::clone::Clone;
|
||||
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
|
||||
use core::default::Default;
|
||||
use core::kinds::marker;
|
||||
use core::ops::{Deref, Drop};
|
||||
use core::option::{Option, Some, None};
|
||||
|
@ -152,6 +153,13 @@ impl<T> Clone for Rc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Default for Rc<T> {
|
||||
#[inline]
|
||||
fn default() -> Rc<T> {
|
||||
Rc::new(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for Rc<T> {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
|
||||
|
|
|
@ -265,8 +265,6 @@ pub fn hash_with_keys<T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
|
|||
state.result()
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use test::Bencher;
|
||||
|
|
|
@ -587,20 +587,32 @@ impl<A> ExactSize<A> for Item<A> {}
|
|||
/// ```
|
||||
#[inline]
|
||||
pub fn collect<T, Iter: Iterator<Option<T>>, V: FromIterator<T>>(iter: Iter) -> Option<V> {
|
||||
// FIXME(#11084): This should be twice as fast once this bug is closed.
|
||||
let mut iter = iter.scan(false, |state, x| {
|
||||
match x {
|
||||
Some(x) => Some(x),
|
||||
None => {
|
||||
*state = true;
|
||||
// FIXME(#11084): This could be replaced with Iterator::scan when this
|
||||
// performance bug is closed.
|
||||
|
||||
struct Adapter<Iter> {
|
||||
iter: Iter,
|
||||
found_none: bool,
|
||||
}
|
||||
|
||||
impl<T, Iter: Iterator<Option<T>>> Iterator<T> for Adapter<Iter> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<T> {
|
||||
match self.iter.next() {
|
||||
Some(Some(value)) => Some(value),
|
||||
Some(None) => {
|
||||
self.found_none = true;
|
||||
None
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let v: V = FromIterator::from_iter(iter.by_ref());
|
||||
let mut adapter = Adapter { iter: iter, found_none: false };
|
||||
let v: V = FromIterator::from_iter(adapter.by_ref());
|
||||
|
||||
if iter.state {
|
||||
if adapter.found_none {
|
||||
None
|
||||
} else {
|
||||
Some(v)
|
||||
|
|
|
@ -585,20 +585,32 @@ impl<T: Show, E> Result<T, E> {
|
|||
/// ```
|
||||
#[inline]
|
||||
pub fn collect<T, E, Iter: Iterator<Result<T, E>>, V: FromIterator<T>>(iter: Iter) -> Result<V, E> {
|
||||
// FIXME(#11084): This should be twice as fast once this bug is closed.
|
||||
let mut iter = iter.scan(None, |state, x| {
|
||||
match x {
|
||||
Ok(x) => Some(x),
|
||||
Err(err) => {
|
||||
*state = Some(err);
|
||||
// FIXME(#11084): This could be replaced with Iterator::scan when this
|
||||
// performance bug is closed.
|
||||
|
||||
struct Adapter<Iter, E> {
|
||||
iter: Iter,
|
||||
err: Option<E>,
|
||||
}
|
||||
|
||||
impl<T, E, Iter: Iterator<Result<T, E>>> Iterator<T> for Adapter<Iter, E> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<T> {
|
||||
match self.iter.next() {
|
||||
Some(Ok(value)) => Some(value),
|
||||
Some(Err(err)) => {
|
||||
self.err = Some(err);
|
||||
None
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let v: V = FromIterator::from_iter(iter.by_ref());
|
||||
let mut adapter = Adapter { iter: iter, err: None };
|
||||
let v: V = FromIterator::from_iter(adapter.by_ref());
|
||||
|
||||
match iter.state {
|
||||
match adapter.err {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(v),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue