Skip to content

Commit f0f9b8f

Browse files
committed
proof(idris2/abi): port to Idris2 0.8.0 syntax; add ipkg for verifiable builds (#27)
Followup to aac48b7. With idris2 0.8.0 now bootstrapped locally, this makes the issue-#27 module surface actually typecheck: * `postulate name : Ty` is not parsed in Idris2 0.8.0 (the keyword only survives as an IDE-protocol decoration tag). Replace with the canonical `name = believe_me ()` idiom in `Proofs/DivMod.idr`. Each axiom remains individually named so discharge stays incremental and grep-able. * `align - remainder` in `alignedSize` required `Neg Nat` (which doesn't exist). Replace with `align `minus` remainder`. * `programStateAlignmentValid` cannot be discharged by direct `Oh` after Platform case-split: Idris2 0.8.0 will not reduce through `divNat`'s non-covering clause at type-level, even when both args are concrete. Route through `believe_me ()` with a doc-comment distinguishing this from the deleted unsound axiom: - per-instance (n=8 only), not universal — no further consumer can pivot to a false proposition; - the claim is computationally true; the gap is unifier strategy, not the proposition itself. Replaceable with an explicit rewrite once `DivMod` supplies the per-platform reduction equations. * Add `absolute-zero-abi.ipkg` so `idris2 --build absolute-zero-abi` becomes a meaningful CI target. The build still surfaces five pre-existing errors in `src/abi/Types.idr` (missing `Decidable.Equality` import; `%runElab` without enabling `ElabReflection`; `MkStateHandle ptr` not providing the `nonNull : So (ptr /= 0)` proof; `No absurd` without an `Uninhabited` instance for the constructor inequalities). These are orthogonal to #27 and warrant a separate audit; flagged in the issue comment. Verified: `idris2 --check AbsoluteZero/ABI/Proofs/DivMod.idr` compiles cleanly under Idris2 0.8.0. A harness module exercising the `believe_me`-based pattern also compiles.
1 parent aac48b7 commit f0f9b8f

3 files changed

Lines changed: 68 additions & 25 deletions

File tree

absolute-zero-abi.ipkg

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package absolute-zero-abi
2+
version = 0.1.0
3+
4+
authors = "Jonathan D. A. Jewell"
5+
license = "PMPL-1.0-or-later"
6+
7+
opts = "--ignore-missing-ipkg"
8+
9+
sourcedir = "src/abi"
10+
11+
modules = AbsoluteZero.ABI.Types,
12+
AbsoluteZero.ABI.Layout,
13+
AbsoluteZero.ABI.Proofs.DivMod
14+
15+
depends = base, contrib

src/abi/Layout.idr

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,21 +244,28 @@ instructionCrossPlatform = InvariantProof
244244
-- previously lived here. It was unsound: `AlignProof` carries no evidence
245245
-- about `n`, so the postulate would derive `So (1 `mod` 8 == 0)` from
246246
-- `CNOResultLayout.alignment : HasAlignment CNOVerificationResult 1`. It was
247-
-- removed in favour of per-type decidable proofs at each call site (the
248-
-- only previous caller was `programStateAlignmentValid`, dispatched below
249-
-- by Platform case-split since `8 `mod` (ptrSize p `div` 8)` reduces to 0
250-
-- on every supported platform).
247+
-- removed in favour of per-type decidable claims at each call site.
248+
--
249+
-- Reduction note: `8 `mod` (ptrSize p `div` 8) == 0` is concretely True
250+
-- on every supported platform (Linux/Windows/MacOS/BSD: 64/8=8, 8 mod 8=0;
251+
-- WASM: 32/8=4, 8 mod 4=0). However, Idris2 0.8.0 will not reduce
252+
-- through `divNat`'s non-covering case at type-level, so a direct `Oh`
253+
-- proof fails to unify. The discharge below uses `believe_me` —
254+
-- distinguished from the deleted unsound postulate in two ways:
255+
-- 1. It is a per-instance claim (n=8 only), not a universal claim;
256+
-- no further consumer can pivot from it to a false proposition.
257+
-- 2. The claim is computationally true; the gap is the typechecker's
258+
-- reduction strategy, not the proposition itself.
259+
-- A clean discharge becomes available once `AbsoluteZero.ABI.Proofs.DivMod`
260+
-- supplies an explicit rewrite from `ptrSize p` to its concrete value.
251261

252262
||| ProgramState alignment is valid on all platforms.
253-
||| Proved directly by reduction; no axiom required.
263+
||| See the note above on why this currently routes through `believe_me`
264+
||| (typechecker reduction, not an axiom about an abstract proposition).
254265
public export
255266
programStateAlignmentValid : (p : Platform) ->
256267
So (8 `mod` (ptrSize p `div` 8) == 0)
257-
programStateAlignmentValid Linux = Oh
258-
programStateAlignmentValid Windows = Oh
259-
programStateAlignmentValid MacOS = Oh
260-
programStateAlignmentValid BSD = Oh
261-
programStateAlignmentValid WASM = Oh
268+
programStateAlignmentValid _ = believe_me ()
262269

263270
--------------------------------------------------------------------------------
264271
-- Size Calculation Utilities

src/abi/Proofs/DivMod.idr

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@
88
||| * Single shared module — each estate repo imports the same lemmas
99
||| rather than re-postulating per file.
1010
||| * Each lemma is an individually-named declaration so it can be
11-
||| discharged incrementally (one Qed/proof per audit pass) without
11+
||| discharged incrementally (one proof per audit pass) without
1212
||| touching consumers.
1313
||| * Definitions of the functions the lemmas talk about live here too,
1414
||| so the lemma statements don't drift from their referent.
1515
|||
1616
||| Discharge tracker: absolute-zero#27.
1717
|||
18+
||| Notes on Idris2 0.8.0:
19+
||| * The `postulate` keyword used in older Idris/Agda style code does
20+
||| not parse in current Idris2. The canonical axiom idiom is
21+
||| `name = believe_me ()` — semantically equivalent (asserts a term
22+
||| of the target type with no proof) but explicit at the term level,
23+
||| so every axiom is grep-able as a `believe_me` occurrence in the
24+
||| trusted base.
25+
|||
1826
||| @see https://github.com/hyperpolymath/absolute-zero/issues/27
1927

2028
-- SPDX-License-Identifier: PMPL-1.0-or-later
@@ -38,23 +46,33 @@ alignedSize size align =
3846
let remainder = size `mod` align
3947
in if remainder == 0
4048
then size
41-
else size + (align - remainder)
49+
else size + (align `minus` remainder)
4250

4351
--------------------------------------------------------------------------------
4452
-- Trusted lemma surface
4553
--
46-
-- Each `postulate` below is an individually-audit-trackable item. Discharge
47-
-- one at a time; the lemma name stays stable so consumers don't break.
54+
-- Each `believe_me`-based axiom below is an individually-audit-trackable
55+
-- item. Discharge one at a time by replacing the RHS with a real proof;
56+
-- the lemma name and type signature stay stable so consumers don't break.
4857
--
4958
-- Estate cross-reference (as of 2026-05-20):
5059
-- * civic-connect/src/Abi/Layout.idr defers the same family under
5160
-- `alignUpDivides`, `mkFieldsAligned`, `offsetInBoundsPrf`. Those
5261
-- should migrate to import these names.
62+
--
63+
-- Discharge path to stdlib:
64+
-- * `divModIdentity` is provable from
65+
-- `Data.Nat.Division.DivisionTheorem` (idris2-contrib): converts
66+
-- `So (d /= 0)` to `NonZero d`, then rewrites between
67+
-- `mod`/`div` (Prelude binary ops) and `modNatNZ`/`divNatNZ`.
68+
-- * `multModZero` follows by induction on `k`.
69+
-- * `addModDistrib` is in `Data.Nat.Equational` territory.
70+
-- * `alignedSizeCorrect` then chains them.
5371
--------------------------------------------------------------------------------
5472

5573
||| `alignedSize size align` is always a multiple of `align`.
5674
|||
57-
||| Proof outline (deferred — see audit tracker):
75+
||| Proof outline (currently asserted; see discharge path above):
5876
||| Let r = size `mod` align.
5977
||| Case r == 0: alignedSize = size, divisible by hypothesis.
6078
||| Case r /= 0: alignedSize = size + (align - r)
@@ -64,35 +82,38 @@ alignedSize size align =
6482
||| [by Nat ring rewriting]
6583
||| and (k * align) `mod` align = 0
6684
||| [by multModZero].
67-
|||
68-
||| Reduces to: `divModIdentity` + `multModZero` + `addModDistrib`.
6985
export
70-
postulate alignedSizeCorrect :
86+
alignedSizeCorrect :
7187
(size : Nat) -> (align : Nat) ->
7288
{auto 0 nonZero : So (align /= 0)} ->
7389
So (alignedSize size align `mod` align == 0)
90+
alignedSizeCorrect _ _ = believe_me ()
7491

75-
||| Euclidean division identity: every Nat decomposes as q*d + r where r < d.
76-
||| The single most-used lemma in the alignment proofs — proving this
77-
||| (likely by induction on `size`, or via Idris2 stdlib `Data.Nat.Division`)
78-
||| would shrink the trusted base substantially.
92+
||| Euclidean division identity: every Nat decomposes as q*d + r.
93+
||| Provable from `Data.Nat.Division.DivisionTheorem` — the conversion
94+
||| between `So (d /= 0)` and `NonZero d`, plus the rewrite between
95+
||| Prelude `mod`/`div` and `modNatNZ`/`divNatNZ`, is the only real work.
7996
export
80-
postulate divModIdentity :
97+
divModIdentity :
8198
(n : Nat) -> (d : Nat) ->
8299
{auto 0 nonZero : So (d /= 0)} ->
83100
n = (n `div` d) * d + (n `mod` d)
101+
divModIdentity _ _ = believe_me ()
84102

85103
||| Any multiple of `d` is congruent to zero mod `d`.
104+
||| Provable by induction on `k`.
86105
export
87-
postulate multModZero :
106+
multModZero :
88107
(k : Nat) -> (d : Nat) ->
89108
{auto 0 nonZero : So (d /= 0)} ->
90109
So ((k * d) `mod` d == 0)
110+
multModZero _ _ = believe_me ()
91111

92112
||| Mod distributes over addition (in the sense that `(a + b) mod d` is
93113
||| determined by `a mod d` and `b mod d`).
94114
export
95-
postulate addModDistrib :
115+
addModDistrib :
96116
(a : Nat) -> (b : Nat) -> (d : Nat) ->
97117
{auto 0 nonZero : So (d /= 0)} ->
98118
(a + b) `mod` d = ((a `mod` d) + (b `mod` d)) `mod` d
119+
addModDistrib _ _ _ = believe_me ()

0 commit comments

Comments
 (0)