Skip to content

Commit c5e0cbf

Browse files
governance: document the 15 module-type interface axioms (Trusted-base reduction policy) (#113)
## Summary Fixes the **"Trusted-base reduction policy"** governance gate (newly enforced estate-wide from `standards`, the same check echo-types adopted in #219). It flagged **15 undocumented `Axiom` declarations** in `ResourceAlgebra.v`. These are **pre-existing on `main`** (unrelated to the Idris F1.4 migration in #112) and they are **not proof debt / not global trusted-base assumptions** — they are the abstract *interface fields* of three Coq `Module Type`s: | Module Type | Axioms | |---|---| | `SEMIRING` (10) | `qadd_comm`, `qadd_assoc`, `qadd_zero_l/r`, `qmul_assoc`, `qmul_one_l`, `qmul_zero_r/l`, `qmul_distrib_l/r` | | `ORDERED_SEMIRING` (3) | `qle_refl`, `qle_trans`, `qle_zero` | | `RESIDUE_MEASURE` (2) | `measure_empty`, `measure_combine` | A `Module Type` axiom is a **parameter** of the parametric soundness functor `SoloCoreF`, **discharged by every concrete instance**: `Module Linear3 <: ORDERED_SEMIRING` and `Module Tropical <: ORDERED_SEMIRING` prove them by `destruct; reflexivity` (real `Qed`); `EchoTraceTropical` discharges the measure pair. That is precisely why `Print Assumptions progress` / `preservation` reports **"Closed under the global context"** for the concrete development (`Include SoloCoreF Linear3`) — asserted in `proofs.yml`. ## Fix (policy-sanctioned, honest) - Inline **`AXIOM:` leading comment** on each of the 15 (the policy's explicit annotation route) + a module-type-wide `TRUSTED-BASE NOTE` explaining the posture. - A `PROOF-NEEDS.md` section enumerating all 15 with the same explanation (the policy's independent "enumerate in PROOF-NEEDS.md" route). - I deliberately did **not** use `.trusted-base-ignore` — that route is for "self-scan noise (test fixture, worktree shadow)", which would mischaracterize genuine interface axioms. Comments-only change: `coqc ResourceAlgebra.v` still exits 0. ## Note A follow-up on this same branch will continue the **Idris F1.4 substitution lemma + preservation (#108)** — `Substitution.idr`, building toward discharging `?todo_preservation`. That work is in progress and not part of this gate fix. ## Test plan - [x] `coqc -R . SoloCore ResourceAlgebra.v` exits 0 - [x] 15 `AXIOM:` annotations present (one per flagged line) - [ ] "Trusted-base reduction policy" check goes green https://claude.ai/code/session_01BwV2DWsjkBiNP3oscimMLV --- _Generated by [Claude Code](https://claude.ai/code/session_01BwV2DWsjkBiNP3oscimMLV)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent d21bcad commit c5e0cbf

5 files changed

Lines changed: 275 additions & 1 deletion

File tree

PROOF-NEEDS.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,26 @@ scaffolding with unresolved {{PROJECT}}/{{AUTHOR}} placeholders and no domain-sp
1212

1313
When this project needs formal ABI verification, create domain-specific Idris2 proofs
1414
following the pattern in repos like `typed-wasm`, `proven`, `echidna`, or `boj-server`.
15+
16+
## Trusted-base posture: module-type interface axioms (2026-06-15)
17+
18+
The Trusted-base reduction policy scanner flags 15 `Axiom` declarations in
19+
`proofs/verification/coq/solo-core/ResourceAlgebra.v`. **These are not proof
20+
debt and not global trusted-base assumptions** — they are the abstract
21+
*interface fields* of three Coq `Module Type`s:
22+
23+
- `SEMIRING` (10): `qadd_comm`, `qadd_assoc`, `qadd_zero_l`, `qadd_zero_r`,
24+
`qmul_assoc`, `qmul_one_l`, `qmul_zero_r`, `qmul_zero_l`,
25+
`qmul_distrib_l`, `qmul_distrib_r`.
26+
- `ORDERED_SEMIRING` (3): `qle_refl`, `qle_trans`, `qle_zero`.
27+
- `RESIDUE_MEASURE` (2): `measure_empty`, `measure_combine`.
28+
29+
A `Module Type` axiom is a *parameter* of the parametric soundness functor
30+
`SoloCoreF`, **discharged by every concrete instance**: `Module Linear3 <:
31+
ORDERED_SEMIRING` proves all of them by `destruct; reflexivity` (real `Qed`),
32+
and `Module Tropical <: ORDERED_SEMIRING` likewise at the infinite carrier;
33+
`EchoTraceTropical` discharges the `RESIDUE_MEASURE` pair. This is exactly why
34+
`Print Assumptions progress` / `preservation` reports **"Closed under the
35+
global context"** for the concrete development (`Include SoloCoreF Linear3`) —
36+
asserted in `proofs.yml`. Each axiom additionally carries an inline `AXIOM:`
37+
annotation per the policy. No genuine proof obligation is hidden here.

proofs/STATUS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Last verified: 2026-06-14.
6161
| `progress` | Coq `solo-core/SoloCore` | **machine-checked** | `Theorem progress : Progress.` real `Qed`, axiom-free. Phase F1.3. CI: `proofs.yml` compiles it + asserts `Print Assumptions` closed. |
6262
| `progress` | Idris2 `solo-core/Soundness` | **locally-checked** | Hole-free total function (no `?todo_progress`); accepted by `idris2`, package built in CI (`proofs.yml`). Phase F1.3. **Re-proven over the SEPARATED context (`Tctx`/`Uvec`) + both products (`TWith`/`TTensor`, `LetPair`) in the 2026-06-15 F1.4 design migration** — closed-term inversions now massage only the usage vector (`uaddEmpty`/`uscaleEmpty`), since the shared type context stays `TEmpty` automatically; `:total progress` confirms totality. |
6363
| `preservation` | Coq `solo-core/SoloCore` | **machine-checked** | `Theorem preservation : Preservation.`, real `Qed`, axiom-free, via the open-context QTT substitution lemma `ht_subst`. Phase F1.4. CI: `proofs.yml` compiles it + asserts `Print Assumptions` closed (and likewise `affine_pres`). |
64-
| `preservation` | Idris2 `solo-core/Soundness` | **statement-only** | `?todo_preservation`, **now stated over the CORRECT design** (separated context + genuine products). The OLD Idris design (split-intro `Pair` + project-elim `Fst`/`Snd`) made the same-usage statement UNSOUND (issue #93); the 2026-06-15 migration makes it provable. Proof obligation = Phase F1.4 (Idris track), #108 — the QTT substitution lemma (`htSubst` + `subst2Lemma`) lands in a companion `Substitution.idr` and is wired in here once discharged. NOT described as proved. |
64+
| `preservation` | Idris2 `solo-core/Soundness` | **statement-only** | `?todo_preservation`, **now stated over the CORRECT design** (separated context + genuine products). The OLD Idris design (split-intro `Pair` + project-elim `Fst`/`Snd`) made the same-usage statement UNSOUND (issue #93); the 2026-06-15 migration makes it provable. Proof obligation = Phase F1.4 (Idris track), #108 — the QTT substitution lemma (`htSubst` + `subst2Lemma`) lands in a companion `Substitution.idr` and is wired in here once discharged. NOT described as proved. **Foundation landed (2026-06-15): `Substitution.idr` (in the ipkg, hole-free) carries the append-context algebra (`tappend`/`uappend` + injectivity/split/boundary lemmas) and the shape invariant (`shapeVar`/`shapeType`), all `idris2 --build`-checked. The shift/subst/preservation layers thread `g`/`t` RELEVANTLY around Idris's index erasure (ADR-003) — heavier than the Coq original; PENDING.** |
6565
| Small-step `step` | Coq `solo-core/SoloCore` | **definitions-only** | CBV left-to-right relation, all redex + congruence constructors. Committed in F1.1. |
6666
| Small-step `Step` | Idris2 `solo-core/Soundness` | **definitions-only** | CBV left-to-right relation, both products: additive `SFst`/`SSnd` fire on `With` values, multiplicative `SLetPair` fires on a `Tensor` value via `subst2`; plus the echo residue rules (`SWeaken`). Consumed by the verified `progress`. Migrated 2026-06-15. |
6767
| General core typing + substitution | Coq `coq/Typing.v` | **locally-checked** | Pre-existing: 9 `Qed`, 0 `Admitted`. Non-quantitative; substitution lemma proved. |

proofs/verification/coq/solo-core/ResourceAlgebra.v

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,42 @@ Module Type SEMIRING.
106106
Parameter zero : Q.
107107
Parameter one : Q.
108108

109+
(* TRUSTED-BASE NOTE (Trusted-base reduction policy). Every [Axiom] in
110+
this and the two module types below is a MODULE-TYPE INTERFACE FIELD
111+
— an abstract parameter of the parametric soundness functor
112+
[SoloCoreF], NOT a global assumption admitted into the trusted base.
113+
Each is DISCHARGED by every concrete instance: [Module Linear3 <:
114+
ORDERED_SEMIRING] proves them by [destruct; reflexivity] (real [Qed]),
115+
[Module Tropical <: ORDERED_SEMIRING] likewise at the infinite carrier.
116+
That is exactly why [Print Assumptions progress] / [preservation] is
117+
"Closed under the global context" for the CONCRETE development
118+
([Include SoloCoreF Linear3]) — CI asserts this in proofs.yml. The
119+
per-line [AXIOM:] annotations below satisfy the policy scanner. *)
120+
109121
(* --- additive structure --- *)
122+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
110123
Axiom qadd_comm : forall a b, qadd a b = qadd b a.
124+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
111125
Axiom qadd_assoc : forall a b c, qadd (qadd a b) c = qadd a (qadd b c).
126+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
112127
Axiom qadd_zero_l : forall q, qadd zero q = q.
128+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
113129
Axiom qadd_zero_r : forall q, qadd q zero = q.
114130

115131
(* --- multiplicative structure --- *)
132+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
116133
Axiom qmul_assoc : forall a b c, qmul (qmul a b) c = qmul a (qmul b c).
134+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
117135
Axiom qmul_one_l : forall q, qmul one q = q.
136+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
118137
Axiom qmul_zero_r : forall q, qmul q zero = zero.
138+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
119139
Axiom qmul_zero_l : forall q, qmul zero q = zero.
120140

121141
(* --- distributivity (both sides genuinely cited) --- *)
142+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
122143
Axiom qmul_distrib_l : forall a b c, qmul a (qadd b c) = qadd (qmul a b) (qmul a c).
144+
(* AXIOM: SEMIRING interface law; discharged by each <: SEMIRING instance. *)
123145
Axiom qmul_distrib_r : forall a b c, qmul (qadd a b) c = qadd (qmul a c) (qmul b c).
124146

125147
(* NOTE (excluded, kept as a reminder, NOT as axioms):
@@ -161,8 +183,11 @@ Module Type ORDERED_SEMIRING.
161183

162184
Parameter qle : Q -> Q -> bool.
163185

186+
(* AXIOM: ORDERED_SEMIRING interface law; discharged by each <: ORDERED_SEMIRING instance. *)
164187
Axiom qle_refl : forall q, qle q q = true.
188+
(* AXIOM: ORDERED_SEMIRING interface law; discharged by each <: ORDERED_SEMIRING instance. *)
165189
Axiom qle_trans : forall a b c, qle a b = true -> qle b c = true -> qle a c = true.
190+
(* AXIOM: ORDERED_SEMIRING interface law; discharged by each <: ORDERED_SEMIRING instance. *)
166191
Axiom qle_zero : forall q, qle zero q = true.
167192

168193
(* Decidable carrier equality (R5). The executable usage-walk checker
@@ -283,7 +308,11 @@ Module Type RESIDUE_MEASURE (S : SEMIRING).
283308
Parameter empty : Residue.
284309
Parameter combine : Residue -> Residue -> Residue.
285310
Parameter measure : Residue -> S.Q.
311+
(* AXIOM: RESIDUE_MEASURE interface law (monoid-homomorphism unit);
312+
discharged by each <: RESIDUE_MEASURE instance (e.g. EchoTraceTropical). *)
286313
Axiom measure_empty : measure empty = S.one.
314+
(* AXIOM: RESIDUE_MEASURE interface law (monoid-homomorphism multiplicativity);
315+
discharged by each <: RESIDUE_MEASURE instance (e.g. EchoTraceTropical). *)
287316
Axiom measure_combine : forall a b,
288317
measure (combine a b) = S.qmul (measure a) (measure b).
289318
End RESIDUE_MEASURE.
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
-- SPDX-License-Identifier: MPL-2.0
2+
-- SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3+
--
4+
-- The QTT substitution lemma + preservation for the my-lang Solo core
5+
-- (Idris2 twin of the F1.4 section of SoloCore.v). Phase F1.4, Idris track.
6+
--
7+
-- This is the proof of `preservation` (Soundness.idr states it as the hole
8+
-- `?todo_preservation`). It rests on the standard open-context substitution
9+
-- lemma `htSubst`: substitution under binders shifts the substituted
10+
-- variable's index, so the lemma is generalised over a type-context prefix
11+
-- `I` (the binders crossed so far). The reduction rules only ever do
12+
-- `subst0` (one variable) and `subst2` (two), but the under-binder induction
13+
-- needs the general form.
14+
--
15+
-- Layers (mirroring the Coq twin):
16+
-- 4a append-context algebra (tappend/uappend + injectivity/split) [VERIFIED]
17+
-- 4b shape + shift (shapeType [VERIFIED]; hvShift/htShift/
18+
-- htShift0/weakeningAppend — PENDING)
19+
-- 4c substitution core (reassoc algebra, hvSubst, htSubst,
20+
-- substLemma0, subst2Lemma — PENDING)
21+
-- 4d preservation (consumes 4c; congruences recurse on Step
22+
-- — PENDING; Soundness.preservation stays
23+
-- the honest hole until 4d lands)
24+
--
25+
-- STATUS (Idris track, #108): this module is HOLE-FREE for the layers it
26+
-- currently contains (4a + the shape invariant). It does NOT yet prove
27+
-- preservation. The remaining layers each thread the type context (and term)
28+
-- RELEVANTLY because Idris erases the indices of `Has`/`HasVar` (ADR-003) —
29+
-- the same wall the `progress` proof navigated with explicit-term recursion.
30+
-- That makes the Idris port heavier than the Coq original (whose `Prop`
31+
-- indices erase without blocking the proofs), but the technique is settled
32+
-- (see `shapeType`/`shapeVar` below): pass `g`/`t` explicitly, recurse on the
33+
-- non-binding premise so erased branch-binder types are never demanded.
34+
35+
module Substitution
36+
37+
import Quantity
38+
import EchoMode
39+
import Syntax
40+
import Context
41+
import Typing
42+
import Soundness
43+
import Data.Nat
44+
45+
%default total
46+
47+
------------------------------------------------------------
48+
-- local disjointness / injectivity helpers
49+
------------------------------------------------------------
50+
-- (Context.idr's equivalents are not exported; restate locally.)
51+
52+
justInj' : Just x = Just y -> x = y
53+
justInj' Refl = Refl
54+
55+
nothingNotJust' : Nothing = Just x -> Void
56+
nothingNotJust' Refl impossible
57+
58+
usnocNotUEmpty' : USnoc d q = UEmpty -> Void
59+
usnocNotUEmpty' Refl impossible
60+
61+
predEq' : S n = S m -> n = m
62+
predEq' Refl = Refl
63+
64+
sNotZ' : S n = Z -> Void
65+
sNotZ' Refl impossible
66+
67+
zNotS' : Z = S n -> Void
68+
zNotS' Refl impossible
69+
70+
------------------------------------------------------------
71+
-- 4a. Append-context algebra
72+
------------------------------------------------------------
73+
74+
||| Append type contexts: `tappend G I` places `I`'s binders on top of `G`.
75+
public export
76+
tappend : Tctx -> Tctx -> Tctx
77+
tappend g TEmpty = g
78+
tappend g (TSnoc i a) = TSnoc (tappend g i) a
79+
80+
||| Append usage vectors, shape-matched to `tappend`.
81+
public export
82+
uappend : Uvec -> Uvec -> Uvec
83+
uappend d UEmpty = d
84+
uappend d (USnoc e q) = USnoc (uappend d e) q
85+
86+
public export
87+
tappendLen : (g, i : Tctx) -> tlen (tappend g i) = tlen g + tlen i
88+
tappendLen g TEmpty = rewrite plusZeroRightNeutral (tlen g) in Refl
89+
tappendLen g (TSnoc i a) =
90+
rewrite tappendLen g i in rewrite plusSuccRightSucc (tlen g) (tlen i) in Refl
91+
92+
public export
93+
uappendLen : (d, e : Uvec) -> ulen (uappend d e) = ulen d + ulen e
94+
uappendLen d UEmpty = rewrite plusZeroRightNeutral (ulen d) in Refl
95+
uappendLen d (USnoc e q) =
96+
rewrite uappendLen d e in rewrite plusSuccRightSucc (ulen d) (ulen e) in Refl
97+
98+
public export
99+
uzeroTappend : (g, i : Tctx) -> uzero (tappend g i) = uappend (uzero g) (uzero i)
100+
uzeroTappend g TEmpty = Refl
101+
uzeroTappend g (TSnoc i a) = rewrite uzeroTappend g i in Refl
102+
103+
public export
104+
uscaleUappend : (q : Q) -> (d, e : Uvec)
105+
-> uscale q (uappend d e) = uappend (uscale q d) (uscale q e)
106+
uscaleUappend q d UEmpty = Refl
107+
uscaleUappend q d (USnoc e qe) = rewrite uscaleUappend q d e in Refl
108+
109+
||| Add appended vectors componentwise (forward direction).
110+
public export
111+
uaddUappend : (ai, bi, ci, ag, bg, cg : Uvec)
112+
-> uadd ai bi = Just ci -> uadd ag bg = Just cg
113+
-> uadd (uappend ag ai) (uappend bg bi) = Just (uappend cg ci)
114+
uaddUappend UEmpty UEmpty ci ag bg cg hi hg =
115+
rewrite sym (justInj' hi) in hg
116+
uaddUappend UEmpty (USnoc _ _) _ _ _ _ hi _ = void (nothingNotJust' hi)
117+
uaddUappend (USnoc _ _) UEmpty _ _ _ _ hi _ = void (nothingNotJust' hi)
118+
uaddUappend (USnoc ai qa) (USnoc bi qb) ci ag bg cg hi hg with (uadd ai bi) proof p
119+
uaddUappend (USnoc ai qa) (USnoc bi qb) ci ag bg cg hi hg | Nothing =
120+
void (nothingNotJust' hi)
121+
uaddUappend (USnoc ai qa) (USnoc bi qb) ci ag bg cg hi hg | Just cii =
122+
rewrite uaddUappend ai bi cii ag bg cg p hg in
123+
rewrite sym (justInj' hi) in Refl
124+
125+
usnocInj : USnoc x p = USnoc y q -> (x = y, p = q)
126+
usnocInj Refl = (Refl, Refl)
127+
128+
||| uappend injectivity, given the low parts have matching length.
129+
public export
130+
uappendInj : (e, f, d1, d2 : Uvec) -> ulen e = ulen f
131+
-> uappend d1 e = uappend d2 f -> (d1 = d2, e = f)
132+
uappendInj UEmpty UEmpty d1 d2 _ heq = (heq, Refl)
133+
uappendInj UEmpty (USnoc _ _) _ _ hlen _ = void (zNotS' hlen)
134+
uappendInj (USnoc _ _) UEmpty _ _ hlen _ = void (sNotZ' hlen)
135+
uappendInj (USnoc e qe) (USnoc f qf) d1 d2 hlen heq =
136+
let (hbody, hq) = usnocInj heq
137+
(hd, he) = uappendInj e f d1 d2 (predEq' hlen) hbody
138+
in (hd, rewrite he in rewrite hq in Refl)
139+
140+
||| Split a usage vector by a target low-length `m`.
141+
public export
142+
uappendSplit : (m : Nat) -> (d : Uvec) -> LTE m (ulen d)
143+
-> (dhi : Uvec ** dlo : Uvec ** (d = uappend dhi dlo, ulen dlo = m))
144+
uappendSplit Z d _ = (d ** UEmpty ** (Refl, Refl))
145+
uappendSplit (S m) UEmpty lte = absurd lte
146+
uappendSplit (S m) (USnoc d q) lte =
147+
let (dhi ** dlo ** (heq, hlen)) = uappendSplit m d (fromLteSucc lte) in
148+
(dhi ** USnoc dlo q ** (rewrite heq in Refl, cong S hlen))
149+
150+
||| Inverse of `uaddUappend`: a sum of appends (with matching low-lengths)
151+
||| splits back into a sum of the highs and a sum of the lows.
152+
public export
153+
uaddUappendInv : (ai, bi, ag, bg, c : Uvec) -> ulen ai = ulen bi
154+
-> uadd (uappend ag ai) (uappend bg bi) = Just c
155+
-> (cg : Uvec ** ci : Uvec **
156+
(c = uappend cg ci, uadd ag bg = Just cg, uadd ai bi = Just ci))
157+
uaddUappendInv UEmpty UEmpty ag bg c _ h = (c ** UEmpty ** (Refl, h, Refl))
158+
uaddUappendInv UEmpty (USnoc _ _) _ _ _ hlen _ = void (zNotS' hlen)
159+
uaddUappendInv (USnoc _ _) UEmpty _ _ _ hlen _ = void (sNotZ' hlen)
160+
uaddUappendInv (USnoc ai qa) (USnoc bi qb) ag bg c hlen h
161+
with (uadd (uappend ag ai) (uappend bg bi)) proof p
162+
uaddUappendInv (USnoc ai qa) (USnoc bi qb) ag bg c hlen h | Nothing =
163+
void (nothingNotJust' h)
164+
uaddUappendInv (USnoc ai qa) (USnoc bi qb) ag bg c hlen h | Just d =
165+
let (cg ** ci ** (heq, hg, hi)) = uaddUappendInv ai bi ag bg d (predEq' hlen) p in
166+
(cg ** USnoc ci (qAdd qa qb) **
167+
(rewrite sym (justInj' h) in rewrite heq in Refl,
168+
hg,
169+
rewrite hi in Refl))
170+
171+
||| Split a sum-of-appends at the boundary (low parts matched by length).
172+
public export
173+
uaddSplitBoundary : (dg1, di1, dg2, di2, dg, di : Uvec)
174+
-> ulen di1 = ulen di2 -> ulen di = ulen di1
175+
-> uadd (uappend dg1 di1) (uappend dg2 di2) = Just (uappend dg di)
176+
-> (uadd dg1 dg2 = Just dg, uadd di1 di2 = Just di)
177+
uaddSplitBoundary dg1 di1 dg2 di2 dg di h12 hd heq =
178+
let (cg ** ci ** (hap, hg, hi)) =
179+
uaddUappendInv di1 di2 dg1 dg2 (uappend dg di) h12 heq
180+
(hdg, hdi) = uappendInj di ci dg cg
181+
(rewrite hd in sym (uaddLen di1 di2 ci hi)) hap
182+
in (rewrite hdg in hg, rewrite hdi in hi)
183+
184+
------------------------------------------------------------
185+
-- 4b. Shape invariant + shift / weakening
186+
------------------------------------------------------------
187+
188+
-- The type context `g` (and, for `shapeType`, the term `t`) are passed
189+
-- EXPLICITLY/relevantly: Idris erases the indices of `HasVar`/`Has`, so the
190+
-- `THUnit` case (which needs `uzeroLen g`) and the binder cases (which need
191+
-- the Lam annotation for the extended context) cannot recover them from the
192+
-- erased derivation. The term drives the recursion; for every BINDING rule
193+
-- except `THLam` we recurse only on the non-binding premise, so the erased
194+
-- branch-binder types are never needed.
195+
196+
||| A variable lookup's usage has the same length as its type context.
197+
public export
198+
shapeVar : (g : Tctx) -> HasVar g d n a -> ulen d = tlen g
199+
shapeVar (TSnoc g a) HVHere = cong S (uzeroLen g)
200+
shapeVar (TSnoc g b) (HVThere hv) = cong S (shapeVar g hv)
201+
202+
||| Every derivation's usage has the length of its type context. The
203+
||| separated-context invariant that the split/scale algebra relies on.
204+
public export
205+
shapeType : (g : Tctx) -> (t : Tm) -> Has g d t a -> ulen d = tlen g
206+
shapeType g (Var n) (THVar hv) = shapeVar g hv
207+
shapeType g UnitT THUnit = uzeroLen g
208+
shapeType g (Lam q a body) (THLam bodyD) = predEq' (shapeType (TSnoc g a) body bodyD)
209+
shapeType g (App t1 t2) (THApp d1 d2 q h1 h2 prf) = trans (uaddLen d1 (uscale q d2) _ prf) (shapeType g t1 h1)
210+
shapeType g (With t1 t2) (THWith h1 h2) = shapeType g t1 h1
211+
shapeType g (Fst t1) (THFst h) = shapeType g t1 h
212+
shapeType g (Snd t1) (THSnd h) = shapeType g t1 h
213+
shapeType g (Tensor t1 t2) (THTensor d1 d2 h1 h2 prf) = trans (uaddLen d1 d2 _ prf) (shapeType g t1 h1)
214+
shapeType g (LetPair t1 t2)(THLetPair d1 d2 h1 hb prf)= trans (uaddLen d1 d2 _ prf) (shapeType g t1 h1)
215+
shapeType g (Inl b t1) (THInl h) = shapeType g t1 h
216+
shapeType g (Inr a t1) (THInr h) = shapeType g t1 h
217+
shapeType g (Case t tL tR) (THCase d1 d2 h hL hR prf) = trans (uaddLen d1 d2 _ prf) (shapeType g t h)
218+
shapeType g (Let q t1 t2) (THLet d1 d2 _ h1 h2 prf) =
219+
trans (uaddLen (uscale q d1) d2 _ prf) (trans (uscaleLen q d1) (shapeType g t1 h1))
220+
shapeType g (MkEcho m a b t1) (THEcho h) = shapeType g t1 h
221+
shapeType g (Weaken t1) (THWeaken h) = shapeType g t1 h

proofs/verification/idris/solo-core/solo-core.ipkg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ modules = Quantity
1717
, Typing
1818
, Soundness
1919
, EchoResidue
20+
, Substitution
2021

2122
main = Soundness

0 commit comments

Comments
 (0)