mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Add tests for tagged pointers
This commit is contained in:
parent
5e4577ec65
commit
6f9b15c40c
@ -203,3 +203,33 @@ where
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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…
Reference in New Issue
Block a user