diff options
| author | bors <bors@rust-lang.org> | 2014-06-30 03:46:25 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-06-30 03:46:25 +0000 |
| commit | e25eb6b223d86047dc807a167f3dd4bf492bbf41 (patch) | |
| tree | b0c22f04747ee2122e32e8c101e371be5fca01c8 /src/libcore | |
| parent | 9ae48286a99627391e30da3888217e6050230cfe (diff) | |
| parent | ab1bd3adf673ef7a515242a2dcc09ce360d41d9c (diff) | |
| download | rust-e25eb6b223d86047dc807a167f3dd4bf492bbf41.tar.gz rust-e25eb6b223d86047dc807a167f3dd4bf492bbf41.zip | |
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.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/option.rs | 32 | ||||
| -rw-r--r-- | src/libcore/result.rs | 32 |
2 files changed, 44 insertions, 20 deletions
diff --git a/src/libcore/option.rs b/src/libcore/option.rs index c0d04ee0b95..b8612ed93e0 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -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; - None + // 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) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index a104d20f4e5..5cbbf30cd36 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -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); - None + // 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), } |
