|
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