The univalence-free refusal guard #
The crux of the Trocq port is to compute, per subterm, the minimal (m,n)
relation level a goal needs, and — when that level is the equivalence top
(level equiv, where an equivalence is used as an equality) — refuse and
report rather than import univalence (UA), which would enlarge the TCB and is
in any case false for the (non-surjective) byte encodings.
That full per-subterm level inference is a separate, larger engine (Coq-Elpi →
Lean MetaM). This module provides the tractable, decidable guard it relies
on. The primary form of the cap lives on the Trocq lattice: the guard
refuses exactly the map4 universe witness (permittedMapClass /
classifyMapClass — map0–map3 is the univalence-free fragment, wider than
the 3-point view). The 3-point classification (permitted / classify) is
the view of that lattice guard through RelLevel.toMapClass
(permitted_toMapClass / classify_toMapClass), so refusing equiv is the
derived form of refusing map4. This guard makes the discipline enforceable
and distinguishes this cap from full Coq-Trocq.
The discipline #
The permitted (m,n) slice on the lattice is map0–map3; in the 3-point
view: map (transfers = forward), embedding (+ injective, transfers =
both ways), and the refused equiv (image map4, needs UA). The crypto
encodings (point/Fp¹²/word serializations) are embeddings, not bijections,
so a goal that would need equiv is one this layer declines.
Primary. The univalence-free slice of the Trocq lattice: a MapClass
is permitted iff it is not the map4 universe witness. map0–map3 are
univalence-free (the fragment wider than the 3-point view — map2a,
map2b and map3 are all permitted); only map4 needs UA.
Equations
Instances For
The univalence-free slice in the 3-point view: the lattice guard through
toMapClass. map and embedding are univalence-free; equiv (image
map4) needs UA.
Equations
Instances For
The 3-point guard is the view of the lattice guard (definitional).
Old = new: the derived guard agrees with the original 3-point table
(refuse exactly equiv).
The lattice cap refuses exactly the map4 universe witness.
The outcome of classifying the level a (sub)goal needs: either a permitted
univalence-free transfer at lvl, or a refusal carrying a report of why
(which subterm forced the equivalence level). The full engine feeds
classify the level it infers per subterm; this module supplies classify
and the report, not the inference.
- ok
(lvl : RelLevel)
: TransferOutcome
Transfer permitted at this (univalence-free) level.
- refused
(report : String)
: TransferOutcome
Transfer refused: the goal needs
equiv(equivalence-as-equality).
Instances For
Equations
- One or more equations did not get rendered due to their size.
- Transfer.LevelRefusal.instDecidableEqTransferOutcome.decEq (Transfer.LevelRefusal.TransferOutcome.ok lvl) (Transfer.LevelRefusal.TransferOutcome.refused report) = isFalse ⋯
- Transfer.LevelRefusal.instDecidableEqTransferOutcome.decEq (Transfer.LevelRefusal.TransferOutcome.refused report) (Transfer.LevelRefusal.TransferOutcome.ok lvl) = isFalse ⋯
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
Primary. Classify a needed lattice level: refuse exactly the map4
universe witness, reporting it; every univalence-free level is permitted
at its 3-point view.
Equations
- One or more equations did not get rendered due to their size.
- Transfer.LevelRefusal.classifyMapClass x✝ = Transfer.LevelRefusal.TransferOutcome.ok x✝.view3
Instances For
Classify a needed level: the lattice classifier through toMapClass —
refuses exactly the equivalence top (image map4), reporting it.
Equations
Instances For
The 3-point classifier is the view of the lattice classifier (definitional).
The lattice classifier refuses exactly the map4 universe witness.
The wider-than-3-point fragment is permitted at the lattice level: a
two-sided graph relation (map3) classifies as an embedding-view
transfer, not a refusal.
The guard is correct and decidable #
map is permitted (forward equation transfer needs no UA).
embedding is permitted (both-ways equation transfer via injectivity — the
level at which the crypto encodings, and the Num ↪ ℕ transfer, live).
equiv is refused with a report — the univalence-free cap.
A minimal-level inferencer over a goal-shape model #
The classifier above takes the needed level as given and only classifies it. This
inferencer computes the level from a small, hand-rolled goal-shape AST and feeds
the inferred level to classify, so classify is reached with equiv when the
shape forces it rather than when a level is supplied.
This is a minimal model. It walks a GoalShape — a small model of the cases the
level discipline turns on — not a real Expr. The full engine traverses a Lean
Expr, threads RelatedAt annotations through binders, and is a larger
MetaM port (no Lean precedent). The contribution here is the direction of
dataflow: level ← shape, then refuse-or-permit.
The modeling decisions #
- A leaf is an equation whose carrier encoding has some
RelLeveland asurjective : Boolflag. The flag distinguishes an embedding that is onto (so the backward direction is free) from a non-surjective encoding (the crypto case: a point/Fp¹²/word serialization that is injective but not onto, so the reverse needs UA). - A forward
∀(forallFwd) transfers in themapdirection only: it adds no strength, soinferLevel (forallFwd d) = inferLevel d. - A backward
∀(forallBwd) needs the reverse direction over its domain.- Over a surjective domain the backward direction is available at the
embeddingstrength, soinferLevelismax (inferLevel d) embedding. - Over a non-surjective domain at level
embedding(the crypto encodings) the reverse needs a bijection, soinferLevelisequiv. This is the one place the inferencer producesequiv, exactly when a subterm lacks the backward direction — matching the classifier's discipline thatequivis refused. - A
forallBwdwhose domain already needsequivstays atequiv.
- Over a surjective domain the backward direction is available at the
- A composite (
compose a b) supports only its weakest part, soinferLevel (compose a b) = RelLevel.meet (inferLevel a) (inferLevel b)(usingmeetfromLevels.lean).
A tiny goal-shape AST: the cases the minimal-level inferencer reasons about.
A model of the level discipline rather than a real Expr (the full engine
walks Expr; this drives the dataflow level ← shape).
- leafEq
(carrierLevel : RelLevel)
(surjective : Bool)
: GoalShape
An equation at a leaf whose carrier encoding has level
carrierLevel;surjectiverecords whether that encoding is onto (so the backward direction is free) —falseis the crypto case (injective, not onto). - forallFwd
(dom : GoalShape)
: GoalShape
A
∀transferred in the forward (map) direction: adds no strength. - forallBwd
(dom : GoalShape)
: GoalShape
A
∀needing the backward direction overdom: needs at leastembedding, and forcesequivwhendomis a non-surjective leaf. - compose
(a b : GoalShape)
: GoalShape
A composite: level is the
meet(weakest) of the parts.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
The maximum (stronger) of two levels — dual to RelLevel.meet; a backward
∀ needs at least embedding, so it takes the max with embedding.
Instances For
Whether a shape's domain is a leaf that is an embedding but not
surjective — the configuration whose reverse direction needs a
bijection, hence forces equiv under a backward ∀.
Equations
Instances For
Infer the minimal level a shape needs. The level is computed, then
handed to classify. See the section docstring above for the modeling
decisions behind each clause.
Equations
- One or more equations did not get rendered due to their size.
- Transfer.LevelRefusal.inferLevel (Transfer.LevelRefusal.GoalShape.leafEq l surjective) = l
- Transfer.LevelRefusal.inferLevel d.forallFwd = Transfer.LevelRefusal.inferLevel d
- Transfer.LevelRefusal.inferLevel (a.compose b) = (Transfer.LevelRefusal.inferLevel a).meet (Transfer.LevelRefusal.inferLevel b)
Instances For
The end-to-end guard: infer the level the shape needs, then refuse or
permit it. classify is called on a computed level.
Equations
Instances For
The inferencer is exercised end-to-end #
A plain embedding equation (e.g. a Num ↪ ℕ leaf) infers embedding and is
permitted.
A leaf at map (forward-only) is permitted at map.
A forward ∀ over an embedding leaf still infers embedding and is
permitted — the forward direction adds no strength.
A backward ∀ over a surjective embedding leaf is still permitted at
embedding — the reverse direction is available because the leaf is onto.
The central refusal. A backward ∀ over a non-surjective embedding leaf
(the crypto encoding case) infers equiv, so the end-to-end guard refuses
— the engine declines exactly when a subterm forces the equivalence level.
The inferred level for that refused shape is exactly equiv — pinning down
why it was refused.
A composite drops to the weaker level: composing a map leaf with an
embedding leaf infers map (the meet), and is permitted at map.
A composite that contains a refusing part still composes down: meeting an
equiv-forcing backward-∀ with a map leaf yields map — the composite
is permitted because its weakest part carries no UA need. So meet can
rescue a transfer, and refusal is level-driven (it occurs only when the
inferred level — after all meets — is equiv).
What this module is not #
The inferencer above is a minimal model over a hand-rolled GoalShape; the level it
computes is faithful to the discipline (forward adds nothing; backward over a
non-surjective embedding forces equiv; composites meet), but the full engine
walks a real Expr, threads RelatedAt levels through actual binders, and
infers the least level that makes the whole transfer go through. That
level-annotated parametricity translation is the heart of the Trocq paper and
a larger MetaM port (no Lean precedent). The RelatedAt kernel carries
the level; the transfer tactic traverses binders; the minimal-level solver over
Expr is not implemented here. The contribution here is the
dataflow direction: the level is computed and fed to classify rather than
supplied.