Skip to main content

sefer_region/
handle.rs

1//! [`Handle`] — the typed, copyable reference to a value in a [`Region`].
2//!
3//! [`Region`]: crate::Region
4
5use core::marker::PhantomData;
6
7/// An opaque, copyable reference to a value stored in a [`Region`].
8///
9/// A handle wraps a `slotmap::DefaultKey` (an index plus a generation) and is
10/// `Copy` and unconditionally `Send + Sync` regardless of `T` — it owns no `T`,
11/// it only names one. The `PhantomData<fn() -> T>` keeps the handle *typed* (so
12/// a `Handle<A>` cannot be passed to a `Region<B>`) while staying covariant in
13/// `T` and free of any drop/auto-trait obligations.
14///
15/// [`Region`]: crate::Region
16pub struct Handle<T> {
17    /// Crate-visible so [`Region`](crate::Region) can build and read a handle,
18    /// never exposed publicly.
19    pub(crate) key: slotmap::DefaultKey,
20    _ty: PhantomData<fn() -> T>,
21}
22
23impl<T> Handle<T> {
24    /// Crate-internal constructor wrapping a raw slotmap key.
25    pub(crate) fn from_key(key: slotmap::DefaultKey) -> Self {
26        Self {
27            key,
28            _ty: PhantomData,
29        }
30    }
31}
32
33// Hand-written impls: a handle is "a slotmap key", so these must hold for
34// *every* `T`, not only `T: Clone`/`Eq`/… that `#[derive]` would (wrongly)
35// require. They delegate to the inner `key` and hold unconditionally in `T`.
36impl<T> Clone for Handle<T> {
37    fn clone(&self) -> Self {
38        *self
39    }
40}
41impl<T> Copy for Handle<T> {}
42impl<T> PartialEq for Handle<T> {
43    fn eq(&self, other: &Self) -> bool {
44        self.key == other.key
45    }
46}
47impl<T> Eq for Handle<T> {}
48impl<T> core::hash::Hash for Handle<T> {
49    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
50        self.key.hash(state);
51    }
52}
53impl<T> core::fmt::Debug for Handle<T> {
54    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55        f.debug_struct("Handle").field("key", &self.key).finish()
56    }
57}