macro_rules! drop_may_dangle {
(unsafe impl<#[may_dangle] $primary:ident: ?Sized + $primary_bound:ident, $alloc:ident: $alloc_bound:ident> Drop for $target:path {
$($inner:tt)*
}) => {
#[cfg(feature = "nightly-may-dangle")]
unsafe impl<#[may_dangle] $primary: ?Sized + $primary_bound, $alloc: $alloc_bound> Drop for $target {
$($inner)*
}
#[cfg(not(feature = "nightly-may-dangle"))]
impl<$primary: ?Sized + $primary_bound, $alloc: $alloc_bound> Drop for $target {
$($inner)*
}
};
}
macro_rules! smart_pointer {
(unsafe impl<$primary:ident: ?Sized + $primary_bound:ident, $alloc:ident: Allocator> SmartPointerBasics for $pointer:ident {}) => {
impl<$primary: ?Sized + $primary_bound, $alloc: Allocator> core::marker::Unpin for $pointer<$primary, $alloc> {}
unsafe impl<$primary, U: ?Sized + $primary_bound, $alloc: Allocator> unsize::CoerciblePtr<U> for $pointer<$primary, $alloc> {
type Pointee = $primary;
type Output = $pointer<U, $alloc>;
#[inline]
fn as_sized_ptr(&mut self) -> *mut Self::Pointee {
$pointer::as_ptr(&*self).cast_mut()
}
#[inline]
unsafe fn replace_ptr(self, new: *mut U) -> Self::Output {
let raw = $pointer::into_raw(self).cast_mut();
let new: *mut U = unsafe { <*mut T as unsize::CoerciblePtr<U>>::replace_ptr(raw, new) };
unsafe { $pointer::from_raw(new) }
}
}
#[cfg(feature = "nightly-coerce")]
impl<$primary: ?Sized, U: ?Sized, $alloc: Allocator> core::ops::CoerceUnsized<$pointer<U, A>> for $pointer<$primary, $alloc>
where
$primary: core::marker::Unsize<U> + $primary_bound,
U: $primary_bound,
{
}
#[doc = concat!("A [`", stringify!($pointer), "`] is just a [`NonNull`] pointer, so `Option<Self>` can be safely zero-initialized")]
unsafe impl<T> bytemuck::ZeroableInOption for $pointer<T> {}
};
(unsafe impl<$primary:ident: ?Sized + $primary_bound:ident, $alloc:ident: Allocator> SmartPointer for $pointer:ident {}) => {
smart_pointer! {
unsafe impl<$primary: ?Sized + $primary_bound, $alloc: Allocator> SmartPointerBasics for $pointer {}
}
impl<$primary: ?Sized + $primary_bound + core::error::Error, $alloc: Allocator> core::error::Error for $pointer<$primary, $alloc> {
#[inline]
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
self.deref().source()
}
#[allow(deprecated, reason = "delegate")]
#[inline]
fn description(&self) -> &str {
self.deref().description()
}
#[allow(deprecated, reason = "delegate")]
#[inline]
fn cause(&self) -> Option<&dyn core::error::Error> {
self.deref().cause()
}
}
impl<$primary: ?Sized + $primary_bound, $alloc: Allocator> core::borrow::Borrow<$primary> for $pointer<$primary, $alloc> {
#[inline]
fn borrow(&self) -> &T {
self.deref()
}
}
impl<$primary: ?Sized + $primary_bound, $alloc: Allocator> AsRef<$primary> for $pointer<$primary, $alloc> {
#[inline]
fn as_ref(&self) -> &T {
self.deref()
}
}
impl<$primary: ?Sized + $primary_bound + core::fmt::Debug, $alloc: Allocator> core::fmt::Debug for $pointer<$primary, $alloc> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(self.deref(), f)
}
}
impl<$primary: ?Sized + $primary_bound + core::fmt::Display, $alloc: Allocator> core::fmt::Display for $pointer<$primary, $alloc> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Display::fmt(self.deref(), f)
}
}
#[warn(clippy::missing_trait_methods)]
#[allow(clippy::partialeq_ne_impl, reason = "smart pointer should delegate")]
impl<$primary: ?Sized + $primary_bound + PartialEq, $alloc: Allocator> PartialEq for $pointer<$primary, $alloc> {
smart_pointer!(@delegate_cmp_ops eq, ne);
}
impl<$primary: ?Sized + $primary_bound + PartialOrd, $alloc: Allocator> PartialOrd for $pointer<$primary, $alloc> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.deref().partial_cmp(other.deref())
}
smart_pointer!(@delegate_cmp_ops lt, gt, le, ge);
}
impl<$primary: ?Sized + $primary_bound + Ord, $alloc: Allocator> Ord for $pointer<$primary, $alloc> {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.deref().cmp(other.deref())
}
}
impl<$primary: ?Sized + $primary_bound + core::hash::Hash, $alloc: Allocator> core::hash::Hash for $pointer<$primary, $alloc> {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state);
}
}
impl<$primary: ?Sized + $primary_bound + Eq, $alloc: Allocator> Eq for $pointer<$primary, $alloc> {}
unsafe impl<$primary: ?Sized + $primary_bound, $alloc: Allocator> stable_deref_trait::StableDeref for $pointer<$primary, $alloc> {}
};
(@delegate_cmp_ops $($name:ident),+ $(,)?) => {
$(#[inline]
fn $name(&self, other: &Self) -> bool {
self.deref().$name(other.deref())
})*
};
}