///|
struct Rc[T] {
  finalizer : Finalizer
  value : Ref[T?]
}

///|
pub fn[T] Rc::new(value : T) -> Rc[T] {
  let value = Ref::new(Some(value))
  let finalizer = Finalizer::new(() => value.val = None)
  Rc::{ finalizer, value }
}

///|
pub fn[T] Rc::get(self : Rc[T]) -> T {
  let value = self.value.val.unwrap()
  ignore(self.finalizer)
  value
}

///|
struct Weak[T](Ref[T?])

///|
pub fn[T] Weak::new(rc : Rc[T]) -> Weak[T] {
  Weak(rc.value)
}

///|
pub fn[T] Weak::get(self : Weak[T]) -> T? {
  self.val
}