macroonz_compiler/host/type_guard.rs
1//! The host's invariant nucleus: every road that reaches the span custody's private seat.
2//!
3//! Declared inside `types.rs` as its own child, so the held spans are reachable here and nowhere else.
4//! Handles are issued in reading order and never reused, which is the whole invariant: a handle answers about the token it was issued for, or the table says it does not reach.
5
6use super::Spans;
7use crate::token::{CaptureBuilder, SpanHandle, SpanResolutionRefusal};
8use proc_macro::Span;
9
10impl Spans {
11 /// A table that has issued nothing.
12 #[must_use]
13 pub const fn empty() -> Self {
14 Self {
15 builder: CaptureBuilder::declared(),
16 }
17 }
18
19 /// The checked builder that owns this table's handles and positions.
20 pub(crate) const fn builder(&mut self) -> &mut CaptureBuilder<Span> {
21 &mut self.builder
22 }
23
24 /// The compiler span one handle names, or the invocation where this table does not reach it.
25 ///
26 /// One lookup for every road that holds a handle, so a diagnostic the compiler composed and a capture this host refused point at their token the same way.
27 /// Where the table does not reach, the invocation stands — never the declaration's first span, which is a real token the observation is not about and would read exactly like an answer.
28 #[must_use]
29 pub fn at(&self, handle: SpanHandle) -> Span {
30 self.resolve(handle).unwrap_or_else(|_| Span::call_site())
31 }
32
33 /// Resolve one preserved source handle for host emission without inventing a fallback span.
34 pub(crate) fn resolve(&self, handle: SpanHandle) -> Result<Span, SpanResolutionRefusal> {
35 usize::try_from(handle.index())
36 .ok()
37 .and_then(|index| self.builder.positions().get(index).copied())
38 .ok_or(SpanResolutionRefusal {
39 handle,
40 reaches: self.builder.positions().len(),
41 })
42 }
43}