Skip to main content

macroonz_compiler/closure/
types.rs

1//! The closure home's declarations: the ways a rendering and its plan disagree, the refusal that carries them, the proof, and the emission that proof partitions.
2//!
3//! Declarations only.
4//! Every road that reaches a private field lives in `type_guard.rs`, this file's own child, which is what makes the home's central claim structural: a joined delivery is built inside a proof and exists nowhere else.
5
6use crate::bounded::Capped;
7use crate::identity::{self, ClosureId, Identity, OwnerIdentity, PlanId, Provenance};
8use crate::kind::{Destination, Role};
9use crate::plan::Membership;
10use crate::render::RenderedProjection;
11use crate::token::GeneratedTree;
12
13#[path = "type_guard.rs"]
14mod guard;
15
16/// Issues one closure refusal carries before it begins counting the rest.
17///
18/// Twice the outputs one plan may declare: at most one issue per planned seat, plus one per rendered unit nothing planned.
19pub const CLOSURE_ISSUE_LIMIT: usize = 64;
20
21/// The tokens one delivery carries, together with the digest of exactly those bytes.
22///
23/// The two arrive together because the digest is taken over the tree at the moment the tree is built, inside the proof.
24///
25/// # Construction
26///
27/// There is no public road to one: every value of this type is built by the partitioning inside [`Closure::proved`], which is why holding one means the bytes it carries were proved.
28#[must_use = "carried tokens are a delivery's bytes and the digest of exactly those bytes"]
29#[derive(Debug, Clone, PartialEq, Eq, Hash)]
30pub struct CarriedTokens {
31    tree: GeneratedTree,
32    digest: Identity<identity::OutputBytes>,
33}
34
35/// What one delivery carries.
36///
37/// "This delivery receives no cargo from this expansion" and "this delivery receives a cargo of no tokens" are answers to different questions, and an empty token tree would read exactly like the first.
38#[must_use = "a delivery either carries proved tokens or states that nothing was planned into it"]
39#[derive(Debug, Clone, PartialEq, Eq, Hash)]
40pub enum PartitionCargo {
41    /// The plan declared no member into this delivery.
42    NothingPlanned,
43    /// The members the plan declared into this delivery, joined in roster order, with the digest of exactly those bytes.
44    Carried(CarriedTokens),
45}
46
47/// Everything one proved rendering JOINS, split across the deliveries its seats declared.
48///
49/// # Authority
50///
51/// **The delivery roster is the quantifier**, exactly as the role roster is the quantifier for the membership proof: every joined delivery has a seat here, filled by walking the rendered units in ROSTER order and reading the delivery each unit's seat declares.
52///
53/// # Bounds
54///
55/// The publication delivery has no seat here, because artifacts are never joined: two artifacts are two addresses, and a published artifact IS its rendered unit at the address the plan named for it.
56#[must_use = "a partitioned emission is what one proved rendering delivers, split by delivery"]
57#[derive(Debug, Clone, PartialEq, Eq, Hash)]
58pub struct PartitionedEmission {
59    declaration_site: PartitionCargo,
60    test_carrier: PartitionCargo,
61    bench_carrier: PartitionCargo,
62}
63
64/// One way a rendering and the plan it claims to materialize disagree.
65///
66/// Every issue about a seat names it; the issues about the whole reconstruction name none, because there is no seat to name and electing one would be a stand-in nobody established.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum ClosureIssue<R: Role> {
69    /// A seat the plan declared was not rendered at all.
70    MemberMissing {
71        /// The planned seat nothing materialized.
72        role: R,
73    },
74    /// A seat was rendered that the plan never declared — the output firewall's own reversal.
75    MemberUnplanned {
76        /// The rendered seat nothing planned.
77        role: R,
78    },
79    /// One seat was rendered more than once.
80    MemberDuplicated {
81        /// The doubled seat.
82        role: R,
83        /// How many units stood under it.
84        observed: u32,
85    },
86    /// A rendered unit walks back to an origin the plan did not declare, which orphans it from the declaration it claims to project.
87    OriginOrphan {
88        /// The seat whose origin disagreed.
89        role: R,
90    },
91    /// The digest a rendered unit carries is not the digest of the bytes it actually carries, taken under the contract the plan stated.
92    DigestMismatch {
93        /// The seat whose digest disagreed.
94        role: R,
95    },
96    /// A unit stood under the planned seat and answered to a different semantic key: the right seat, filled by the wrong thing.
97    SemanticKeyMismatch {
98        /// The seat whose semantic key disagreed.
99        role: R,
100    },
101    /// A unit was rendered under a profile, or written to an address, the plan did not name.
102    ///
103    /// The delivery cannot disagree and is not checked: a delivery is the seat's own constant answer, so both sides read one value.
104    MaterializationMismatch {
105        /// The seat whose materialization disagreed.
106        role: R,
107    },
108    /// The plan itself declared one seat twice, independent of what was rendered.
109    ///
110    /// Two members under one seat make the seat-to-unit match elect one of them, and a proof that elected its own subject proves nothing.
111    MemberPlannedTwice {
112        /// The doubled seat.
113        role: R,
114        /// How many members the plan declared under it.
115        observed: u32,
116    },
117    /// The rebuilt membership and the planned one are not the same set under this seat.
118    ///
119    /// The final theorem, checked as sets: a walk comparing one member per seat would agree about two memberships that differ in their second.
120    MembershipDisagreement {
121        /// The seat the two sets disagree under.
122        role: R,
123    },
124    /// The rebuild produced no member at all.
125    ReconstructionEmpty,
126    /// The rebuild produced members that will not declare as a complete output set.
127    ReconstructionUndeclarable {
128        /// How many members the rebuild produced.
129        observed: u32,
130    },
131    /// One delivery's joined token tree outgrows the declared token magnitude.
132    ///
133    /// It names the delivery it overran at: a caller told only that "the tree" is too wide does not know which build to cut.
134    JoinedTreeUnbounded {
135        /// The delivery whose joined tree overran.
136        destination: Destination,
137    },
138    /// Two rendered units are published to ONE address, so the artifact written second stands where the first stands.
139    ///
140    /// The two stand under different seats and carry different material, so every check before this one passes them.
141    ArtifactAddressDoubled {
142        /// The seat whose artifact would stand at an address already taken.
143        role: R,
144        /// The address both units are written under.
145        address: OwnerIdentity,
146    },
147    /// A unit was rendered into the publication delivery with no address to write it to.
148    ///
149    /// A publication that elected an address for it would be minting the consumer's own fact.
150    ArtifactAddressAbsent {
151        /// The seat whose artifact has nowhere to be written.
152        role: R,
153    },
154}
155
156/// How closure says no.
157///
158/// Closure issues are independent and co-establishable, so the body carries every issue the pass established and says so where it kept only what fits.
159/// No issue is elected as the primary one, and a body with nothing in it is unrepresentable.
160#[must_use = "a closure refusal carries every way the rendering and the plan disagree"]
161#[derive(Debug, Clone, PartialEq, Eq)]
162pub struct ClosureError<R: Role> {
163    body: Capped<ClosureIssue<R>, CLOSURE_ISSUE_LIMIT>,
164}
165
166/// The proof that what was rendered is what was planned, and the emission that proof partitioned.
167///
168/// Holding one means the membership was rebuilt out of the rendered units and equals the plan's declared membership seat for seat, key for key, origin for origin, and digest for digest — and that the rendering was then split across the deliveries its seats declared, each joined delivery's digest committed to inside this closure's own identity.
169///
170/// **No token reaches a compiler except through a value proved here.**
171/// The proved emission is this closure's material and is not handed out: the public road to tokens is the expansion that binds this proof to the plan it was proved against and the explanation written over the two.
172#[must_use = "a closure is the proof that what was rendered is what was planned"]
173#[derive(Debug, Clone, PartialEq, Eq)]
174pub struct Closure<R: Role> {
175    plan: PlanId,
176    reconstructed: Membership<R>,
177    rendered: RenderedProjection<R>,
178    emission: PartitionedEmission,
179    identity: ClosureId,
180    provenance: Provenance,
181}