use core::{
any,
borrow,
cmp,
convert,
fmt,
future,
hash,
iter,
marker,
mem::{self, MaybeUninit},
ops,
pin,
ptr::{self, NonNull},
task,
};
use alloc::boxed::Box;
#[cfg(feature = "nightly-async-iterator")]
use core::async_iter;
#[cfg(feature = "nightly-coerce-unsized")]
use core::ops::CoerceUnsized;
#[cfg(feature = "nightly-dispatch-from-dyn")]
use core::ops::DispatchFromDyn;
pub struct StaticRc<T: ?Sized, const NUM: usize, const DEN: usize> {
pointer: NonNull<T>,
}
impl<T, const N: usize> StaticRc<T, N, N> {
#[inline(always)]
pub fn new(value: T) -> Self
where
AssertLeType!(1, N): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
assert!(N > 0);
let pointer = NonNull::from(Box::leak(Box::new(value)));
Self { pointer }
}
#[inline(always)]
pub fn pin(value: T) -> pin::Pin<Self>
where
AssertLeType!(1, N): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
assert!(N > 0);
unsafe { pin::Pin::new_unchecked(Self::new(value)) }
}
#[inline(always)]
pub fn into_inner(this: Self) -> T {
let boxed = unsafe { Box::from_raw(this.pointer.as_ptr()) };
mem::forget(this);
*boxed
}
}
impl<T: ?Sized, const N: usize> StaticRc<T, N, N> {
#[inline(always)]
pub fn get_mut(this: &mut Self) -> &mut T {
unsafe { this.pointer.as_mut() }
}
#[inline(always)]
pub fn into_box(this: Self) -> Box<T> {
let pointer = this.pointer;
mem::forget(this);
unsafe { Box::from_raw(pointer.as_ptr()) }
}
}
impl<T: ?Sized, const NUM: usize, const DEN: usize> StaticRc<T, NUM, DEN> {
#[inline(always)]
pub fn into_raw(this: Self) -> NonNull<T> {
let pointer = this.pointer;
mem::forget(this);
pointer
}
#[inline(always)]
pub fn as_ptr(this: &Self) -> NonNull<T> { this.pointer }
#[inline(always)]
pub fn get_ref(this: &Self) -> &T {
unsafe { this.pointer.as_ref() }
}
#[inline(always)]
pub unsafe fn from_raw(pointer: NonNull<T>) -> Self
where
AssertLeType!(1, NUM): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
assert!(NUM > 0);
Self { pointer }
}
#[inline(always)]
pub fn ptr_eq<const N: usize, const D: usize>(this: &Self, other: &StaticRc<T, N, D>) -> bool {
StaticRc::as_ptr(this) == StaticRc::as_ptr(other)
}
#[inline(always)]
pub fn adjust<const N: usize, const D: usize>(this: Self) -> StaticRc<T, N, D>
where
AssertLeType!(1, N): Sized,
AssertEqType!(N * DEN, NUM * D): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
{
assert!(N > 0);
assert_eq!(NUM * D, N * DEN, "{} / {} != {} / {}", NUM, DEN, N, D);
}
let pointer = this.pointer;
mem::forget(this);
StaticRc { pointer }
}
#[inline(always)]
pub fn as_rcref<'a>(this: &'a mut Self) -> super::StaticRcRef<'a, T, NUM, DEN>
where
AssertLeType!(1, NUM): Sized,
{
let ptr = this.pointer;
unsafe {
super::StaticRcRef::from_raw(ptr)
}
}
#[inline(always)]
pub fn split<const A: usize, const B: usize>(this: Self) -> (StaticRc<T, A, DEN>, StaticRc<T, B, DEN>)
where
AssertLeType!(1, A): Sized,
AssertLeType!(1, B): Sized,
AssertEqType!(A + B, NUM): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
{
assert!(A > 0);
assert!(B > 0);
assert_eq!(NUM, A + B, "{} != {} + {}", NUM, A, B);
}
let pointer = this.pointer;
mem::forget(this);
(StaticRc { pointer }, StaticRc { pointer })
}
#[inline(always)]
pub fn split_array<const N: usize, const DIM: usize>(this: Self) -> [StaticRc<T, N, DEN>; DIM]
where
AssertEqType!(N * DIM, NUM ): Sized,
AssertLeType!(mem::size_of::<[StaticRc<T, N, DEN>; DIM]>(), usize::MAX / 2 + 1): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
assert_eq!(NUM, N * DIM, "{} != {} * {}", NUM, N, DIM);
#[cfg(not(feature = "compile-time-ratio"))]
assert!(mem::size_of::<[StaticRc<T, N, DEN>; DIM]>() <= (isize::MAX as usize),
"Size of result ({}) exceeeds isize::MAX", mem::size_of::<[StaticRc<T, N, DEN>; DIM]>());
let pointer = this.pointer;
mem::forget(this);
let mut array = MaybeUninit::uninit();
for i in 0..DIM {
let destination = unsafe { (array.as_mut_ptr() as *mut StaticRc<T, N, DEN>).add(i) };
unsafe { ptr::write(destination, StaticRc { pointer }); }
}
unsafe { array.assume_init() }
}
#[inline(always)]
pub fn join<const A: usize, const B: usize>(left: StaticRc<T, A, DEN>, right: StaticRc<T, B, DEN>) -> Self
where
AssertEqType!(NUM, A + B): Sized,
{
let (left, right) = Self::validate_pair(left, right);
unsafe { Self::join_impl(left, right) }
}
#[inline(always)]
pub unsafe fn join_unchecked<const A: usize, const B: usize>(
left: StaticRc<T, A, DEN>,
right: StaticRc<T, B, DEN>,
) -> Self
where
AssertEqType!(NUM, A + B): Sized,
{
#[cfg(debug_assertions)]
let (left, right) = Self::validate_pair(left, right);
Self::join_impl(left, right)
}
#[inline(always)]
pub fn join_array<const N: usize, const DIM: usize>(array: [StaticRc<T, N, DEN>; DIM]) -> Self
where
AssertLeType!(1, NUM): Sized,
AssertEqType!(N * DIM, NUM): Sized,
{
let array = Self::validate_array(array);
unsafe { Self::join_array_impl(array) }
}
#[inline(always)]
pub unsafe fn join_array_unchecked<const N: usize, const DIM: usize>(array: [StaticRc<T, N, DEN>; DIM])
-> Self
where
AssertLeType!(1, NUM): Sized,
AssertEqType!(N * DIM, NUM): Sized,
{
#[cfg(debug_assertions)]
let array = Self::validate_array(array);
Self::join_array_impl(array)
}
#[inline(always)]
unsafe fn join_impl<const A: usize, const B: usize>(
left: StaticRc<T, A, DEN>,
right: StaticRc<T, B, DEN>,
) -> Self
where
AssertEqType!(NUM, A + B): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
if NUM != A + B {
mem::forget(left);
mem::forget(right);
panic!("{} != {} + {}", NUM, A, B);
}
let pointer = left.pointer;
mem::forget(left);
mem::forget(right);
Self { pointer }
}
#[inline(always)]
unsafe fn join_array_impl<const N: usize, const DIM: usize>(array: [StaticRc<T, N, DEN>; DIM])
-> Self
where
AssertLeType!(1, NUM): Sized,
AssertEqType!(N * DIM, NUM): Sized,
{
#[cfg(not(feature = "compile-time-ratio"))]
{
if NUM <= 0 {
mem::forget(array);
panic!("NUM <= 0");
}
if NUM != N * DIM {
mem::forget(array);
panic!("{} != {} * {}", NUM, N, DIM);
}
}
let pointer = array[0].pointer;
mem::forget(array);
Self { pointer, }
}
fn validate_pair<const A: usize, const B: usize>(left: StaticRc<T, A, DEN>, right: StaticRc<T, B, DEN>)
-> (StaticRc<T, A, DEN>, StaticRc<T, B, DEN>)
{
if StaticRc::ptr_eq(&left, &right) {
return (left, right);
}
let left = StaticRc::into_raw(left);
let right = StaticRc::into_raw(right);
panic!("Cannot join pair with multiple origins: {:?} != {:?}", left.as_ptr(), right.as_ptr());
}
fn validate_array<const N: usize, const DIM: usize>(array: [StaticRc<T, N, DEN>; DIM]) -> [StaticRc<T, N, DEN>; DIM] {
let first = &array[0];
let divergent = array[1..].iter().find(|e| !StaticRc::ptr_eq(&first, e));
if let Some(divergent) = divergent {
let first = first.pointer.as_ptr();
let divergent = divergent.pointer.as_ptr();
mem::forget(array);
panic!("Cannot join array with multiple origins: {:?} != {:?}", first, divergent);
}
array
}
}
impl<const NUM: usize, const DEN: usize> StaticRc<dyn any::Any, NUM, DEN> {
pub fn downcast<T: any::Any>(self) -> Result<StaticRc<T, NUM, DEN>, Self> {
if Self::get_ref(&self).is::<T>() {
let pointer = Self::into_raw(self).cast::<T>();
Ok(StaticRc { pointer })
} else {
Err(self)
}
}
}
impl<T: ?Sized, const NUM: usize, const DEN: usize> Drop for StaticRc<T, NUM, DEN> {
#[inline(always)]
fn drop(&mut self) {
debug_assert_eq!(NUM, DEN, "{} != {}", NUM, DEN);
if NUM == DEN {
unsafe { Box::from_raw(self.pointer.as_ptr()) };
}
}
}
impl<T: ?Sized, const N: usize> convert::AsMut<T> for StaticRc<T, N, N> {
#[inline(always)]
fn as_mut(&mut self) -> &mut T { Self::get_mut(self) }
}
impl<T: ?Sized, const NUM: usize, const DEN: usize> convert::AsRef<T> for StaticRc<T, NUM, DEN> {
#[inline(always)]
fn as_ref(&self) -> &T { Self::get_ref(self) }
}
impl<T: ?Sized, const NUM: usize, const DEN: usize> borrow::Borrow<T> for StaticRc<T, NUM, DEN> {
#[inline(always)]
fn borrow(&self) -> &T { Self::get_ref(self) }
}
impl<T: ?Sized, const N: usize> borrow::BorrowMut<T> for StaticRc<T, N, N> {
#[inline(always)]
fn borrow_mut(&mut self) -> &mut T { Self::get_mut(self) }
}
#[cfg(feature = "nightly-coerce-unsized")]
impl<T, U, const NUM: usize, const DEN: usize> CoerceUnsized<StaticRc<U, NUM, DEN>> for StaticRc<T, NUM, DEN>
where
T: ?Sized + marker::Unsize<U>,
U: ?Sized,
{}
impl<T: ?Sized + fmt::Debug, const NUM: usize, const DEN: usize> fmt::Debug for StaticRc<T, NUM, DEN> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
fmt::Debug::fmt(Self::get_ref(self), f)
}
}
impl<T: Default, const N: usize> Default for StaticRc<T, N, N>
where
AssertLeType!(1, N): Sized,
{
#[inline(always)]
fn default() -> Self { Self::new(T::default()) }
}
impl<T: ?Sized, const NUM: usize, const DEN: usize> ops::Deref for StaticRc<T, NUM, DEN> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T { Self::get_ref(self) }
}
impl<T: ?Sized, const N: usize> ops::DerefMut for StaticRc<T, N, N> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut T { Self::get_mut(self) }
}
impl<T: ?Sized + fmt::Display, const NUM: usize, const DEN: usize> fmt::Display for StaticRc<T, NUM, DEN> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
fmt::Display::fmt(Self::get_ref(self), f)
}
}
#[cfg(feature = "nightly-dispatch-from-dyn")]
impl<T, U, const NUM: usize, const DEN: usize> DispatchFromDyn<StaticRc<U, NUM, DEN>> for StaticRc<T, NUM, DEN>
where
T: ?Sized + marker::Unsize<U>,
U: ?Sized,
{}
impl<I: iter::DoubleEndedIterator + ?Sized, const N: usize> iter::DoubleEndedIterator for StaticRc<I, N, N> {
#[inline(always)]
fn next_back(&mut self) -> Option<I::Item> { Self::get_mut(self).next_back() }
#[inline(always)]
fn nth_back(&mut self, n: usize) -> Option<I::Item> { Self::get_mut(self).nth_back(n) }
}
impl<T: ?Sized + cmp::Eq, const NUM: usize, const DEN: usize> cmp::Eq for StaticRc<T, NUM, DEN> {}
impl<I: iter::ExactSizeIterator + ?Sized, const N: usize> iter::ExactSizeIterator for StaticRc<I, N, N> {
#[inline(always)]
fn len(&self) -> usize { Self::get_ref(self).len() }
}
impl<T: ?Sized, const N: usize> From<Box<T>> for StaticRc<T, N, N> {
#[inline(always)]
fn from(value: Box<T>) -> Self {
let pointer = NonNull::from(Box::leak(value));
Self { pointer }
}
}
impl<T: Copy, const N: usize> From<&'_ [T]> for StaticRc<[T], N, N> {
#[inline(always)]
fn from(value: &[T]) -> Self { Self::from(Box::from(value)) }
}
impl<const N: usize> From<&'_ str> for StaticRc<str, N, N> {
#[inline(always)]
fn from(value: &str) -> Self { Self::from(Box::from(value)) }
}
impl<T, const LEN: usize, const N: usize> From<[T; LEN]> for StaticRc<[T], N, N> {
#[inline(always)]
fn from(value: [T; LEN]) -> Self { Self::from(Box::from(value)) }
}
impl<T: Copy, const N: usize> From<alloc::borrow::Cow<'_, [T]>> for StaticRc<[T], N, N> {
#[inline(always)]
fn from(value: alloc::borrow::Cow<'_, [T]>) -> Self { Self::from(Box::from(value)) }
}
impl<const N: usize> From<alloc::borrow::Cow<'_, str>> for StaticRc<str, N, N> {
#[inline(always)]
fn from(value: alloc::borrow::Cow<'_, str>) -> Self { Self::from(Box::from(value)) }
}
impl<const N: usize> From<alloc::string::String> for StaticRc<str, N, N> {
#[inline(always)]
fn from(value: alloc::string::String) -> Self { Self::from(Box::from(value)) }
}
impl<T, const N: usize> From<T> for StaticRc<T, N, N> {
#[inline(always)]
fn from(value: T) -> Self { Self::from(Box::from(value)) }
}
impl<T, const N: usize> From<alloc::vec::Vec<T>> for StaticRc<[T], N, N> {
#[inline(always)]
fn from(value: alloc::vec::Vec<T>) -> Self { Self::from(Box::from(value)) }
}
impl<T, const N: usize> From<StaticRc<[T], N, N>> for alloc::vec::Vec<T> {
#[inline(always)]
fn from(value: StaticRc<[T], N, N>) -> Self { Self::from(StaticRc::into_box(value)) }
}
impl<T: ?Sized, const N: usize> From<StaticRc<T, N, N>> for alloc::rc::Rc<T> {
#[inline(always)]
fn from(value: StaticRc<T, N, N>) -> Self { Self::from(StaticRc::into_box(value)) }
}
impl<T: ?Sized, const N: usize> From<StaticRc<T, N, N>> for alloc::sync::Arc<T> {
#[inline(always)]
fn from(value: StaticRc<T, N, N>) -> Self { Self::from(StaticRc::into_box(value)) }
}
impl<const N: usize> From<StaticRc<str, N, N>> for alloc::string::String {
#[inline(always)]
fn from(value: StaticRc<str, N, N>) -> Self { Self::from(StaticRc::into_box(value)) }
}
impl<const NUM: usize, const DEN: usize> From<StaticRc<str, NUM, DEN>> for StaticRc<[u8], NUM, DEN> {
#[inline(always)]
fn from(value: StaticRc<str, NUM, DEN>) -> Self {
let pointer = value.pointer.as_ptr() as *mut [u8];
mem::forget(value);
debug_assert!(!pointer.is_null());
let pointer = unsafe { NonNull::new_unchecked(pointer) };
Self { pointer }
}
}
impl<const N: usize> iter::FromIterator<StaticRc<str, N, N>> for alloc::string::String {
#[inline(always)]
fn from_iter<I: IntoIterator<Item = StaticRc<str, N, N>>>(iter: I) -> Self {
Self::from_iter(iter.into_iter().map(StaticRc::into_box))
}
}
impl<T, const N: usize> iter::FromIterator<T> for StaticRc<[T], N, N> {
#[inline(always)]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { Self::from(Box::from_iter(iter)) }
}
impl<I: iter::FusedIterator + ?Sized, const N: usize> iter::FusedIterator for StaticRc<I, N, N> {}
impl<F: ?Sized + future::Future + marker::Unpin, const N: usize> future::Future for StaticRc<F, N, N> {
type Output = F::Output;
fn poll(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
F::poll(pin::Pin::new(&mut *self), cx)
}
}
#[cfg(feature = "nightly-generator-trait")]
impl<G: ?Sized + ops::Generator<R> + marker::Unpin, R, const N: usize> ops::Generator<R> for StaticRc<G, N, N> {
type Yield = G::Yield;
type Return = G::Return;
fn resume(mut self: pin::Pin<&mut Self>, arg: R) -> ops::GeneratorState<Self::Yield, Self::Return> {
G::resume(pin::Pin::new(&mut *self), arg)
}
}
#[cfg(feature = "nightly-generator-trait")]
impl<G: ?Sized + ops::Generator<R>, R, const N: usize> ops::Generator<R> for pin::Pin<StaticRc<G, N, N>> {
type Yield = G::Yield;
type Return = G::Return;
fn resume(mut self: pin::Pin<&mut Self>, arg: R) -> ops::GeneratorState<Self::Yield, Self::Return> {
G::resume((*self).as_mut(), arg)
}
}
impl<T: ?Sized + hash::Hash, const NUM: usize, const DEN: usize> hash::Hash for StaticRc<T, NUM, DEN> {
#[inline(always)]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
Self::get_ref(self).hash(state);
}
}
impl<I: iter::Iterator + ?Sized, const N: usize> iter::Iterator for StaticRc<I, N, N> {
type Item = I::Item;
#[inline(always)]
fn next(&mut self) -> Option<I::Item> { Self::get_mut(self).next() }
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) { Self::get_ref(self).size_hint() }
#[inline(always)]
fn nth(&mut self, n: usize) -> Option<I::Item> { Self::get_mut(self).nth(n) }
#[inline(always)]
fn last(self) -> Option<I::Item> { Self::into_box(self).last() }
}
impl<T: ?Sized + cmp::Ord, const NUM: usize, const DEN: usize> cmp::Ord for StaticRc<T, NUM, DEN> {
#[inline(always)]
fn cmp(&self, other: &Self) -> cmp::Ordering {
if Self::ptr_eq(self, other) {
cmp::Ordering::Equal
} else {
Self::get_ref(self).cmp(Self::get_ref(other))
}
}
}
impl<T, const NUM: usize, const DEN: usize, const N: usize, const D: usize> cmp::PartialEq<StaticRc<T, N, D>>
for StaticRc<T, NUM, DEN>
where
T: ?Sized + PartialEq<T>
{
#[inline(always)]
fn eq(&self, other: &StaticRc<T, N, D>) -> bool { Self::get_ref(self).eq(StaticRc::get_ref(other)) }
#[inline(always)]
fn ne(&self, other: &StaticRc<T, N, D>) -> bool { Self::get_ref(self).ne(StaticRc::get_ref(other)) }
}
impl<T, const NUM: usize, const DEN: usize, const N: usize, const D: usize> cmp::PartialOrd<StaticRc<T, N, D>>
for StaticRc<T, NUM, DEN>
where
T: ?Sized + PartialOrd<T>
{
#[inline(always)]
fn partial_cmp(&self, other: &StaticRc<T, N, D>) -> Option<cmp::Ordering> {
Self::get_ref(self).partial_cmp(StaticRc::get_ref(other))
}
#[inline(always)]
fn lt(&self, other: &StaticRc<T, N, D>) -> bool {
Self::get_ref(self).lt(StaticRc::get_ref(other))
}
#[inline(always)]
fn le(&self, other: &StaticRc<T, N, D>) -> bool {
Self::get_ref(self).le(StaticRc::get_ref(other))
}
#[inline(always)]
fn gt(&self, other: &StaticRc<T, N, D>) -> bool {
Self::get_ref(self).gt(StaticRc::get_ref(other))
}
#[inline(always)]
fn ge(&self, other: &StaticRc<T, N, D>) -> bool {
Self::get_ref(self).ge(StaticRc::get_ref(other))
}
}
impl<T: ?Sized, const NUM: usize, const DEN: usize> fmt::Pointer for StaticRc<T, NUM, DEN> {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&Self::as_ptr(self).as_ptr(), f)
}
}
#[cfg(feature = "nightly-async-iterator")]
impl<S: ?Sized + async_iter::AsyncIterator + marker::Unpin, const N: usize> async_iter::AsyncIterator for StaticRc<S, N, N> {
type Item = S::Item;
fn poll_next(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Option<Self::Item>> {
pin::Pin::new(&mut **self).poll_next(cx)
}
fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
}
impl<T: ?Sized, const NUM: usize, const DEN: usize> marker::Unpin for StaticRc<T, NUM, DEN> {}
unsafe impl<T: ?Sized + marker::Send, const NUM: usize, const DEN: usize> marker::Send for StaticRc<T, NUM, DEN> {}
unsafe impl<T: ?Sized + marker::Sync, const NUM: usize, const DEN: usize> marker::Sync for StaticRc<T, NUM, DEN> {}
#[doc(hidden)]
pub mod compile_tests {
pub fn rc_reborrow_and_move() {}
pub fn rc_reborrow_and_use() {}
}
#[doc(hidden)]
#[cfg(feature = "compile-time-ratio")]
pub mod compile_ratio_tests {
pub fn rc_new_zero() {}
pub fn rc_pin_zero() {}
pub fn rc_from_raw_zero() {}
pub fn rc_adjust_zero() {}
pub fn rc_adjust_ratio() {}
pub fn rc_split_zero_first() {}
pub fn rc_split_zero_second() {}
pub fn rc_split_sum() {}
pub fn rc_split_array_ratio() {}
pub fn rc_join_ratio() {}
pub fn rc_join_unchecked_ratio() {}
pub fn rc_join_array_ratio() {}
pub fn rc_join_array_unchecked_ratio() {}
}
#[cfg(all(test, not(feature = "compile-time-ratio")))]
mod panic_ratio_tests {
use super::*;
type Zero = StaticRc<i32, 0, 0>;
type One = StaticRc<i32, 1, 1>;
type Two = StaticRc<i32, 2, 2>;
#[test]
#[should_panic]
fn rc_new_zero() {
Zero::new(42);
}
#[test]
#[should_panic]
fn rc_pin_zero() {
Zero::pin(42);
}
#[test]
#[should_panic]
fn rc_from_raw_zero() {
let pointer = NonNull::dangling();
unsafe { Zero::from_raw(pointer) };
}
#[test]
#[should_panic]
fn rc_adjust_zero() {
let rc = One::new(42);
One::adjust::<0, 0>(rc);
}
#[test]
#[should_panic]
fn rc_adjust_ratio() {
let rc = One::new(42);
One::adjust::<2, 3>(rc);
}
#[test]
#[should_panic]
fn rc_split_zero_first() {
let rc = Two::new(42);
Two::split::<0, 2>(rc);
}
#[test]
#[should_panic]
fn rc_split_zero_second() {
let rc = Two::new(42);
Two::split::<0, 2>(rc);
}
#[test]
#[should_panic]
fn rc_split_sum() {
let rc = Two::new(42);
Two::split::<1, 2>(rc);
}
#[test]
#[should_panic]
fn rc_split_array_ratio() {
let rc = Two::new(42);
Two::split_array::<2, 2>(rc);
}
#[test]
#[should_panic]
fn rc_join_ratio() {
let rc = Two::new(42);
will_leak(&rc);
let (one, two) = Two::split::<1, 1>(rc);
StaticRc::<_, 1, 2>::join(one, two);
}
#[test]
#[should_panic]
fn rc_join_different() {
let (rc, other) = (Two::new(42), Two::new(33));
will_leak(&rc);
will_leak(&other);
let (one, two) = Two::split::<1, 1>(rc);
let (other_one, other_two) = Two::split::<1, 1>(other);
mem::forget([two, other_two]);
Two::join(one, other_one);
}
#[test]
#[should_panic]
fn rc_join_unchecked_ratio() {
let rc = Two::new(42);
will_leak(&rc);
let (one, two) = Two::split::<1, 1>(rc);
unsafe { StaticRc::<_, 1, 2>::join_unchecked(one, two) };
}
#[test]
#[should_panic]
fn rc_join_array_ratio() {
let rc = Two::new(42);
will_leak(&rc);
let array: [_; 2] = Two::split_array::<1, 2>(rc);
StaticRc::<_, 1, 2>::join_array(array);
}
#[test]
#[should_panic]
fn rc_join_array_different() {
let (rc, other) = (Two::new(42), Two::new(33));
will_leak(&rc);
will_leak(&other);
let (one, two) = Two::split::<1, 1>(rc);
let (other_one, other_two) = Two::split::<1, 1>(other);
mem::forget([two, other_two]);
Two::join_array([one, other_one]);
}
#[test]
#[should_panic]
fn rc_join_array_unchecked_ratio() {
let rc = Two::new(42);
will_leak(&rc);
let array = Two::split_array::<1, 2>(rc);
unsafe { StaticRc::<_, 1, 2>::join_array_unchecked(array) };
}
fn will_leak<T, const NUM: usize, const DEN: usize>(_rc: &StaticRc<T, NUM, DEN>) {
#[cfg(miri)]
{
unsafe { miri_static_root(StaticRc::as_ptr(_rc).as_ptr() as *const u8) };
}
}
#[cfg(miri)]
extern "Rust" {
fn miri_static_root(ptr: *const u8);
}
}