about summary refs log tree commit diff
path: root/src/libcore/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-08-02 00:14:21 +0000
committerbors <bors@rust-lang.org>2018-08-02 00:14:21 +0000
commit1d9405fb6caa5eac18e5a28685e4f30dcbde6d45 (patch)
treece4c50b240bfafc9cfe665e533aed28fb8c0c7b8 /src/libcore/tests
parent97085f9fb0736b322dc216db3655da780b4d8041 (diff)
parent9fcf2c972663ab510417ba1df058f99f0b0d0abe (diff)
downloadrust-1d9405fb6caa5eac18e5a28685e4f30dcbde6d45.tar.gz
rust-1d9405fb6caa5eac18e5a28685e4f30dcbde6d45.zip
Auto merge of #52206 - RalfJung:zst-slices, r=alexcrichton
slices: fix ZST slice iterators making up pointers; debug_assert alignment in from_raw_parts

This fixes the problem that we are fabricating pointers out of thin air. I also managed to share more code between the mutable and shared iterators, while reducing the amount of macros.

I am not sure how useful it really is to add a `debug_assert!` in libcore. Everybody gets a release version of that anyway, right? Is there at least a CI job that runs the test suite with a debug version?

Fixes #42789
Diffstat (limited to 'src/libcore/tests')
-rw-r--r--src/libcore/tests/slice.rs126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 2b37acdfe3e..7968521f7b4 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -390,6 +390,132 @@ fn test_windows_zip() {
     assert_eq!(res, [14, 18, 22, 26]);
 }
 
+#[test]
+#[allow(const_err)]
+fn test_iter_ref_consistency() {
+    use std::fmt::Debug;
+
+    fn test<T : Copy + Debug + PartialEq>(x : T) {
+        let v : &[T] = &[x, x, x];
+        let v_ptrs : [*const T; 3] = match v {
+            [ref v1, ref v2, ref v3] => [v1 as *const _, v2 as *const _, v3 as *const _],
+            _ => unreachable!()
+        };
+        let len = v.len();
+
+        // nth(i)
+        for i in 0..len {
+            assert_eq!(&v[i] as *const _, v_ptrs[i]); // check the v_ptrs array, just to be sure
+            let nth = v.iter().nth(i).unwrap();
+            assert_eq!(nth as *const _, v_ptrs[i]);
+        }
+        assert_eq!(v.iter().nth(len), None, "nth(len) should return None");
+
+        // stepping through with nth(0)
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let next = it.nth(0).unwrap();
+                assert_eq!(next as *const _, v_ptrs[i]);
+            }
+            assert_eq!(it.nth(0), None);
+        }
+
+        // next()
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let next = it.next().unwrap();
+                assert_eq!(next as *const _, v_ptrs[i]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next(), None, "The final call to next() should return None");
+        }
+
+        // next_back()
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let prev = it.next_back().unwrap();
+                assert_eq!(prev as *const _, v_ptrs[remaining-1]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next_back(), None, "The final call to next_back() should return None");
+        }
+    }
+
+    fn test_mut<T : Copy + Debug + PartialEq>(x : T) {
+        let v : &mut [T] = &mut [x, x, x];
+        let v_ptrs : [*mut T; 3] = match v {
+            [ref v1, ref v2, ref v3] =>
+              [v1 as *const _ as *mut _, v2 as *const _ as *mut _, v3 as *const _ as *mut _],
+            _ => unreachable!()
+        };
+        let len = v.len();
+
+        // nth(i)
+        for i in 0..len {
+            assert_eq!(&mut v[i] as *mut _, v_ptrs[i]); // check the v_ptrs array, just to be sure
+            let nth = v.iter_mut().nth(i).unwrap();
+            assert_eq!(nth as *mut _, v_ptrs[i]);
+        }
+        assert_eq!(v.iter().nth(len), None, "nth(len) should return None");
+
+        // stepping through with nth(0)
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let next = it.nth(0).unwrap();
+                assert_eq!(next as *const _, v_ptrs[i]);
+            }
+            assert_eq!(it.nth(0), None);
+        }
+
+        // next()
+        {
+            let mut it = v.iter_mut();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let next = it.next().unwrap();
+                assert_eq!(next as *mut _, v_ptrs[i]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next(), None, "The final call to next() should return None");
+        }
+
+        // next_back()
+        {
+            let mut it = v.iter_mut();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let prev = it.next_back().unwrap();
+                assert_eq!(prev as *mut _, v_ptrs[remaining-1]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next_back(), None, "The final call to next_back() should return None");
+        }
+    }
+
+    // Make sure iterators and slice patterns yield consistent addresses for various types,
+    // including ZSTs.
+    test(0u32);
+    test(());
+    test([0u32; 0]); // ZST with alignment > 0
+    test_mut(0u32);
+    test_mut(());
+    test_mut([0u32; 0]); // ZST with alignment > 0
+}
+
 // The current implementation of SliceIndex fails to handle methods
 // orthogonally from range types; therefore, it is worth testing
 // all of the indexing operations on each input.