From fabd77201abacd200379c67cda44b3a4e743e754 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Tue, 29 Jan 2019 12:40:16 +0100 Subject: [PATCH] Remove TrustedRandomAccess specialization for Cloned For incorrect Clone implementations, this exposes specialization. --- src/libcore/iter/adapters/mod.rs | 18 ++---------------- src/libcore/tests/iter.rs | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index f8d6bedeace25..1b0f471d71013 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -314,27 +314,13 @@ impl<'a, I, T: 'a> FusedIterator for Cloned #[doc(hidden)] unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned where I: TrustedRandomAccess, T: Clone -{ - default unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - self.it.get_unchecked(i).clone() - } - - #[inline] - default fn may_have_side_effect() -> bool { true } -} - -#[doc(hidden)] -unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned - where I: TrustedRandomAccess, T: Copy { unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { - *self.it.get_unchecked(i) + self.it.get_unchecked(i).clone() } #[inline] - fn may_have_side_effect() -> bool { - I::may_have_side_effect() - } + fn may_have_side_effect() -> bool { true } } #[unstable(feature = "trusted_len", issue = "37572")] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 0fa99745d9065..a94bd1af07d17 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1,6 +1,7 @@ use core::cell::Cell; use core::iter::*; use core::{i8, i16, isize}; +use core::sync::atomic::{AtomicUsize, Ordering}; use core::usize; #[test] @@ -1305,6 +1306,24 @@ fn test_cloned_side_effects() { assert_eq!(count, 2); } +#[test] +fn test_cloned_side_effects_with_incorrect_clone_implementation() { + #[derive(Copy)] + struct X; + + static CALL_COUNT: AtomicUsize = AtomicUsize::new(0); + + impl Clone for X { + fn clone(&self) -> X { + CALL_COUNT.store(CALL_COUNT.load(Ordering::Relaxed) + 1, Ordering::Relaxed); + X + } + } + + for _ in [X; 3].iter().cloned().zip(&[1]) {} + assert_eq!(CALL_COUNT.load(Ordering::Relaxed), 2); +} + #[test] fn test_double_ended_map() { let xs = [1, 2, 3, 4, 5, 6];