Add tests for tagged pointers
This commit is contained in:
parent
5e4577ec65
commit
6f9b15c40c
4 changed files with 222 additions and 0 deletions
|
@ -203,3 +203,33 @@ where
|
||||||
self.tag().hash_stable(hcx, hasher);
|
self.tag().hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test that `new` does not compile if there is not enough alignment for the
|
||||||
|
/// tag in the pointer.
|
||||||
|
///
|
||||||
|
/// ```compile_fail,E0080
|
||||||
|
/// use rustc_data_structures::tagged_ptr::{CopyTaggedPtr, Tag};
|
||||||
|
///
|
||||||
|
/// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
/// enum Tag2 { B00 = 0b00, B01 = 0b01, B10 = 0b10, B11 = 0b11 };
|
||||||
|
///
|
||||||
|
/// unsafe impl Tag for Tag2 {
|
||||||
|
/// const BITS: usize = 2;
|
||||||
|
///
|
||||||
|
/// fn into_usize(self) -> usize { todo!() }
|
||||||
|
/// unsafe fn from_usize(tag: usize) -> Self { todo!() }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let value = 12u16;
|
||||||
|
/// let reference = &value;
|
||||||
|
/// let tag = Tag2::B01;
|
||||||
|
///
|
||||||
|
/// let _ptr = CopyTaggedPtr::<_, _, true>::new(reference, tag);
|
||||||
|
/// ```
|
||||||
|
// For some reason miri does not get the compile error
|
||||||
|
// probably it `check`s instead of `build`ing?
|
||||||
|
#[cfg(not(miri))]
|
||||||
|
const _: () = ();
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
61
compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs
Normal file
61
compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
use crate::tagged_ptr::{CopyTaggedPtr, Pointer, Tag};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
enum Tag2 {
|
||||||
|
B00 = 0b00,
|
||||||
|
B01 = 0b01,
|
||||||
|
B10 = 0b10,
|
||||||
|
B11 = 0b11,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Tag for Tag2 {
|
||||||
|
const BITS: usize = 2;
|
||||||
|
|
||||||
|
fn into_usize(self) -> usize {
|
||||||
|
self as _
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn from_usize(tag: usize) -> Self {
|
||||||
|
const B00: usize = Tag2::B00 as _;
|
||||||
|
const B01: usize = Tag2::B01 as _;
|
||||||
|
const B10: usize = Tag2::B10 as _;
|
||||||
|
const B11: usize = Tag2::B11 as _;
|
||||||
|
match tag {
|
||||||
|
B00 => Tag2::B00,
|
||||||
|
B01 => Tag2::B01,
|
||||||
|
B10 => Tag2::B10,
|
||||||
|
B11 => Tag2::B11,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn smoke() {
|
||||||
|
let value = 12u32;
|
||||||
|
let reference = &value;
|
||||||
|
let tag = Tag2::B01;
|
||||||
|
|
||||||
|
let ptr = tag_ptr(reference, tag);
|
||||||
|
|
||||||
|
assert_eq!(ptr.tag(), tag);
|
||||||
|
assert_eq!(*ptr, 12);
|
||||||
|
assert!(ptr::eq(ptr.pointer(), reference));
|
||||||
|
|
||||||
|
let copy = ptr;
|
||||||
|
|
||||||
|
let mut ptr = ptr;
|
||||||
|
ptr.set_tag(Tag2::B00);
|
||||||
|
assert_eq!(ptr.tag(), Tag2::B00);
|
||||||
|
|
||||||
|
assert_eq!(copy.tag(), tag);
|
||||||
|
assert_eq!(*copy, 12);
|
||||||
|
assert!(ptr::eq(copy.pointer(), reference));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to create tagged pointers without specifying `COMPARE_PACKED` if it does not matter.
|
||||||
|
fn tag_ptr<P: Pointer, T: Tag>(ptr: P, tag: T) -> CopyTaggedPtr<P, T, true> {
|
||||||
|
CopyTaggedPtr::new(ptr, tag)
|
||||||
|
}
|
|
@ -134,3 +134,33 @@ where
|
||||||
self.raw.hash_stable(hcx, hasher);
|
self.raw.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test that `new` does not compile if there is not enough alignment for the
|
||||||
|
/// tag in the pointer.
|
||||||
|
///
|
||||||
|
/// ```compile_fail,E0080
|
||||||
|
/// use rustc_data_structures::tagged_ptr::{TaggedPtr, Tag};
|
||||||
|
///
|
||||||
|
/// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
/// enum Tag2 { B00 = 0b00, B01 = 0b01, B10 = 0b10, B11 = 0b11 };
|
||||||
|
///
|
||||||
|
/// unsafe impl Tag for Tag2 {
|
||||||
|
/// const BITS: usize = 2;
|
||||||
|
///
|
||||||
|
/// fn into_usize(self) -> usize { todo!() }
|
||||||
|
/// unsafe fn from_usize(tag: usize) -> Self { todo!() }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let value = 12u16;
|
||||||
|
/// let reference = &value;
|
||||||
|
/// let tag = Tag2::B01;
|
||||||
|
///
|
||||||
|
/// let _ptr = TaggedPtr::<_, _, true>::new(reference, tag);
|
||||||
|
/// ```
|
||||||
|
// For some reason miri does not get the compile error
|
||||||
|
// probably it `check`s instead of `build`ing?
|
||||||
|
#[cfg(not(miri))]
|
||||||
|
const _: () = ();
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
101
compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs
Normal file
101
compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
use std::{ptr, sync::Arc};
|
||||||
|
|
||||||
|
use crate::tagged_ptr::{Pointer, Tag, TaggedPtr};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
enum Tag2 {
|
||||||
|
B00 = 0b00,
|
||||||
|
B01 = 0b01,
|
||||||
|
B10 = 0b10,
|
||||||
|
B11 = 0b11,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Tag for Tag2 {
|
||||||
|
const BITS: usize = 2;
|
||||||
|
|
||||||
|
fn into_usize(self) -> usize {
|
||||||
|
self as _
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn from_usize(tag: usize) -> Self {
|
||||||
|
const B00: usize = Tag2::B00 as _;
|
||||||
|
const B01: usize = Tag2::B01 as _;
|
||||||
|
const B10: usize = Tag2::B10 as _;
|
||||||
|
const B11: usize = Tag2::B11 as _;
|
||||||
|
match tag {
|
||||||
|
B00 => Tag2::B00,
|
||||||
|
B01 => Tag2::B01,
|
||||||
|
B10 => Tag2::B10,
|
||||||
|
B11 => Tag2::B11,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn smoke() {
|
||||||
|
let value = 12u32;
|
||||||
|
let reference = &value;
|
||||||
|
let tag = Tag2::B01;
|
||||||
|
|
||||||
|
let ptr = tag_ptr(reference, tag);
|
||||||
|
|
||||||
|
assert_eq!(ptr.tag(), tag);
|
||||||
|
assert_eq!(*ptr, 12);
|
||||||
|
|
||||||
|
let clone = ptr.clone();
|
||||||
|
assert_eq!(clone.tag(), tag);
|
||||||
|
assert_eq!(*clone, 12);
|
||||||
|
|
||||||
|
let mut ptr = ptr;
|
||||||
|
ptr.set_tag(Tag2::B00);
|
||||||
|
assert_eq!(ptr.tag(), Tag2::B00);
|
||||||
|
|
||||||
|
assert_eq!(clone.tag(), tag);
|
||||||
|
assert_eq!(*clone, 12);
|
||||||
|
assert!(ptr::eq(&*ptr, &*clone))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn boxed() {
|
||||||
|
let value = 12u32;
|
||||||
|
let boxed = Box::new(value);
|
||||||
|
let tag = Tag2::B01;
|
||||||
|
|
||||||
|
let ptr = tag_ptr(boxed, tag);
|
||||||
|
|
||||||
|
assert_eq!(ptr.tag(), tag);
|
||||||
|
assert_eq!(*ptr, 12);
|
||||||
|
|
||||||
|
let clone = ptr.clone();
|
||||||
|
assert_eq!(clone.tag(), tag);
|
||||||
|
assert_eq!(*clone, 12);
|
||||||
|
|
||||||
|
let mut ptr = ptr;
|
||||||
|
ptr.set_tag(Tag2::B00);
|
||||||
|
assert_eq!(ptr.tag(), Tag2::B00);
|
||||||
|
|
||||||
|
assert_eq!(clone.tag(), tag);
|
||||||
|
assert_eq!(*clone, 12);
|
||||||
|
assert!(!ptr::eq(&*ptr, &*clone))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn arclones() {
|
||||||
|
let value = 12u32;
|
||||||
|
let arc = Arc::new(value);
|
||||||
|
let tag = Tag2::B01;
|
||||||
|
|
||||||
|
let ptr = tag_ptr(arc, tag);
|
||||||
|
|
||||||
|
assert_eq!(ptr.tag(), tag);
|
||||||
|
assert_eq!(*ptr, 12);
|
||||||
|
|
||||||
|
let clone = ptr.clone();
|
||||||
|
assert!(ptr::eq(&*ptr, &*clone))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to create tagged pointers without specifying `COMPARE_PACKED` if it does not matter.
|
||||||
|
fn tag_ptr<P: Pointer, T: Tag>(ptr: P, tag: T) -> TaggedPtr<P, T, true> {
|
||||||
|
TaggedPtr::new(ptr, tag)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue