about summary refs log tree commit diff
path: root/src/libcore/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-12-26 19:39:19 +0000
committerbors <bors@rust-lang.org>2018-12-26 19:39:19 +0000
commita7be40c65ae8ace467c9c40b0a22642973e31a13 (patch)
tree997497091f9aaca0489ac21046023138342a7432 /src/libcore/tests
parent79d8a0fcefa5134db2a94739b1d18daa01fc6e9f (diff)
parent315401ddf8857c9431a889ac1307dca856e4fe65 (diff)
downloadrust-a7be40c65ae8ace467c9c40b0a22642973e31a13.tar.gz
rust-a7be40c65ae8ace467c9c40b0a22642973e31a13.zip
Auto merge of #56534 - xfix:copied, r=@SimonSapin
Add unstable Iterator::copied()

Initially suggested at https://github.com/bluss/rust-itertools/pull/289, however the maintainers of itertools suggested this may be better of in a standard library.

The intent of `copied` is to avoid accidentally cloning iterator elements after doing a code refactoring which causes a structure to be no longer `Copy`. This is a relatively common pattern, as it can be seen by calling `rg --pcre2 '[.]map[(][|](?:(\w+)[|] [*]\1|&(\w+)[|] \2)[)]'` on Rust main repository. Additionally, many uses of `cloned` actually want to simply `Copy`, and changing something to be no longer copyable may introduce unnoticeable performance penalty.

Also, this makes sense because the standard library includes `[T].copy_from_slice` to pair with `[T].clone_from_slice`.

This also adds `Option::copied`, because it makes sense to pair it with `Iterator::copied`. I don't think this feature is particularly important, but it makes sense to update `Option` along with `Iterator` for consistency.
Diffstat (limited to 'src/libcore/tests')
-rw-r--r--src/libcore/tests/iter.rs17
-rw-r--r--src/libcore/tests/lib.rs2
-rw-r--r--src/libcore/tests/option.rs21
3 files changed, 40 insertions, 0 deletions
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 2029f3fa131..cf19851c17b 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -1254,6 +1254,23 @@ fn test_rev() {
 }
 
 #[test]
+fn test_copied() {
+    let xs = [2, 4, 6, 8];
+
+    let mut it = xs.iter().copied();
+    assert_eq!(it.len(), 4);
+    assert_eq!(it.next(), Some(2));
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.next(), Some(4));
+    assert_eq!(it.len(), 2);
+    assert_eq!(it.next_back(), Some(8));
+    assert_eq!(it.len(), 1);
+    assert_eq!(it.next_back(), Some(6));
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.next_back(), None);
+}
+
+#[test]
 fn test_cloned() {
     let xs = [2, 4, 6, 8];
 
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 520fd74c7f7..72846daf16a 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -1,5 +1,6 @@
 #![feature(box_syntax)]
 #![feature(cell_update)]
+#![feature(copied)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
 #![feature(dec2flt)]
@@ -9,6 +10,7 @@
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
 #![feature(hashmap_internals)]
+#![feature(iter_copied)]
 #![feature(iter_nth_back)]
 #![feature(iter_unfold)]
 #![feature(pattern)]
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
index 896479c352a..b059b134868 100644
--- a/src/libcore/tests/option.rs
+++ b/src/libcore/tests/option.rs
@@ -238,6 +238,27 @@ fn test_collect() {
     assert!(v == None);
 }
 
+#[test]
+fn test_copied() {
+    let val = 1;
+    let val_ref = &val;
+    let opt_none: Option<&'static u32> = None;
+    let opt_ref = Some(&val);
+    let opt_ref_ref = Some(&val_ref);
+
+    // None works
+    assert_eq!(opt_none.clone(), None);
+    assert_eq!(opt_none.copied(), None);
+
+    // Immutable ref works
+    assert_eq!(opt_ref.clone(), Some(&val));
+    assert_eq!(opt_ref.copied(), Some(1));
+
+    // Double Immutable ref works
+    assert_eq!(opt_ref_ref.clone(), Some(&val_ref));
+    assert_eq!(opt_ref_ref.clone().copied(), Some(&val));
+    assert_eq!(opt_ref_ref.copied().copied(), Some(1));
+}
 
 #[test]
 fn test_cloned() {