1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! [`Handle`] — the typed, copyable reference to a value in a [`Region`].
//!
//! [`Region`]: crate::Region
use PhantomData;
use NonZeroUsize;
/// An opaque, copyable reference to a value stored in a [`Region`].
///
/// A handle wraps a `slotmap::DefaultKey` (an index plus a generation) and a
/// `region_id` that identifies which `Region` instance the handle belongs to.
/// It is `Copy` and unconditionally `Send + Sync` regardless of `T` — it owns
/// no `T`, it only names one. The `PhantomData<fn() -> T>` keeps the handle
/// *typed* (so a `Handle<A>` cannot be passed to a `Region<B>`) while staying
/// covariant in `T` and free of any drop/auto-trait obligations.
///
/// The `region_id: NonZeroUsize` field ensures that handles from different
/// `Region` instances never collide even if they have the same `key`. Using
/// `NonZeroUsize` preserves the niche optimization for `Option<Handle<T>>`.
/// `region_id` is pointer-width (not a fixed 64 bits) so this type stays
/// buildable on no_std targets without 64-bit atomics (e.g.
/// `thumbv7em-none-eabi`, `i686-*`) — every such target
/// still has pointer-width atomics.
///
/// ## Layout is an observed property, not a guarantee
///
/// This crate does not use `#[repr(C)]`/`#[repr(transparent)]` here — there is
/// no FFI or C-ABI use case for `Handle<T>`, and one would be misleading
/// regardless: the inner `slotmap::DefaultKey` is itself not `#[repr(C)]`
/// upstream, so pinning only the outer field order would not yield an actual
/// stable C layout. `size_of::<Handle<T>>()` (16 bytes on a 64-bit host, 12 on
/// 32-bit) and the `Option<Handle<T>>` niche optimization are *current,
/// observed* properties of this implementation, verified by
/// `tests/handle_static_asserts.rs` — a tripwire against silent drift (e.g. a
/// future `slotmap` minor bump changing `DefaultKey`'s size), not a stable
/// public contract. If a genuine FFI need arises, the crate would add an
/// explicit `to_raw`/`from_raw` conversion pair rather than promise this
/// struct's layout.
///
/// [`Region`]: crate::Region
// Hand-written impls: a handle's identity is the pair `(region_id, key)`, so these
// impls must hold for *every* `T`, not only `T: Clone`/`Eq`/… that `#[derive]` would
// (wrongly) require. They delegate to the inner fields and hold unconditionally in `T`.
// Comparison order: first by `region_id`, then by `key`.
//
// This is a deliberate design choice (not a `Hash`-impl-parity default —
// field order in `Hash` has no bearing on `Ord`/`Eq` consistency, and any
// order here is equally valid for that purpose): ordering by `region_id`
// first means handles group by their owning `Region` under `sort()` /
// inside a `BTreeMap<Handle<T>, V>` / `BTreeSet<Handle<T>>`, so a caller
// holding handles from several `Region`s can range-scan just one Region's
// slice contiguously (e.g. `handles.sort()` then `.partition_point(..)` /
// a `BTreeMap` range bounded by that Region's own handles). Ordering by
// `key` first (the alternative) would instead interleave handles from
// different Regions whenever their raw `DefaultKey`s happen to compare
// close together — which is common, since the first insert into any fresh
// `Region` tends to produce the same key — defeating exactly the grouping
// a `BTreeMap`/sorted-`Vec` user would reasonably want.
//
// Handles from different regions (different `region_id`) will never
// compare equal per `PartialEq`, but they still have a consistent total
// order — useful for sorting/`BTreeMap` even though `HashMap` is the more
// common use case.
/// `Ord`/`PartialOrd` provide a total order consistent with [`Eq`], suitable
/// for storing `Handle<T>` in a `BTreeMap`/`BTreeSet` or sorting a `Vec` of
/// them. The *relative* order between two particular handles — including
/// whether handles from different [`Region`](crate::Region)s group together
/// or interleave — is an unspecified implementation detail (currently:
/// group by `region_id`, tie-break by `key`) and may change in any release.
/// Do not depend on it for anything beyond "a total order exists".