]> git.lizzy.rs Git - rust.git/blob - library/core/tests/ptr.rs
update provenance test
[rust.git] / library / core / tests / ptr.rs
1 use core::cell::RefCell;
2 use core::mem::{self, MaybeUninit};
3 use core::num::NonZeroUsize;
4 use core::ptr;
5 use core::ptr::*;
6 use std::fmt::{Debug, Display};
7
8 #[test]
9 fn test_const_from_raw_parts() {
10     const SLICE: &[u8] = &[1, 2, 3, 4];
11     const FROM_RAW: &[u8] = unsafe { &*slice_from_raw_parts(SLICE.as_ptr(), SLICE.len()) };
12     assert_eq!(SLICE, FROM_RAW);
13
14     let slice = &[1, 2, 3, 4, 5];
15     let from_raw = unsafe { &*slice_from_raw_parts(slice.as_ptr(), 2) };
16     assert_eq!(&slice[..2], from_raw);
17 }
18
19 #[test]
20 fn test() {
21     unsafe {
22         #[repr(C)]
23         struct Pair {
24             fst: isize,
25             snd: isize,
26         }
27         let mut p = Pair { fst: 10, snd: 20 };
28         let pptr: *mut Pair = &mut p;
29         let iptr: *mut isize = pptr as *mut isize;
30         assert_eq!(*iptr, 10);
31         *iptr = 30;
32         assert_eq!(*iptr, 30);
33         assert_eq!(p.fst, 30);
34
35         *pptr = Pair { fst: 50, snd: 60 };
36         assert_eq!(*iptr, 50);
37         assert_eq!(p.fst, 50);
38         assert_eq!(p.snd, 60);
39
40         let v0 = vec![32000u16, 32001u16, 32002u16];
41         let mut v1 = vec![0u16, 0u16, 0u16];
42
43         copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
44         assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16));
45         copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
46         assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16));
47         copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
48         assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16));
49     }
50 }
51
52 #[test]
53 fn test_is_null() {
54     let p: *const isize = null();
55     assert!(p.is_null());
56
57     let q = p.wrapping_offset(1);
58     assert!(!q.is_null());
59
60     let mp: *mut isize = null_mut();
61     assert!(mp.is_null());
62
63     let mq = mp.wrapping_offset(1);
64     assert!(!mq.is_null());
65
66     // Pointers to unsized types -- slices
67     let s: &mut [u8] = &mut [1, 2, 3];
68     let cs: *const [u8] = s;
69     assert!(!cs.is_null());
70
71     let ms: *mut [u8] = s;
72     assert!(!ms.is_null());
73
74     let cz: *const [u8] = &[];
75     assert!(!cz.is_null());
76
77     let mz: *mut [u8] = &mut [];
78     assert!(!mz.is_null());
79
80     let ncs: *const [u8] = null::<[u8; 3]>();
81     assert!(ncs.is_null());
82
83     let nms: *mut [u8] = null_mut::<[u8; 3]>();
84     assert!(nms.is_null());
85
86     // Pointers to unsized types -- trait objects
87     let ci: *const dyn ToString = &3;
88     assert!(!ci.is_null());
89
90     let mi: *mut dyn ToString = &mut 3;
91     assert!(!mi.is_null());
92
93     let nci: *const dyn ToString = null::<isize>();
94     assert!(nci.is_null());
95
96     let nmi: *mut dyn ToString = null_mut::<isize>();
97     assert!(nmi.is_null());
98
99     extern "C" {
100         type Extern;
101     }
102     let ec: *const Extern = null::<Extern>();
103     assert!(ec.is_null());
104
105     let em: *mut Extern = null_mut::<Extern>();
106     assert!(em.is_null());
107 }
108
109 #[test]
110 fn test_as_ref() {
111     unsafe {
112         let p: *const isize = null();
113         assert_eq!(p.as_ref(), None);
114
115         let q: *const isize = &2;
116         assert_eq!(q.as_ref().unwrap(), &2);
117
118         let p: *mut isize = null_mut();
119         assert_eq!(p.as_ref(), None);
120
121         let q: *mut isize = &mut 2;
122         assert_eq!(q.as_ref().unwrap(), &2);
123
124         // Lifetime inference
125         let u = 2isize;
126         {
127             let p = &u as *const isize;
128             assert_eq!(p.as_ref().unwrap(), &2);
129         }
130
131         // Pointers to unsized types -- slices
132         let s: &mut [u8] = &mut [1, 2, 3];
133         let cs: *const [u8] = s;
134         assert_eq!(cs.as_ref(), Some(&*s));
135
136         let ms: *mut [u8] = s;
137         assert_eq!(ms.as_ref(), Some(&*s));
138
139         let cz: *const [u8] = &[];
140         assert_eq!(cz.as_ref(), Some(&[][..]));
141
142         let mz: *mut [u8] = &mut [];
143         assert_eq!(mz.as_ref(), Some(&[][..]));
144
145         let ncs: *const [u8] = null::<[u8; 3]>();
146         assert_eq!(ncs.as_ref(), None);
147
148         let nms: *mut [u8] = null_mut::<[u8; 3]>();
149         assert_eq!(nms.as_ref(), None);
150
151         // Pointers to unsized types -- trait objects
152         let ci: *const dyn ToString = &3;
153         assert!(ci.as_ref().is_some());
154
155         let mi: *mut dyn ToString = &mut 3;
156         assert!(mi.as_ref().is_some());
157
158         let nci: *const dyn ToString = null::<isize>();
159         assert!(nci.as_ref().is_none());
160
161         let nmi: *mut dyn ToString = null_mut::<isize>();
162         assert!(nmi.as_ref().is_none());
163     }
164 }
165
166 #[test]
167 fn test_as_mut() {
168     unsafe {
169         let p: *mut isize = null_mut();
170         assert!(p.as_mut() == None);
171
172         let q: *mut isize = &mut 2;
173         assert!(q.as_mut().unwrap() == &mut 2);
174
175         // Lifetime inference
176         let mut u = 2isize;
177         {
178             let p = &mut u as *mut isize;
179             assert!(p.as_mut().unwrap() == &mut 2);
180         }
181
182         // Pointers to unsized types -- slices
183         let s: &mut [u8] = &mut [1, 2, 3];
184         let ms: *mut [u8] = s;
185         assert_eq!(ms.as_mut(), Some(&mut [1, 2, 3][..]));
186
187         let mz: *mut [u8] = &mut [];
188         assert_eq!(mz.as_mut(), Some(&mut [][..]));
189
190         let nms: *mut [u8] = null_mut::<[u8; 3]>();
191         assert_eq!(nms.as_mut(), None);
192
193         // Pointers to unsized types -- trait objects
194         let mi: *mut dyn ToString = &mut 3;
195         assert!(mi.as_mut().is_some());
196
197         let nmi: *mut dyn ToString = null_mut::<isize>();
198         assert!(nmi.as_mut().is_none());
199     }
200 }
201
202 #[test]
203 fn test_ptr_addition() {
204     unsafe {
205         let xs = vec![5; 16];
206         let mut ptr = xs.as_ptr();
207         let end = ptr.offset(16);
208
209         while ptr < end {
210             assert_eq!(*ptr, 5);
211             ptr = ptr.offset(1);
212         }
213
214         let mut xs_mut = xs;
215         let mut m_ptr = xs_mut.as_mut_ptr();
216         let m_end = m_ptr.offset(16);
217
218         while m_ptr < m_end {
219             *m_ptr += 5;
220             m_ptr = m_ptr.offset(1);
221         }
222
223         assert!(xs_mut == vec![10; 16]);
224     }
225 }
226
227 #[test]
228 fn test_ptr_subtraction() {
229     unsafe {
230         let xs = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
231         let mut idx = 9;
232         let ptr = xs.as_ptr();
233
234         while idx >= 0 {
235             assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
236             idx = idx - 1;
237         }
238
239         let mut xs_mut = xs;
240         let m_start = xs_mut.as_mut_ptr();
241         let mut m_ptr = m_start.offset(9);
242
243         loop {
244             *m_ptr += *m_ptr;
245             if m_ptr == m_start {
246                 break;
247             }
248             m_ptr = m_ptr.offset(-1);
249         }
250
251         assert_eq!(xs_mut, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
252     }
253 }
254
255 #[test]
256 fn test_set_memory() {
257     let mut xs = [0u8; 20];
258     let ptr = xs.as_mut_ptr();
259     unsafe {
260         write_bytes(ptr, 5u8, xs.len());
261     }
262     assert!(xs == [5u8; 20]);
263 }
264
265 #[test]
266 fn test_set_memory_const() {
267     const XS: [u8; 20] = {
268         let mut xs = [0u8; 20];
269         let ptr = xs.as_mut_ptr();
270         unsafe {
271             ptr.write_bytes(5u8, xs.len());
272         }
273         xs
274     };
275
276     assert!(XS == [5u8; 20]);
277 }
278
279 #[test]
280 fn test_unsized_nonnull() {
281     let xs: &[i32] = &[1, 2, 3];
282     let ptr = unsafe { NonNull::new_unchecked(xs as *const [i32] as *mut [i32]) };
283     let ys = unsafe { ptr.as_ref() };
284     let zs: &[i32] = &[1, 2, 3];
285     assert!(ys == zs);
286 }
287
288 #[test]
289 fn test_const_nonnull_new() {
290     const {
291         assert!(NonNull::new(core::ptr::null_mut::<()>()).is_none());
292
293         let value = &mut 0u32;
294         let mut ptr = NonNull::new(value).unwrap();
295         unsafe { *ptr.as_mut() = 42 };
296
297         let reference = unsafe { &*ptr.as_ref() };
298         assert!(*reference == *value);
299         assert!(*reference == 42);
300     };
301 }
302
303 #[test]
304 #[cfg(unix)] // printf may not be available on other platforms
305 #[allow(deprecated)] // For SipHasher
306 pub fn test_variadic_fnptr() {
307     use core::ffi;
308     use core::hash::{Hash, SipHasher};
309     extern "C" {
310         // This needs to use the correct function signature even though it isn't called as some
311         // codegen backends make it UB to declare a function with multiple conflicting signatures
312         // (like LLVM) while others straight up return an error (like Cranelift).
313         fn printf(_: *const ffi::c_char, ...) -> ffi::c_int;
314     }
315     let p: unsafe extern "C" fn(*const ffi::c_char, ...) -> ffi::c_int = printf;
316     let q = p.clone();
317     assert_eq!(p, q);
318     assert!(!(p < q));
319     let mut s = SipHasher::new();
320     assert_eq!(p.hash(&mut s), q.hash(&mut s));
321 }
322
323 #[test]
324 fn write_unaligned_drop() {
325     thread_local! {
326         static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
327     }
328
329     struct Dropper(u32);
330
331     impl Drop for Dropper {
332         fn drop(&mut self) {
333             DROPS.with(|d| d.borrow_mut().push(self.0));
334         }
335     }
336
337     {
338         let c = Dropper(0);
339         let mut t = Dropper(1);
340         unsafe {
341             write_unaligned(&mut t, c);
342         }
343     }
344     DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
345 }
346
347 #[test]
348 fn align_offset_zst() {
349     // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
350     // all, because no amount of elements will align the pointer.
351     let mut p = 1;
352     while p < 1024 {
353         assert_eq!(ptr::invalid::<()>(p).align_offset(p), 0);
354         if p != 1 {
355             assert_eq!(ptr::invalid::<()>(p + 1).align_offset(p), !0);
356         }
357         p = (p + 1).next_power_of_two();
358     }
359 }
360
361 #[test]
362 #[cfg(not(bootstrap))]
363 fn align_offset_zst_const() {
364     const {
365         // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
366         // all, because no amount of elements will align the pointer.
367         let mut p = 1;
368         while p < 1024 {
369             assert!(ptr::invalid::<()>(p).align_offset(p) == 0);
370             if p != 1 {
371                 assert!(ptr::invalid::<()>(p + 1).align_offset(p) == !0);
372             }
373             p = (p + 1).next_power_of_two();
374         }
375     }
376 }
377
378 #[test]
379 fn align_offset_stride_one() {
380     // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
381     // number of bytes.
382     let mut align = 1;
383     while align < 1024 {
384         for ptr in 1..2 * align {
385             let expected = ptr % align;
386             let offset = if expected == 0 { 0 } else { align - expected };
387             assert_eq!(
388                 ptr::invalid::<u8>(ptr).align_offset(align),
389                 offset,
390                 "ptr = {}, align = {}, size = 1",
391                 ptr,
392                 align
393             );
394         }
395         align = (align + 1).next_power_of_two();
396     }
397 }
398
399 #[test]
400 #[cfg(not(bootstrap))]
401 fn align_offset_stride_one_const() {
402     const {
403         // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
404         // number of bytes.
405         let mut align = 1;
406         while align < 1024 {
407             let mut ptr = 1;
408             while ptr < 2 * align {
409                 let expected = ptr % align;
410                 let offset = if expected == 0 { 0 } else { align - expected };
411                 assert!(ptr::invalid::<u8>(ptr).align_offset(align) == offset);
412                 ptr += 1;
413             }
414             align = (align + 1).next_power_of_two();
415         }
416     }
417 }
418
419 #[test]
420 fn align_offset_various_strides() {
421     unsafe fn test_stride<T>(ptr: *const T, align: usize) -> bool {
422         let numptr = ptr as usize;
423         let mut expected = usize::MAX;
424         // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
425         for el in 0..align {
426             if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
427                 expected = el;
428                 break;
429             }
430         }
431         let got = ptr.align_offset(align);
432         if got != expected {
433             eprintln!(
434                 "aligning {:p} (with stride of {}) to {}, expected {}, got {}",
435                 ptr,
436                 ::std::mem::size_of::<T>(),
437                 align,
438                 expected,
439                 got
440             );
441             return true;
442         }
443         return false;
444     }
445
446     // For pointers of stride != 1, we verify the algorithm against the naivest possible
447     // implementation
448     let mut align = 1;
449     let mut x = false;
450     // Miri is too slow
451     let limit = if cfg!(miri) { 32 } else { 1024 };
452     while align < limit {
453         for ptr in 1usize..4 * align {
454             unsafe {
455                 #[repr(packed)]
456                 struct A3(u16, u8);
457                 x |= test_stride::<A3>(ptr::invalid::<A3>(ptr), align);
458
459                 struct A4(u32);
460                 x |= test_stride::<A4>(ptr::invalid::<A4>(ptr), align);
461
462                 #[repr(packed)]
463                 struct A5(u32, u8);
464                 x |= test_stride::<A5>(ptr::invalid::<A5>(ptr), align);
465
466                 #[repr(packed)]
467                 struct A6(u32, u16);
468                 x |= test_stride::<A6>(ptr::invalid::<A6>(ptr), align);
469
470                 #[repr(packed)]
471                 struct A7(u32, u16, u8);
472                 x |= test_stride::<A7>(ptr::invalid::<A7>(ptr), align);
473
474                 #[repr(packed)]
475                 struct A8(u32, u32);
476                 x |= test_stride::<A8>(ptr::invalid::<A8>(ptr), align);
477
478                 #[repr(packed)]
479                 struct A9(u32, u32, u8);
480                 x |= test_stride::<A9>(ptr::invalid::<A9>(ptr), align);
481
482                 #[repr(packed)]
483                 struct A10(u32, u32, u16);
484                 x |= test_stride::<A10>(ptr::invalid::<A10>(ptr), align);
485
486                 x |= test_stride::<u32>(ptr::invalid::<u32>(ptr), align);
487                 x |= test_stride::<u128>(ptr::invalid::<u128>(ptr), align);
488             }
489         }
490         align = (align + 1).next_power_of_two();
491     }
492     assert!(!x);
493 }
494
495 #[test]
496 #[cfg(not(bootstrap))]
497 fn align_offset_various_strides_const() {
498     const unsafe fn test_stride<T>(ptr: *const T, numptr: usize, align: usize) {
499         let mut expected = usize::MAX;
500         // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
501         let mut el = 0;
502         while el < align {
503             if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
504                 expected = el;
505                 break;
506             }
507             el += 1;
508         }
509         let got = ptr.align_offset(align);
510         assert!(got == expected);
511     }
512
513     const {
514         // For pointers of stride != 1, we verify the algorithm against the naivest possible
515         // implementation
516         let mut align = 1;
517         let limit = 32;
518         while align < limit {
519             let mut ptr = 1;
520             while ptr < 4 * align {
521                 unsafe {
522                     #[repr(packed)]
523                     struct A3(u16, u8);
524                     test_stride::<A3>(ptr::invalid::<A3>(ptr), ptr, align);
525
526                     struct A4(u32);
527                     test_stride::<A4>(ptr::invalid::<A4>(ptr), ptr, align);
528
529                     #[repr(packed)]
530                     struct A5(u32, u8);
531                     test_stride::<A5>(ptr::invalid::<A5>(ptr), ptr, align);
532
533                     #[repr(packed)]
534                     struct A6(u32, u16);
535                     test_stride::<A6>(ptr::invalid::<A6>(ptr), ptr, align);
536
537                     #[repr(packed)]
538                     struct A7(u32, u16, u8);
539                     test_stride::<A7>(ptr::invalid::<A7>(ptr), ptr, align);
540
541                     #[repr(packed)]
542                     struct A8(u32, u32);
543                     test_stride::<A8>(ptr::invalid::<A8>(ptr), ptr, align);
544
545                     #[repr(packed)]
546                     struct A9(u32, u32, u8);
547                     test_stride::<A9>(ptr::invalid::<A9>(ptr), ptr, align);
548
549                     #[repr(packed)]
550                     struct A10(u32, u32, u16);
551                     test_stride::<A10>(ptr::invalid::<A10>(ptr), ptr, align);
552
553                     test_stride::<u32>(ptr::invalid::<u32>(ptr), ptr, align);
554                     test_stride::<u128>(ptr::invalid::<u128>(ptr), ptr, align);
555                 }
556                 ptr += 1;
557             }
558             align = (align + 1).next_power_of_two();
559         }
560     }
561 }
562
563 #[test]
564 #[cfg(not(bootstrap))]
565 fn align_offset_with_provenance_const() {
566     const {
567         // On some platforms (e.g. msp430-none-elf), the alignment of `i32` is less than 4.
568         #[repr(align(4))]
569         struct AlignedI32(i32);
570
571         let data = AlignedI32(42);
572
573         // `stride % align == 0` (usual case)
574
575         let ptr: *const i32 = &data.0;
576         assert!(ptr.align_offset(1) == 0);
577         assert!(ptr.align_offset(2) == 0);
578         assert!(ptr.align_offset(4) == 0);
579         assert!(ptr.align_offset(8) == usize::MAX);
580         assert!(ptr.wrapping_byte_add(1).align_offset(1) == 0);
581         assert!(ptr.wrapping_byte_add(1).align_offset(2) == usize::MAX);
582         assert!(ptr.wrapping_byte_add(2).align_offset(1) == 0);
583         assert!(ptr.wrapping_byte_add(2).align_offset(2) == 0);
584         assert!(ptr.wrapping_byte_add(2).align_offset(4) == usize::MAX);
585         assert!(ptr.wrapping_byte_add(3).align_offset(1) == 0);
586         assert!(ptr.wrapping_byte_add(3).align_offset(2) == usize::MAX);
587
588         assert!(ptr.wrapping_add(42).align_offset(4) == 0);
589         assert!(ptr.wrapping_add(42).align_offset(8) == usize::MAX);
590
591         let ptr1: *const i8 = ptr.cast();
592         assert!(ptr1.align_offset(1) == 0);
593         assert!(ptr1.align_offset(2) == 0);
594         assert!(ptr1.align_offset(4) == 0);
595         assert!(ptr1.align_offset(8) == usize::MAX);
596         assert!(ptr1.wrapping_byte_add(1).align_offset(1) == 0);
597         assert!(ptr1.wrapping_byte_add(1).align_offset(2) == 1);
598         assert!(ptr1.wrapping_byte_add(1).align_offset(4) == 3);
599         assert!(ptr1.wrapping_byte_add(1).align_offset(8) == usize::MAX);
600         assert!(ptr1.wrapping_byte_add(2).align_offset(1) == 0);
601         assert!(ptr1.wrapping_byte_add(2).align_offset(2) == 0);
602         assert!(ptr1.wrapping_byte_add(2).align_offset(4) == 2);
603         assert!(ptr1.wrapping_byte_add(2).align_offset(8) == usize::MAX);
604         assert!(ptr1.wrapping_byte_add(3).align_offset(1) == 0);
605         assert!(ptr1.wrapping_byte_add(3).align_offset(2) == 1);
606         assert!(ptr1.wrapping_byte_add(3).align_offset(4) == 1);
607         assert!(ptr1.wrapping_byte_add(3).align_offset(8) == usize::MAX);
608
609         let ptr2: *const i16 = ptr.cast();
610         assert!(ptr2.align_offset(1) == 0);
611         assert!(ptr2.align_offset(2) == 0);
612         assert!(ptr2.align_offset(4) == 0);
613         assert!(ptr2.align_offset(8) == usize::MAX);
614         assert!(ptr2.wrapping_byte_add(1).align_offset(1) == 0);
615         assert!(ptr2.wrapping_byte_add(1).align_offset(2) == usize::MAX);
616         assert!(ptr2.wrapping_byte_add(2).align_offset(1) == 0);
617         assert!(ptr2.wrapping_byte_add(2).align_offset(2) == 0);
618         assert!(ptr2.wrapping_byte_add(2).align_offset(4) == 1);
619         assert!(ptr2.wrapping_byte_add(2).align_offset(8) == usize::MAX);
620         assert!(ptr2.wrapping_byte_add(3).align_offset(1) == 0);
621         assert!(ptr2.wrapping_byte_add(3).align_offset(2) == usize::MAX);
622
623         let ptr3: *const i64 = ptr.cast();
624         assert!(ptr3.align_offset(1) == 0);
625         assert!(ptr3.align_offset(2) == 0);
626         assert!(ptr3.align_offset(4) == 0);
627         assert!(ptr3.align_offset(8) == usize::MAX);
628         assert!(ptr3.wrapping_byte_add(1).align_offset(1) == 0);
629         assert!(ptr3.wrapping_byte_add(1).align_offset(2) == usize::MAX);
630
631         // `stride % align != 0` (edge case)
632
633         let ptr4: *const [u8; 3] = ptr.cast();
634         assert!(ptr4.align_offset(1) == 0);
635         assert!(ptr4.align_offset(2) == 0);
636         assert!(ptr4.align_offset(4) == 0);
637         assert!(ptr4.align_offset(8) == usize::MAX);
638         assert!(ptr4.wrapping_byte_add(1).align_offset(1) == 0);
639         assert!(ptr4.wrapping_byte_add(1).align_offset(2) == 1);
640         assert!(ptr4.wrapping_byte_add(1).align_offset(4) == 1);
641         assert!(ptr4.wrapping_byte_add(1).align_offset(8) == usize::MAX);
642         assert!(ptr4.wrapping_byte_add(2).align_offset(1) == 0);
643         assert!(ptr4.wrapping_byte_add(2).align_offset(2) == 0);
644         assert!(ptr4.wrapping_byte_add(2).align_offset(4) == 2);
645         assert!(ptr4.wrapping_byte_add(2).align_offset(8) == usize::MAX);
646         assert!(ptr4.wrapping_byte_add(3).align_offset(1) == 0);
647         assert!(ptr4.wrapping_byte_add(3).align_offset(2) == 1);
648         assert!(ptr4.wrapping_byte_add(3).align_offset(4) == 3);
649         assert!(ptr4.wrapping_byte_add(3).align_offset(8) == usize::MAX);
650
651         let ptr5: *const [u8; 5] = ptr.cast();
652         assert!(ptr5.align_offset(1) == 0);
653         assert!(ptr5.align_offset(2) == 0);
654         assert!(ptr5.align_offset(4) == 0);
655         assert!(ptr5.align_offset(8) == usize::MAX);
656         assert!(ptr5.wrapping_byte_add(1).align_offset(1) == 0);
657         assert!(ptr5.wrapping_byte_add(1).align_offset(2) == 1);
658         assert!(ptr5.wrapping_byte_add(1).align_offset(4) == 3);
659         assert!(ptr5.wrapping_byte_add(1).align_offset(8) == usize::MAX);
660         assert!(ptr5.wrapping_byte_add(2).align_offset(1) == 0);
661         assert!(ptr5.wrapping_byte_add(2).align_offset(2) == 0);
662         assert!(ptr5.wrapping_byte_add(2).align_offset(4) == 2);
663         assert!(ptr5.wrapping_byte_add(2).align_offset(8) == usize::MAX);
664         assert!(ptr5.wrapping_byte_add(3).align_offset(1) == 0);
665         assert!(ptr5.wrapping_byte_add(3).align_offset(2) == 1);
666         assert!(ptr5.wrapping_byte_add(3).align_offset(4) == 1);
667         assert!(ptr5.wrapping_byte_add(3).align_offset(8) == usize::MAX);
668     }
669 }
670
671 #[test]
672 fn align_offset_issue_103361() {
673     #[cfg(target_pointer_width = "64")]
674     const SIZE: usize = 1 << 47;
675     #[cfg(target_pointer_width = "32")]
676     const SIZE: usize = 1 << 30;
677     #[cfg(target_pointer_width = "16")]
678     const SIZE: usize = 1 << 13;
679     struct HugeSize([u8; SIZE - 1]);
680     let _ = (SIZE as *const HugeSize).align_offset(SIZE);
681 }
682
683 #[test]
684 #[cfg(not(bootstrap))]
685 fn align_offset_issue_103361_const() {
686     #[cfg(target_pointer_width = "64")]
687     const SIZE: usize = 1 << 47;
688     #[cfg(target_pointer_width = "32")]
689     const SIZE: usize = 1 << 30;
690     #[cfg(target_pointer_width = "16")]
691     const SIZE: usize = 1 << 13;
692     struct HugeSize([u8; SIZE - 1]);
693
694     const {
695         assert!(ptr::invalid::<HugeSize>(SIZE - 1).align_offset(SIZE) == SIZE - 1);
696         assert!(ptr::invalid::<HugeSize>(SIZE).align_offset(SIZE) == 0);
697         assert!(ptr::invalid::<HugeSize>(SIZE + 1).align_offset(SIZE) == 1);
698     }
699 }
700
701 #[test]
702 fn is_aligned() {
703     let data = 42;
704     let ptr: *const i32 = &data;
705     assert!(ptr.is_aligned());
706     assert!(ptr.is_aligned_to(1));
707     assert!(ptr.is_aligned_to(2));
708     assert!(ptr.is_aligned_to(4));
709     assert!(ptr.wrapping_byte_add(2).is_aligned_to(1));
710     assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
711     assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
712
713     // At runtime either `ptr` or `ptr+1` is aligned to 8.
714     assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
715 }
716
717 #[test]
718 #[cfg(not(bootstrap))]
719 fn is_aligned_const() {
720     const {
721         let data = 42;
722         let ptr: *const i32 = &data;
723         assert!(ptr.is_aligned());
724         assert!(ptr.is_aligned_to(1));
725         assert!(ptr.is_aligned_to(2));
726         assert!(ptr.is_aligned_to(4));
727         assert!(ptr.wrapping_byte_add(2).is_aligned_to(1));
728         assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
729         assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
730
731         // At comptime neither `ptr` nor `ptr+1` is aligned to 8.
732         assert!(!ptr.is_aligned_to(8));
733         assert!(!ptr.wrapping_add(1).is_aligned_to(8));
734     }
735 }
736
737 #[test]
738 #[cfg(bootstrap)]
739 fn is_aligned_const() {
740     const {
741         let data = 42;
742         let ptr: *const i32 = &data;
743         // The bootstrap compiler always returns false for is_aligned.
744         assert!(!ptr.is_aligned());
745         assert!(!ptr.is_aligned_to(1));
746     }
747 }
748
749 #[test]
750 fn offset_from() {
751     let mut a = [0; 5];
752     let ptr1: *mut i32 = &mut a[1];
753     let ptr2: *mut i32 = &mut a[3];
754     unsafe {
755         assert_eq!(ptr2.offset_from(ptr1), 2);
756         assert_eq!(ptr1.offset_from(ptr2), -2);
757         assert_eq!(ptr1.offset(2), ptr2);
758         assert_eq!(ptr2.offset(-2), ptr1);
759     }
760 }
761
762 #[test]
763 fn ptr_metadata() {
764     struct Unit;
765     struct Pair<A, B: ?Sized>(A, B);
766     extern "C" {
767         type Extern;
768     }
769     let () = metadata(&());
770     let () = metadata(&Unit);
771     let () = metadata(&4_u32);
772     let () = metadata(&String::new());
773     let () = metadata(&Some(4_u32));
774     let () = metadata(&ptr_metadata);
775     let () = metadata(&|| {});
776     let () = metadata(&[4, 7]);
777     let () = metadata(&(4, String::new()));
778     let () = metadata(&Pair(4, String::new()));
779     let () = metadata(ptr::null::<()>() as *const Extern);
780     let () = metadata(ptr::null::<()>() as *const <&u32 as std::ops::Deref>::Target);
781
782     assert_eq!(metadata("foo"), 3_usize);
783     assert_eq!(metadata(&[4, 7][..]), 2_usize);
784
785     let dst_tuple: &(bool, [u8]) = &(true, [0x66, 0x6F, 0x6F]);
786     let dst_struct: &Pair<bool, [u8]> = &Pair(true, [0x66, 0x6F, 0x6F]);
787     assert_eq!(metadata(dst_tuple), 3_usize);
788     assert_eq!(metadata(dst_struct), 3_usize);
789     unsafe {
790         let dst_tuple: &(bool, str) = std::mem::transmute(dst_tuple);
791         let dst_struct: &Pair<bool, str> = std::mem::transmute(dst_struct);
792         assert_eq!(&dst_tuple.1, "foo");
793         assert_eq!(&dst_struct.1, "foo");
794         assert_eq!(metadata(dst_tuple), 3_usize);
795         assert_eq!(metadata(dst_struct), 3_usize);
796     }
797
798     let vtable_1: DynMetadata<dyn Debug> = metadata(&4_u16 as &dyn Debug);
799     let vtable_2: DynMetadata<dyn Display> = metadata(&4_u16 as &dyn Display);
800     let vtable_3: DynMetadata<dyn Display> = metadata(&4_u32 as &dyn Display);
801     let vtable_4: DynMetadata<dyn Display> = metadata(&(true, 7_u32) as &(bool, dyn Display));
802     let vtable_5: DynMetadata<dyn Display> =
803         metadata(&Pair(true, 7_u32) as &Pair<bool, dyn Display>);
804     unsafe {
805         let address_1: *const () = std::mem::transmute(vtable_1);
806         let address_2: *const () = std::mem::transmute(vtable_2);
807         let address_3: *const () = std::mem::transmute(vtable_3);
808         let address_4: *const () = std::mem::transmute(vtable_4);
809         let address_5: *const () = std::mem::transmute(vtable_5);
810         // Different trait => different vtable pointer
811         assert_ne!(address_1, address_2);
812         // Different erased type => different vtable pointer
813         assert_ne!(address_2, address_3);
814         // Same erased type and same trait => same vtable pointer
815         assert_eq!(address_3, address_4);
816         assert_eq!(address_3, address_5);
817     }
818 }
819
820 #[test]
821 fn ptr_metadata_bounds() {
822     fn metadata_eq_method_address<T: ?Sized>() -> usize {
823         // The `Metadata` associated type has an `Ord` bound, so this is valid:
824         <<T as Pointee>::Metadata as PartialEq>::eq as usize
825     }
826     // "Synthetic" trait impls generated by the compiler like those of `Pointee`
827     // are not checked for bounds of associated type.
828     // So with a buggy libcore we could have both:
829     // * `<dyn Display as Pointee>::Metadata == DynMetadata`
830     // * `DynMetadata: !PartialEq`
831     // â€¦ and cause an ICE here:
832     metadata_eq_method_address::<dyn Display>();
833
834     // For this reason, let’s check here that bounds are satisfied:
835
836     let _ = static_assert_expected_bounds_for_metadata::<()>;
837     let _ = static_assert_expected_bounds_for_metadata::<usize>;
838     let _ = static_assert_expected_bounds_for_metadata::<DynMetadata<dyn Display>>;
839     fn _static_assert_associated_type<T: ?Sized>() {
840         let _ = static_assert_expected_bounds_for_metadata::<<T as Pointee>::Metadata>;
841     }
842
843     fn static_assert_expected_bounds_for_metadata<Meta>()
844     where
845         // Keep this in sync with the associated type in `library/core/src/ptr/metadata.rs`
846         Meta: Copy + Send + Sync + Ord + std::hash::Hash + Unpin,
847     {
848     }
849 }
850
851 #[test]
852 fn dyn_metadata() {
853     #[derive(Debug)]
854     #[repr(align(32))]
855     struct Something([u8; 47]);
856
857     let value = Something([0; 47]);
858     let trait_object: &dyn Debug = &value;
859     let meta = metadata(trait_object);
860
861     assert_eq!(meta.size_of(), 64);
862     assert_eq!(meta.size_of(), std::mem::size_of::<Something>());
863     assert_eq!(meta.align_of(), 32);
864     assert_eq!(meta.align_of(), std::mem::align_of::<Something>());
865     assert_eq!(meta.layout(), std::alloc::Layout::new::<Something>());
866
867     assert!(format!("{meta:?}").starts_with("DynMetadata(0x"));
868 }
869
870 #[test]
871 fn from_raw_parts() {
872     let mut value = 5_u32;
873     let address = &mut value as *mut _ as *mut ();
874     let trait_object: &dyn Display = &mut value;
875     let vtable = metadata(trait_object);
876     let trait_object = NonNull::from(trait_object);
877
878     assert_eq!(ptr::from_raw_parts(address, vtable), trait_object.as_ptr());
879     assert_eq!(ptr::from_raw_parts_mut(address, vtable), trait_object.as_ptr());
880     assert_eq!(NonNull::from_raw_parts(NonNull::new(address).unwrap(), vtable), trait_object);
881
882     let mut array = [5_u32, 5, 5, 5, 5];
883     let address = &mut array as *mut _ as *mut ();
884     let array_ptr = NonNull::from(&mut array);
885     let slice_ptr = NonNull::from(&mut array[..]);
886
887     assert_eq!(ptr::from_raw_parts(address, ()), array_ptr.as_ptr());
888     assert_eq!(ptr::from_raw_parts_mut(address, ()), array_ptr.as_ptr());
889     assert_eq!(NonNull::from_raw_parts(NonNull::new(address).unwrap(), ()), array_ptr);
890
891     assert_eq!(ptr::from_raw_parts(address, 5), slice_ptr.as_ptr());
892     assert_eq!(ptr::from_raw_parts_mut(address, 5), slice_ptr.as_ptr());
893     assert_eq!(NonNull::from_raw_parts(NonNull::new(address).unwrap(), 5), slice_ptr);
894 }
895
896 #[test]
897 fn thin_box() {
898     let foo = ThinBox::<dyn Display>::new(4);
899     assert_eq!(foo.to_string(), "4");
900     drop(foo);
901     let bar = ThinBox::<dyn Display>::new(7);
902     assert_eq!(bar.to_string(), "7");
903
904     // A slightly more interesting library that could be built on top of metadata APIs.
905     //
906     // * It could be generalized to any `T: ?Sized` (not just trait object)
907     //   if `{size,align}_of_for_meta<T: ?Sized>(T::Metadata)` are added.
908     // * Constructing a `ThinBox` without consuming and deallocating a `Box`
909     //   requires either the unstable `Unsize` marker trait,
910     //   or the unstable `unsized_locals` language feature,
911     //   or taking `&dyn T` and restricting to `T: Copy`.
912
913     use std::alloc::*;
914     use std::marker::PhantomData;
915
916     struct ThinBox<T>
917     where
918         T: ?Sized + Pointee<Metadata = DynMetadata<T>>,
919     {
920         ptr: NonNull<DynMetadata<T>>,
921         phantom: PhantomData<T>,
922     }
923
924     impl<T> ThinBox<T>
925     where
926         T: ?Sized + Pointee<Metadata = DynMetadata<T>>,
927     {
928         pub fn new<Value: std::marker::Unsize<T>>(value: Value) -> Self {
929             let unsized_: &T = &value;
930             let meta = metadata(unsized_);
931             let meta_layout = Layout::for_value(&meta);
932             let value_layout = Layout::for_value(&value);
933             let (layout, offset) = meta_layout.extend(value_layout).unwrap();
934             // `DynMetadata` is pointer-sized:
935             assert!(layout.size() > 0);
936             // If `ThinBox<T>` is generalized to any `T: ?Sized`,
937             // handle ZSTs with a dangling pointer without going through `alloc()`,
938             // like `Box<T>` does.
939             unsafe {
940                 let ptr = NonNull::new(alloc(layout))
941                     .unwrap_or_else(|| handle_alloc_error(layout))
942                     .cast::<DynMetadata<T>>();
943                 ptr.as_ptr().write(meta);
944                 ptr.as_ptr().byte_add(offset).cast::<Value>().write(value);
945                 Self { ptr, phantom: PhantomData }
946             }
947         }
948
949         fn meta(&self) -> DynMetadata<T> {
950             unsafe { *self.ptr.as_ref() }
951         }
952
953         fn layout(&self) -> (Layout, usize) {
954             let meta = self.meta();
955             Layout::for_value(&meta).extend(meta.layout()).unwrap()
956         }
957
958         fn value_ptr(&self) -> *const T {
959             let (_, offset) = self.layout();
960             let data_ptr = unsafe { self.ptr.cast::<u8>().as_ptr().add(offset) };
961             ptr::from_raw_parts(data_ptr.cast(), self.meta())
962         }
963
964         fn value_mut_ptr(&mut self) -> *mut T {
965             let (_, offset) = self.layout();
966             // FIXME: can this line be shared with the same in `value_ptr()`
967             // without upsetting Stacked Borrows?
968             let data_ptr = unsafe { self.ptr.cast::<u8>().as_ptr().add(offset) };
969             from_raw_parts_mut(data_ptr.cast(), self.meta())
970         }
971     }
972
973     impl<T> std::ops::Deref for ThinBox<T>
974     where
975         T: ?Sized + Pointee<Metadata = DynMetadata<T>>,
976     {
977         type Target = T;
978
979         fn deref(&self) -> &T {
980             unsafe { &*self.value_ptr() }
981         }
982     }
983
984     impl<T> std::ops::DerefMut for ThinBox<T>
985     where
986         T: ?Sized + Pointee<Metadata = DynMetadata<T>>,
987     {
988         fn deref_mut(&mut self) -> &mut T {
989             unsafe { &mut *self.value_mut_ptr() }
990         }
991     }
992
993     impl<T> std::ops::Drop for ThinBox<T>
994     where
995         T: ?Sized + Pointee<Metadata = DynMetadata<T>>,
996     {
997         fn drop(&mut self) {
998             let (layout, _) = self.layout();
999             unsafe {
1000                 drop_in_place::<T>(&mut **self);
1001                 dealloc(self.ptr.cast().as_ptr(), layout);
1002             }
1003         }
1004     }
1005 }
1006
1007 #[test]
1008 fn nonnull_tagged_pointer_with_provenance() {
1009     let raw_pointer = Box::into_raw(Box::new(10));
1010
1011     let mut p = TaggedPointer::new(raw_pointer).unwrap();
1012     assert_eq!(p.tag(), 0);
1013
1014     p.set_tag(1);
1015     assert_eq!(p.tag(), 1);
1016     assert_eq!(unsafe { *p.pointer().as_ptr() }, 10);
1017
1018     p.set_tag(3);
1019     assert_eq!(p.tag(), 3);
1020     assert_eq!(unsafe { *p.pointer().as_ptr() }, 10);
1021
1022     unsafe { Box::from_raw(p.pointer().as_ptr()) };
1023
1024     /// A non-null pointer type which carries several bits of metadata and maintains provenance.
1025     #[repr(transparent)]
1026     pub struct TaggedPointer<T>(NonNull<T>);
1027
1028     impl<T> Clone for TaggedPointer<T> {
1029         fn clone(&self) -> Self {
1030             Self(self.0)
1031         }
1032     }
1033
1034     impl<T> Copy for TaggedPointer<T> {}
1035
1036     impl<T> TaggedPointer<T> {
1037         /// The ABI-required minimum alignment of the `P` type.
1038         pub const ALIGNMENT: usize = core::mem::align_of::<T>();
1039         /// A mask for data-carrying bits of the address.
1040         pub const DATA_MASK: usize = !Self::ADDRESS_MASK;
1041         /// Number of available bits of storage in the address.
1042         pub const NUM_BITS: u32 = Self::ALIGNMENT.trailing_zeros();
1043         /// A mask for the non-data-carrying bits of the address.
1044         pub const ADDRESS_MASK: usize = usize::MAX << Self::NUM_BITS;
1045
1046         /// Create a new tagged pointer from a possibly null pointer.
1047         pub fn new(pointer: *mut T) -> Option<TaggedPointer<T>> {
1048             Some(TaggedPointer(NonNull::new(pointer)?))
1049         }
1050
1051         /// Consume this tagged pointer and produce a raw mutable pointer to the
1052         /// memory location.
1053         pub fn pointer(self) -> NonNull<T> {
1054             // SAFETY: The `addr` guaranteed to have bits set in the Self::ADDRESS_MASK, so the result will be non-null.
1055             self.0.map_addr(|addr| unsafe {
1056                 NonZeroUsize::new_unchecked(addr.get() & Self::ADDRESS_MASK)
1057             })
1058         }
1059
1060         /// Consume this tagged pointer and produce the data it carries.
1061         pub fn tag(&self) -> usize {
1062             self.0.addr().get() & Self::DATA_MASK
1063         }
1064
1065         /// Update the data this tagged pointer carries to a new value.
1066         pub fn set_tag(&mut self, data: usize) {
1067             assert_eq!(
1068                 data & Self::ADDRESS_MASK,
1069                 0,
1070                 "cannot set more data beyond the lowest NUM_BITS"
1071             );
1072             let data = data & Self::DATA_MASK;
1073
1074             // SAFETY: This value will always be non-zero because the upper bits (from
1075             // ADDRESS_MASK) will always be non-zero. This a property of the type and its
1076             // construction.
1077             self.0 = self.0.map_addr(|addr| unsafe {
1078                 NonZeroUsize::new_unchecked((addr.get() & Self::ADDRESS_MASK) | data)
1079             })
1080         }
1081     }
1082 }
1083
1084 #[test]
1085 fn swap_copy_untyped() {
1086     // We call `{swap,copy}{,_nonoverlapping}` at `bool` type on data that is not a valid bool.
1087     // These should all do untyped copies, so this should work fine.
1088     let mut x = 5u8;
1089     let mut y = 6u8;
1090
1091     let ptr1 = &mut x as *mut u8 as *mut bool;
1092     let ptr2 = &mut y as *mut u8 as *mut bool;
1093
1094     unsafe {
1095         ptr::swap(ptr1, ptr2);
1096         ptr::swap_nonoverlapping(ptr1, ptr2, 1);
1097     }
1098     assert_eq!(x, 5);
1099     assert_eq!(y, 6);
1100
1101     unsafe {
1102         ptr::copy(ptr1, ptr2, 1);
1103         ptr::copy_nonoverlapping(ptr1, ptr2, 1);
1104     }
1105     assert_eq!(x, 5);
1106     assert_eq!(y, 5);
1107 }
1108
1109 #[test]
1110 fn test_const_copy() {
1111     const {
1112         let ptr1 = &1;
1113         let mut ptr2 = &666;
1114
1115         // Copy ptr1 to ptr2, bytewise.
1116         unsafe {
1117             ptr::copy(
1118                 &ptr1 as *const _ as *const MaybeUninit<u8>,
1119                 &mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
1120                 mem::size_of::<&i32>(),
1121             );
1122         }
1123
1124         // Make sure they still work.
1125         assert!(*ptr1 == 1);
1126         assert!(*ptr2 == 1);
1127     };
1128
1129     const {
1130         let ptr1 = &1;
1131         let mut ptr2 = &666;
1132
1133         // Copy ptr1 to ptr2, bytewise.
1134         unsafe {
1135             ptr::copy_nonoverlapping(
1136                 &ptr1 as *const _ as *const MaybeUninit<u8>,
1137                 &mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
1138                 mem::size_of::<&i32>(),
1139             );
1140         }
1141
1142         // Make sure they still work.
1143         assert!(*ptr1 == 1);
1144         assert!(*ptr2 == 1);
1145     };
1146 }