Skip to content

Commit e25eb6b

Browse files
committed
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.
2 parents 9ae4828 + ab1bd3a commit e25eb6b

File tree

4 files changed

+52
-22
lines changed

4 files changed

+52
-22
lines changed

src/liballoc/rc.rs

+8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use core::mem::transmute;
2727
use core::cell::Cell;
2828
use core::clone::Clone;
2929
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
30+
use core::default::Default;
3031
use core::kinds::marker;
3132
use core::ops::{Deref, Drop};
3233
use core::option::{Option, Some, None};
@@ -152,6 +153,13 @@ impl<T> Clone for Rc<T> {
152153
}
153154
}
154155

156+
impl<T: Default> Default for Rc<T> {
157+
#[inline]
158+
fn default() -> Rc<T> {
159+
Rc::new(Default::default())
160+
}
161+
}
162+
155163
impl<T: PartialEq> PartialEq for Rc<T> {
156164
#[inline(always)]
157165
fn eq(&self, other: &Rc<T>) -> bool { **self == **other }

src/libcollections/hash/sip.rs

-2
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,6 @@ pub fn hash_with_keys<T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
265265
state.result()
266266
}
267267

268-
269-
270268
#[cfg(test)]
271269
mod tests {
272270
use test::Bencher;

src/libcore/option.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -587,20 +587,32 @@ impl<A> ExactSize<A> for Item<A> {}
587587
/// ```
588588
#[inline]
589589
pub fn collect<T, Iter: Iterator<Option<T>>, V: FromIterator<T>>(iter: Iter) -> Option<V> {
590-
// FIXME(#11084): This should be twice as fast once this bug is closed.
591-
let mut iter = iter.scan(false, |state, x| {
592-
match x {
593-
Some(x) => Some(x),
594-
None => {
595-
*state = true;
596-
None
590+
// FIXME(#11084): This could be replaced with Iterator::scan when this
591+
// performance bug is closed.
592+
593+
struct Adapter<Iter> {
594+
iter: Iter,
595+
found_none: bool,
596+
}
597+
598+
impl<T, Iter: Iterator<Option<T>>> Iterator<T> for Adapter<Iter> {
599+
#[inline]
600+
fn next(&mut self) -> Option<T> {
601+
match self.iter.next() {
602+
Some(Some(value)) => Some(value),
603+
Some(None) => {
604+
self.found_none = true;
605+
None
606+
}
607+
None => None,
597608
}
598609
}
599-
});
610+
}
600611

601-
let v: V = FromIterator::from_iter(iter.by_ref());
612+
let mut adapter = Adapter { iter: iter, found_none: false };
613+
let v: V = FromIterator::from_iter(adapter.by_ref());
602614

603-
if iter.state {
615+
if adapter.found_none {
604616
None
605617
} else {
606618
Some(v)

src/libcore/result.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -585,20 +585,32 @@ impl<T: Show, E> Result<T, E> {
585585
/// ```
586586
#[inline]
587587
pub fn collect<T, E, Iter: Iterator<Result<T, E>>, V: FromIterator<T>>(iter: Iter) -> Result<V, E> {
588-
// FIXME(#11084): This should be twice as fast once this bug is closed.
589-
let mut iter = iter.scan(None, |state, x| {
590-
match x {
591-
Ok(x) => Some(x),
592-
Err(err) => {
593-
*state = Some(err);
594-
None
588+
// FIXME(#11084): This could be replaced with Iterator::scan when this
589+
// performance bug is closed.
590+
591+
struct Adapter<Iter, E> {
592+
iter: Iter,
593+
err: Option<E>,
594+
}
595+
596+
impl<T, E, Iter: Iterator<Result<T, E>>> Iterator<T> for Adapter<Iter, E> {
597+
#[inline]
598+
fn next(&mut self) -> Option<T> {
599+
match self.iter.next() {
600+
Some(Ok(value)) => Some(value),
601+
Some(Err(err)) => {
602+
self.err = Some(err);
603+
None
604+
}
605+
None => None,
595606
}
596607
}
597-
});
608+
}
598609

599-
let v: V = FromIterator::from_iter(iter.by_ref());
610+
let mut adapter = Adapter { iter: iter, err: None };
611+
let v: V = FromIterator::from_iter(adapter.by_ref());
600612

601-
match iter.state {
613+
match adapter.err {
602614
Some(err) => Err(err),
603615
None => Ok(v),
604616
}

0 commit comments

Comments
 (0)