Skip to content

Instantly share code, notes, and snippets.

@eira-fransham
Last active April 27, 2026 10:08
Show Gist options
  • Select an option

  • Save eira-fransham/3e5337c1ee51a7e1fcdf4f36c68fe2d2 to your computer and use it in GitHub Desktop.

Select an option

Save eira-fransham/3e5337c1ee51a7e1fcdf4f36c68fe2d2 to your computer and use it in GitHub Desktop.
A version of `Rc<T>` which doesn't allocate for ZSTs and has less memory overhead.
use std::{
any::Any,
cell::Cell,
mem,
num::NonZero,
ops::Deref,
ptr::NonNull,
};
struct OptRcInner<T: ?Sized> {
refcount: Cell<NonZero<usize>>,
inner: T,
}
pub struct OptRc<T: ?Sized> {
// If `T` is a ZST, the top bit determines if the destructor
// should be called.
ptr: NonNull<OptRcInner<T>>,
}
const ZST_FLAG: usize = 1 << (usize::BITS - 1);
impl<T> OptRc<T> {
pub fn new(value: T) -> Self {
if mem::size_of::<T>() == 0 && !mem::needs_drop::<T>() {
Self {
ptr: NonNull::dangling()
.map_addr(|addr| unsafe { NonZero::new_unchecked(addr.get() | ZST_FLAG) }),
}
} else {
let ptr: NonNull<_> = Box::leak(Box::new(OptRcInner {
refcount: Cell::new(unsafe { NonZero::new_unchecked(1) }),
inner: value,
}))
.into();
assert_eq!(ptr.addr().get() & ZST_FLAG, 0);
Self { ptr }
}
}
pub fn into_any(self) -> OptRc<dyn Any>
where
T: 'static,
{
let this = mem::ManuallyDrop::new(self);
OptRc { ptr: this.ptr as _ }
}
}
impl<T: ?Sized> OptRc<T> {
fn no_drop_zst(&self) -> bool {
self.ptr.addr().get() & ZST_FLAG != 0
}
}
impl<T: ?Sized> Clone for OptRc<T> {
fn clone(&self) -> Self {
if self.no_drop_zst() {
Self { ptr: self.ptr }
} else {
unsafe {
self.ptr.as_ref().refcount.update(|count| {
NonZero::new_unchecked(
count.get().checked_add(1).expect("Rc refcount overflow"),
)
})
};
Self { ptr: self.ptr }
}
}
}
impl<T: ?Sized> Drop for OptRc<T> {
fn drop(&mut self) {
if self.no_drop_zst() {
return;
}
if unsafe { self.ptr.as_ref().refcount.get().get() == 1 } {
let _ = unsafe { Box::from_raw(self.ptr.as_ptr()) };
} else {
unsafe {
self.ptr
.as_ref()
.refcount
.update(|val| NonZero::new_unchecked(val.get() - 1))
}
}
}
}
impl<T: ?Sized> Deref for OptRc<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &self.ptr.as_ref().inner }
}
}
fn main() {
struct Foo;
let foo = OptRc::new(Foo).into_any();
let bar = foo.clone();
let _baz = bar.clone();
let _qux = foo.clone();
assert!(foo.no_drop_zst());
struct FooDrop;
impl Drop for FooDrop {
fn drop(&mut self) {
println!("Hello, world!");
}
}
let foo = OptRc::new(FooDrop).into_any();
let bar = foo.clone();
let _baz = bar.clone();
let _qux = foo.clone();
assert!(!foo.no_drop_zst());
struct FooSized(&'static str);
impl Drop for FooSized {
fn drop(&mut self) {
println!("{}", self.0);
}
}
let foo = OptRc::new(FooSized("Goodbye, world!")).into_any();
let bar = foo.clone();
let _baz = bar.clone();
let _qux = foo.clone();
assert!(!foo.no_drop_zst());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment