|
1 | 1 | use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
|
2 | 2 | use crate::num::NonZeroUsize;
|
3 |
| -use crate::mem; |
| 3 | +use crate::{mem, ptr}; |
4 | 4 | use crate::ops::Try;
|
5 | 5 |
|
6 | 6 | /// An iterator that links two iterators together, in a chain.
|
@@ -365,35 +365,55 @@ where
|
365 | 365 |
|
366 | 366 | impl<A, B> SpecChain for Chain<A, B>
|
367 | 367 | where
|
368 |
| - A: Iterator, |
369 |
| - B: Iterator<Item = A::Item>, |
| 368 | + A: Iterator + FusedIterator, |
| 369 | + B: Iterator<Item = A::Item> + FusedIterator, |
370 | 370 | Self: SymmetricalModuloLifetimes,
|
371 | 371 | {
|
372 | 372 | #[inline]
|
373 | 373 | fn next(&mut self) -> Option<A::Item> {
|
374 |
| - let mut result = and_then_or_clear(&mut self.a, Iterator::next); |
| 374 | + let mut result = self.a.as_mut().and_then( Iterator::next); |
375 | 375 | if result.is_none() {
|
376 |
| - // SAFETY: SymmetricalModuloLifetimes guarantees that A and B are safe to swap |
377 |
| - unsafe { mem::swap(&mut self.a, &mut *(&mut self.b as *mut _ as *mut Option<A>)) }; |
378 |
| - result = and_then_or_clear(&mut self.a, Iterator::next); |
| 376 | + if mem::needs_drop::<A>() { |
| 377 | + // swap iters to avoid running drop code inside the loop. |
| 378 | + // SAFETY: SymmetricalModuloLifetimes guarantees that A and B are safe to swap. |
| 379 | + unsafe { mem::swap(&mut self.a, &mut *(&mut self.b as *mut _ as *mut Option<A>)) }; |
| 380 | + } else { |
| 381 | + // SAFETY: SymmetricalModuloLifetimes guarantees that A and B are safe to swap. |
| 382 | + // And they dont need drop, so we can overwrite the values directly. |
| 383 | + unsafe { |
| 384 | + ptr::write(&mut self.a, ptr::from_ref(&self.b).cast::<Option<A>>().read()); |
| 385 | + ptr::write(&mut self.b, None); |
| 386 | + } |
| 387 | + } |
| 388 | + result = self.a.as_mut().and_then(Iterator::next); |
379 | 389 | }
|
380 | 390 | result
|
381 | 391 | }
|
382 | 392 | }
|
383 | 393 |
|
384 | 394 | impl<A, B> SpecChainBack for Chain<A, B>
|
385 | 395 | where
|
386 |
| - A: DoubleEndedIterator, |
387 |
| - B: DoubleEndedIterator<Item = A::Item>, |
| 396 | + A: DoubleEndedIterator + FusedIterator, |
| 397 | + B: DoubleEndedIterator<Item = A::Item> + FusedIterator, |
388 | 398 | Self: SymmetricalModuloLifetimes,
|
389 | 399 | {
|
390 | 400 | #[inline]
|
391 | 401 | fn next_back(&mut self) -> Option<Self::Item> {
|
392 |
| - let mut result = and_then_or_clear(&mut self.b, DoubleEndedIterator::next_back); |
| 402 | + let mut result = self.b.as_mut().and_then( DoubleEndedIterator::next_back); |
393 | 403 | if result.is_none() {
|
394 |
| - // SAFETY: SymmetricalModuloLifetimes guarantees that A and B are safe to swap |
395 |
| - unsafe { mem::swap(&mut self.a, &mut *(&mut self.b as *mut _ as *mut Option<A>)) }; |
396 |
| - result = and_then_or_clear(&mut self.b, DoubleEndedIterator::next_back); |
| 404 | + if mem::needs_drop::<A>() { |
| 405 | + // swap iters to avoid running drop code inside the loop. |
| 406 | + // SAFETY: SymmetricalModuloLifetimes guarantees that A and B are safe to swap. |
| 407 | + unsafe { mem::swap(&mut self.a, &mut *(&mut self.b as *mut _ as *mut Option<A>)) }; |
| 408 | + } else { |
| 409 | + // SAFETY: SymmetricalModuloLifetimes guarantees that A and B are safe to swap. |
| 410 | + // And they dont need drop, so we can overwrite the values directly. |
| 411 | + unsafe { |
| 412 | + ptr::write(&mut self.b, ptr::from_ref(&self.a).cast::<Option<B>>().read()); |
| 413 | + ptr::write(&mut self.a, None); |
| 414 | + } |
| 415 | + } |
| 416 | + result = self.b.as_mut().and_then(DoubleEndedIterator::next_back); |
397 | 417 | }
|
398 | 418 | result
|
399 | 419 | }
|
|
0 commit comments