pedant_types/resolution/handle.rs
1//! Builder-scoped provenance for records that have no identifier yet.
2//!
3//! A report's identifiers are assigned by `finish`, after sorting, so a writer
4//! needs some other way to point at a record it already added. Two builders can
5//! both issue local index zero, so the index alone would let a handle from one
6//! builder silently name a different record in another. Each builder owns one
7//! zero-sized brand behind an `Arc`, and every handle carries a clone of it:
8//! pointer identity gives provenance without a global counter, without
9//! process-local state in the serialized report, and without a panic path.
10
11use std::marker::PhantomData;
12use std::sync::Arc;
13
14use super::record::ResolutionCertainty;
15
16/// One builder's identity. Zero-sized: only the allocation address matters.
17#[derive(Debug)]
18pub(crate) struct BuilderBrand;
19
20/// A local insertion index plus the brand and record kind that issued it.
21#[derive(Clone, Debug)]
22pub struct Handle<K> {
23 brand: Arc<BuilderBrand>,
24 index: u32,
25 kind: PhantomData<fn() -> K>,
26}
27
28impl<K> Handle<K> {
29 pub(crate) fn new(brand: &Arc<BuilderBrand>, index: u32) -> Self {
30 Self {
31 brand: Arc::clone(brand),
32 index,
33 kind: PhantomData,
34 }
35 }
36
37 /// The local index, if `brand` is the builder that issued this handle.
38 pub(crate) fn resolve(&self, brand: &Arc<BuilderBrand>) -> Option<u32> {
39 Arc::ptr_eq(&self.brand, brand).then_some(self.index)
40 }
41}
42
43/// Marker distinguishing unit handles from the other handle kinds.
44#[derive(Clone, Debug)]
45pub struct UnitHandleKind;
46
47/// Marker distinguishing definition handles from the other handle kinds.
48#[derive(Clone, Debug)]
49pub struct DefinitionHandleKind;
50
51/// Marker distinguishing reference handles from the other handle kinds.
52#[derive(Clone, Debug)]
53pub struct ReferenceHandleKind;
54
55/// A unit a builder holds. Clone, never `Copy`, and never serialized.
56pub type ResolutionUnitHandle = Handle<UnitHandleKind>;
57
58/// A definition a builder holds. Clone, never `Copy`, and never serialized.
59pub type DefinitionHandle = Handle<DefinitionHandleKind>;
60
61/// A reference a builder holds. Clone, never `Copy`, and never serialized.
62pub type ReferenceHandle = Handle<ReferenceHandleKind>;
63
64/// One candidate a writer offers for a reference.
65///
66/// The only way to name a candidate, so a candidate cannot reach a report
67/// without passing the same brand check every other handle does.
68#[derive(Clone, Debug)]
69pub struct CandidateInput {
70 definition: DefinitionHandle,
71 certainty: ResolutionCertainty,
72}
73
74impl CandidateInput {
75 /// A candidate definition and how much it is known.
76 pub fn new(definition: DefinitionHandle, certainty: ResolutionCertainty) -> Self {
77 Self {
78 definition,
79 certainty,
80 }
81 }
82
83 /// The handle and its certainty, consuming the input.
84 ///
85 /// By value because the builder takes the stated candidates by value: a
86 /// borrowing accessor would leave the boxed slice owned but never moved.
87 pub(crate) fn into_parts(self) -> (DefinitionHandle, ResolutionCertainty) {
88 (self.definition, self.certainty)
89 }
90}