]> git.lizzy.rs Git - rust.git/blobdiff - library/core/tests/ptr.rs
Auto merge of #99814 - aliemjay:patch-2, r=jackh726
[rust.git] / library / core / tests / ptr.rs
index 186e83d50b6cae2dd950d5ecfee7c5c7049578a0..90bc83510803f2185d4f8a3ec83e19343cc5eda8 100644 (file)
@@ -510,49 +510,53 @@ fn align_offset_various_strides_const() {
         assert!(got == expected);
     }
 
-    // For pointers of stride != 1, we verify the algorithm against the naivest possible
-    // implementation
-    let mut align = 1;
-    let limit = 1024;
-    while align < limit {
-        for ptr in 1usize..4 * align {
-            unsafe {
-                #[repr(packed)]
-                struct A3(u16, u8);
-                test_stride::<A3>(ptr::invalid::<A3>(ptr), ptr, align);
-
-                struct A4(u32);
-                test_stride::<A4>(ptr::invalid::<A4>(ptr), ptr, align);
-
-                #[repr(packed)]
-                struct A5(u32, u8);
-                test_stride::<A5>(ptr::invalid::<A5>(ptr), ptr, align);
-
-                #[repr(packed)]
-                struct A6(u32, u16);
-                test_stride::<A6>(ptr::invalid::<A6>(ptr), ptr, align);
-
-                #[repr(packed)]
-                struct A7(u32, u16, u8);
-                test_stride::<A7>(ptr::invalid::<A7>(ptr), ptr, align);
-
-                #[repr(packed)]
-                struct A8(u32, u32);
-                test_stride::<A8>(ptr::invalid::<A8>(ptr), ptr, align);
-
-                #[repr(packed)]
-                struct A9(u32, u32, u8);
-                test_stride::<A9>(ptr::invalid::<A9>(ptr), ptr, align);
-
-                #[repr(packed)]
-                struct A10(u32, u32, u16);
-                test_stride::<A10>(ptr::invalid::<A10>(ptr), ptr, align);
-
-                test_stride::<u32>(ptr::invalid::<u32>(ptr), ptr, align);
-                test_stride::<u128>(ptr::invalid::<u128>(ptr), ptr, align);
+    const {
+        // For pointers of stride != 1, we verify the algorithm against the naivest possible
+        // implementation
+        let mut align = 1;
+        let limit = 32;
+        while align < limit {
+            let mut ptr = 1;
+            while ptr < 4 * align {
+                unsafe {
+                    #[repr(packed)]
+                    struct A3(u16, u8);
+                    test_stride::<A3>(ptr::invalid::<A3>(ptr), ptr, align);
+
+                    struct A4(u32);
+                    test_stride::<A4>(ptr::invalid::<A4>(ptr), ptr, align);
+
+                    #[repr(packed)]
+                    struct A5(u32, u8);
+                    test_stride::<A5>(ptr::invalid::<A5>(ptr), ptr, align);
+
+                    #[repr(packed)]
+                    struct A6(u32, u16);
+                    test_stride::<A6>(ptr::invalid::<A6>(ptr), ptr, align);
+
+                    #[repr(packed)]
+                    struct A7(u32, u16, u8);
+                    test_stride::<A7>(ptr::invalid::<A7>(ptr), ptr, align);
+
+                    #[repr(packed)]
+                    struct A8(u32, u32);
+                    test_stride::<A8>(ptr::invalid::<A8>(ptr), ptr, align);
+
+                    #[repr(packed)]
+                    struct A9(u32, u32, u8);
+                    test_stride::<A9>(ptr::invalid::<A9>(ptr), ptr, align);
+
+                    #[repr(packed)]
+                    struct A10(u32, u32, u16);
+                    test_stride::<A10>(ptr::invalid::<A10>(ptr), ptr, align);
+
+                    test_stride::<u32>(ptr::invalid::<u32>(ptr), ptr, align);
+                    test_stride::<u128>(ptr::invalid::<u128>(ptr), ptr, align);
+                }
+                ptr += 1;
             }
+            align = (align + 1).next_power_of_two();
         }
-        align = (align + 1).next_power_of_two();
     }
 }
 
@@ -560,9 +564,15 @@ fn align_offset_various_strides_const() {
 #[cfg(not(bootstrap))]
 fn align_offset_with_provenance_const() {
     const {
-        let data = 42;
+        // On some platforms (e.g. msp430-none-elf), the alignment of `i32` is less than 4.
+        #[repr(align(4))]
+        struct AlignedI32(i32);
 
-        let ptr: *const i32 = &data;
+        let data = AlignedI32(42);
+
+        // `stride % align == 0` (usual case)
+
+        let ptr: *const i32 = &data.0;
         assert!(ptr.align_offset(1) == 0);
         assert!(ptr.align_offset(2) == 0);
         assert!(ptr.align_offset(4) == 0);
@@ -617,6 +627,44 @@ fn align_offset_with_provenance_const() {
         assert!(ptr3.align_offset(8) == usize::MAX);
         assert!(ptr3.wrapping_byte_add(1).align_offset(1) == 0);
         assert!(ptr3.wrapping_byte_add(1).align_offset(2) == usize::MAX);
+
+        // `stride % align != 0` (edge case)
+
+        let ptr4: *const [u8; 3] = ptr.cast();
+        assert!(ptr4.align_offset(1) == 0);
+        assert!(ptr4.align_offset(2) == 0);
+        assert!(ptr4.align_offset(4) == 0);
+        assert!(ptr4.align_offset(8) == usize::MAX);
+        assert!(ptr4.wrapping_byte_add(1).align_offset(1) == 0);
+        assert!(ptr4.wrapping_byte_add(1).align_offset(2) == 1);
+        assert!(ptr4.wrapping_byte_add(1).align_offset(4) == 1);
+        assert!(ptr4.wrapping_byte_add(1).align_offset(8) == usize::MAX);
+        assert!(ptr4.wrapping_byte_add(2).align_offset(1) == 0);
+        assert!(ptr4.wrapping_byte_add(2).align_offset(2) == 0);
+        assert!(ptr4.wrapping_byte_add(2).align_offset(4) == 2);
+        assert!(ptr4.wrapping_byte_add(2).align_offset(8) == usize::MAX);
+        assert!(ptr4.wrapping_byte_add(3).align_offset(1) == 0);
+        assert!(ptr4.wrapping_byte_add(3).align_offset(2) == 1);
+        assert!(ptr4.wrapping_byte_add(3).align_offset(4) == 3);
+        assert!(ptr4.wrapping_byte_add(3).align_offset(8) == usize::MAX);
+
+        let ptr5: *const [u8; 5] = ptr.cast();
+        assert!(ptr5.align_offset(1) == 0);
+        assert!(ptr5.align_offset(2) == 0);
+        assert!(ptr5.align_offset(4) == 0);
+        assert!(ptr5.align_offset(8) == usize::MAX);
+        assert!(ptr5.wrapping_byte_add(1).align_offset(1) == 0);
+        assert!(ptr5.wrapping_byte_add(1).align_offset(2) == 1);
+        assert!(ptr5.wrapping_byte_add(1).align_offset(4) == 3);
+        assert!(ptr5.wrapping_byte_add(1).align_offset(8) == usize::MAX);
+        assert!(ptr5.wrapping_byte_add(2).align_offset(1) == 0);
+        assert!(ptr5.wrapping_byte_add(2).align_offset(2) == 0);
+        assert!(ptr5.wrapping_byte_add(2).align_offset(4) == 2);
+        assert!(ptr5.wrapping_byte_add(2).align_offset(8) == usize::MAX);
+        assert!(ptr5.wrapping_byte_add(3).align_offset(1) == 0);
+        assert!(ptr5.wrapping_byte_add(3).align_offset(2) == 1);
+        assert!(ptr5.wrapping_byte_add(3).align_offset(4) == 1);
+        assert!(ptr5.wrapping_byte_add(3).align_offset(8) == usize::MAX);
     }
 }
 
@@ -629,7 +677,73 @@ fn align_offset_issue_103361() {
     #[cfg(target_pointer_width = "16")]
     const SIZE: usize = 1 << 13;
     struct HugeSize([u8; SIZE - 1]);
-    let _ = (SIZE as *const HugeSize).align_offset(SIZE);
+    let _ = ptr::invalid::<HugeSize>(SIZE).align_offset(SIZE);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn align_offset_issue_103361_const() {
+    #[cfg(target_pointer_width = "64")]
+    const SIZE: usize = 1 << 47;
+    #[cfg(target_pointer_width = "32")]
+    const SIZE: usize = 1 << 30;
+    #[cfg(target_pointer_width = "16")]
+    const SIZE: usize = 1 << 13;
+    struct HugeSize([u8; SIZE - 1]);
+
+    const {
+        assert!(ptr::invalid::<HugeSize>(SIZE - 1).align_offset(SIZE) == SIZE - 1);
+        assert!(ptr::invalid::<HugeSize>(SIZE).align_offset(SIZE) == 0);
+        assert!(ptr::invalid::<HugeSize>(SIZE + 1).align_offset(SIZE) == 1);
+    }
+}
+
+#[test]
+fn is_aligned() {
+    let data = 42;
+    let ptr: *const i32 = &data;
+    assert!(ptr.is_aligned());
+    assert!(ptr.is_aligned_to(1));
+    assert!(ptr.is_aligned_to(2));
+    assert!(ptr.is_aligned_to(4));
+    assert!(ptr.wrapping_byte_add(2).is_aligned_to(1));
+    assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
+    assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
+
+    // At runtime either `ptr` or `ptr+1` is aligned to 8.
+    assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn is_aligned_const() {
+    const {
+        let data = 42;
+        let ptr: *const i32 = &data;
+        assert!(ptr.is_aligned());
+        assert!(ptr.is_aligned_to(1));
+        assert!(ptr.is_aligned_to(2));
+        assert!(ptr.is_aligned_to(4));
+        assert!(ptr.wrapping_byte_add(2).is_aligned_to(1));
+        assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
+        assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
+
+        // At comptime neither `ptr` nor `ptr+1` is aligned to 8.
+        assert!(!ptr.is_aligned_to(8));
+        assert!(!ptr.wrapping_add(1).is_aligned_to(8));
+    }
+}
+
+#[test]
+#[cfg(bootstrap)]
+fn is_aligned_const() {
+    const {
+        let data = 42;
+        let ptr: *const i32 = &data;
+        // The bootstrap compiler always returns false for is_aligned.
+        assert!(!ptr.is_aligned());
+        assert!(!ptr.is_aligned_to(1));
+    }
 }
 
 #[test]