Lean Kernel Arena / lazylean

Checker "lazylean"

Version: 0.3.0 · 📄 Declaration · 🔗 Source

lazylean — a Lean 4 kernel in C++ whose reduction engine is a lazy abstract machine in the style of the Coq kernel's cClosure, rather than Lean's substitution-based whnf.

  • The type-checking algorithm is Lean's own (is_def_eq, lazy delta reduction with reducibility hints, proof irrelevance, eta, K-like recursors, Nat/String literals with GMP), cross-checked against lean4lean; recursors are re-derived from the inductive specification and compared with the exported ones.
  • Weak-head normalisation runs a Krivine machine: closures over environments, call-by-need thunks overwritten with their value when first forced, constant C++ stack, reference-counted memory proportional to the live data.
  • Lean's compiled match/brecOn wrapper chains are fused once per definition, and structurally recursive definitions get Coq-style fixpoint rules that the kernel verifies with is_def_eq before using them.
  • Lean.reduceBool/reduceNat (native reduction) are declined.
  • Declarations are checked by worker processes forked after the export has been parsed, so the parse and the interned terms are shared rather than repeated; the export's declaration order is verified first, so that no worker can be shown a constant introduced after the one it is checking.

Written by Claude (Anthropic), directed by Chris Emery.

Soundness (rightfully rejected tests)

72 ✅ 0 ❌ 0 🚫

Completeness (rightfully accepted tests)

135 ✅ 0 ❌ 0 🚫

Corner cases (no outcome prescribed)

24 ✅ 2 🚫

Test Expected Result ⏱️ 🧠
cedar 👍 👍 1.3 m (-46%) 1015.4 MB (-27%)
con-leche 👍 👍 1.3 m (-31%) 617.3 MB (-28%)
cslib 👍 👍 4.6 m (-47%) 2.5 GB (-26%)
init 👍 👍 37.0 s (-44%) 392.0 MB (-30%)
init-prelude 👍 👍 101 ms (÷3.6) 29.4 MB (÷2.5)
mathlib 👍 👍 16.4 m (-49%) 7.0 GB (-29%)
navier-stokes-euler 👍 👍 6.6 m (-41%) 1.8 GB (-29%)
std 👍 👍 1.0 m (-45%) 710.3 MB (-24%)
19 56 ms 26.1 MB
constlevels ✋ ✋ 1 ms 21.6 MB
ctor-num-fields ✋ ✋ 1 ms 22.0 MB
eta-ctor-alias ✋ ✋ 1 ms 21.7 MB
k-rec-conv ✋ ✋ 1 ms 21.7 MB
large-elim-param ✋ ✋ 1 ms 21.8 MB
large-elim-prop-bool ✋ ✋ 1 ms 21.7 MB
level-imax-leq ✋ ✋ 1 ms 21.7 MB
level-imax-normalization ✋ ✋ 1 ms 21.8 MB
nat-rec-k-lie ✋ ✋ 1 ms 22.0 MB
nat-rec-rules ✋ ✋ 1 ms 21.9 MB
nested-unused-param ✋ ✋ 2 ms 22.3 MB
orphan-rec ✋ ✋ 1 ms 21.8 MB
proj-non-structure ✋ ✋ 1 ms 21.9 MB
proj-of-imax-prop ✋ ✋ 1 ms 21.6 MB
proj-of-stuck-prop ✋ ✋ 9 ms 26.1 MB
proj-of-subst-prop ✋ ✋ 9 ms 23.7 MB
rec-k-lie ✋ ✋ 1 ms 21.7 MB
rec-missing-ih ✋ ✋ 9 ms 23.7 MB
rec-of-subst-prop ✋ ✋ 9 ms 23.6 MB
1 38 ms 23.0 MB
alg-conv-trans-acc 🤷 ✋ 3 ms 23.0 MB
alg-conv-trans-acc-left 🤷 👍 3 ms 22.4 MB
alg-conv-trans-acc-right 🤷 👍 3 ms 22.3 MB
alg-conv-trans-quot 🤷 ✋ 1 ms 21.7 MB
alg-conv-trans-quot-left 🤷 ✋ 1 ms 21.6 MB
alg-conv-trans-quot-left-def 🤷 👍 1 ms 21.6 MB
alg-conv-trans-quot-right 🤷 👍 1 ms 21.7 MB
eta-ctor 🤷 ✋ 1 ms 21.7 MB
eta-rec-struct 🤷 ✋ 1 ms 21.6 MB
eta-rule-k 🤷 ✋ 1 ms 21.9 MB
eta-struct-major-and 🤷 ✋ 1 ms 21.6 MB
eta-struct-major-and-no-whnf 🤷 ⌛ 0 ms 0 B
eta-struct-major-no-whnf 🤷 ⌛ 0 ms 0 B
eta-unit-like-nested 🤷 ✋ 1 ms 21.6 MB
eta-unit-like-pi 🤷 ✋ 1 ms 21.6 MB
eta-unit-like-proof-field 🤷 ✋ 1 ms 21.6 MB
eta-unit-like-struct 🤷 ✋ 1 ms 21.7 MB
imax-right-successor 🤷 ✋ 1 ms 21.6 MB
let-value-type-mismatch 🤷 ✋ 1 ms 21.7 MB
nested-nonuniform-param 🤷 👍 1 ms 21.7 MB
positivity-whnf 🤷 ✋ 1 ms 21.6 MB
proj-maybe-prop 🤷 👍 1 ms 21.8 MB
proj-maybe-prop-past 🤷 👍 1 ms 21.7 MB
proof-param-ok 👍 👍 1 ms 21.8 MB
proof-param-swap 🤷 ✋ 1 ms 21.7 MB
subject-reduction-redex 🤷 👍 3 ms 22.3 MB
subject-reduction-reduct 🤷 ✋ 3 ms 22.9 MB
9 12 ms 21.9 MB
extra-rec ✋ ✋ 1 ms 21.8 MB
level-index-out-of-order 👍 👍 1 ms 21.6 MB
nat-lit-add 👍 👍 2 ms 21.9 MB
nat-lit-add-bad ✋ ✋ 2 ms 21.8 MB
nat-lit-ble 👍 👍 2 ms 21.8 MB
nat-lit-sub 👍 👍 2 ms 21.9 MB
orphan-ctor ✋ ✋ 1 ms 21.6 MB
proj-of-prop ✋ ✋ 1 ms 21.6 MB
sparse-name-index 👍 👍 1 ms 21.7 MB
29 22.3 s (÷3.6) 1.3 GB
app-lam 👍 👍 2.4 s (÷2.1) 78.0 MB (÷18)
args-before-unfold 👍 👍 5 ms (÷6.6) 24.8 MB (÷2.7)
beta-ladder 👍 👍 668 ms (÷2.5) 47.4 MB (÷11)
church-numerals 👍 👍 17 ms (÷2.8) 31.5 MB (÷2.5)
discarded-argument 👍 👍 10 ms (÷17) 25.0 MB (÷2.6)
discarded-argument-match 👍 👍 36 ms (÷3.9) 25.3 MB (÷2.7)
folded-constant-first 👍 👍 5 ms (÷8.4) 26.8 MB (÷2.6)
folded-constant-last 👍 👍 5 ms (÷8.4) 26.8 MB (÷2.6)
fueled-chain 👍 👍 102 ms (-19%) 26.9 MB (÷2.8)
grind-ring-5 👍 👍 809 ms (÷2.7) 86.3 MB (÷2.6)
identical-nesting 👍 👍 1 ms (÷24) 21.5 MB (÷3.1)
irrelevance-before-evaluation 👍 👍 1 ms (÷23) 21.6 MB (÷3.1)
let-fold 👍 👍 12 ms (÷5.0) 22.9 MB (÷2.9)
let-ladder 👍 👍 366 ms (÷2.8) 36.9 MB (÷8.7)
magma-list-deep-n21 👍 👍 389 ms (÷6.9) 29.8 MB (÷22)
magma-list-deep-n36 👍 👍 5.2 s (÷6.8) 47.1 MB (÷171)
magma-list-pair-n21 👍 👍 6.3 s (÷2.9) 1.3 GB (÷3.0)
magma-list-pair-n7 👍 👍 540 ms (÷3.1) 128.7 MB (÷3.3)
magma-string-n4 👍 👍 1.8 s (-48%) 55.5 MB (÷2.2)
magma-string-pair-n9 👍 👍 3.4 s (÷2.4) 158.4 MB (÷6.3)
proj-cheap-struct 👍 👍 3 ms (÷12) 22.0 MB (÷3.0)
proj-lazy-struct 👍 👍 2 ms (÷16) 22.0 MB (÷3.0)
proj-stuck-struct 👍 👍 2 ms (÷15) 21.9 MB (÷3.0)
refute-cheap-first ✋ ✋ 10 ms (÷4.1) 25.6 MB (÷2.7)
refute-cheap-last ✋ ✋ 10 ms (÷18) 25.8 MB (÷2.7)
repeated-subproblem 👍 👍 1 ms (÷21) 21.5 MB (÷3.1)
shared-subterm 👍 👍 19 ms (÷3.1) 28.7 MB (÷2.5)
shift-cascade 👍 👍 88 ms (+91%) 33.3 MB (÷2.0)
unroll-versus-evaluate 👍 👍 1 ms (÷22) 21.8 MB (÷3.0)
141 160 ms 22.3 MB
001_basicDef 👍 👍 1 ms 21.6 MB
002_badDef ✋ ✋ 1 ms 21.7 MB
003_arrowType 👍 👍 1 ms 21.5 MB
004_dependentType 👍 👍 1 ms 21.6 MB
005_constType 👍 👍 1 ms 21.6 MB
006_betaReduction 👍 👍 1 ms 21.7 MB
007_betaReduction2 👍 👍 1 ms 21.4 MB
008_forallSortWhnf 👍 👍 1 ms 21.7 MB
009_forallSortBad ✋ ✋ 1 ms 21.7 MB
010_nonTypeType ✋ ✋ 1 ms 21.5 MB
011_nonTypeAxiom ✋ ✋ 1 ms 21.7 MB
012_nonPropThm ✋ ✋ 1 ms 21.6 MB
013_thmProof 👍 👍 1 ms 21.8 MB
014_selfProof ✋ ✋ 1 ms 21.6 MB
015_levelComp1 👍 👍 1 ms 21.7 MB
016_levelComp2 👍 👍 1 ms 21.5 MB
017_levelComp3 👍 👍 1 ms 21.7 MB
018_levelParams 👍 👍 1 ms 21.7 MB
019_tut06_bad01 ✋ ✋ 1 ms 21.7 MB
020_levelComp4 👍 👍 1 ms 21.8 MB
021_levelComp5 👍 👍 1 ms 21.6 MB
022_imax1 👍 👍 1 ms 21.7 MB
023_imax2 👍 👍 1 ms 21.7 MB
024_levelMaxComm 👍 👍 1 ms 21.7 MB
025_levelMaxAssoc 👍 👍 1 ms 21.5 MB
026_levelMaxIdem 👍 👍 1 ms 21.7 MB
027_levelMaxAbsorb 👍 👍 1 ms 21.5 MB
028_inferVar 👍 👍 1 ms 21.7 MB
029_defEqLambda 👍 👍 1 ms 21.6 MB
030_peano1 👍 👍 1 ms 21.5 MB
031_peano2 👍 👍 1 ms 21.8 MB
032_peano3 👍 👍 1 ms 21.6 MB
033_letType 👍 👍 1 ms 21.7 MB
034_letTypeDep 👍 👍 1 ms 21.7 MB
035_letRed 👍 👍 1 ms 21.8 MB
036_empty 👍 👍 1 ms 21.8 MB
037_boolType 👍 👍 1 ms 21.5 MB
038_twoBool 👍 👍 1 ms 21.6 MB
039_andType 👍 👍 1 ms 21.6 MB
040_prodType 👍 👍 1 ms 21.9 MB
041_pprodType 👍 👍 1 ms 21.7 MB
042_pUnitType 👍 👍 1 ms 21.7 MB
043_eqType 👍 👍 1 ms 21.6 MB
044_natDef 👍 👍 1 ms 21.8 MB
045_rbTreeDef 👍 👍 1 ms 21.8 MB
046_inductBadNonSort ✋ ✋ 1 ms 21.6 MB
047_inductBadNonSort2 ✋ ✋ 1 ms 21.7 MB
048_inductLevelParam ✋ ✋ 1 ms 21.6 MB
049_inductTooFewParams ✋ ✋ 1 ms 21.6 MB
050_inductWrongCtorParams ✋ ✋ 1 ms 21.7 MB
051_inductWrongCtorResParams ✋ ✋ 1 ms 21.6 MB
052_inductWrongCtorResLevel ✋ ✋ 1 ms 21.7 MB
053_inductInIndex ✋ ✋ 1 ms 21.9 MB
054_indNeg ✋ ✋ 1 ms 21.7 MB
055_reduceCtorParam.mk 👍 👍 1 ms 21.5 MB
056_reduceCtorType.mk ✋ ✋ 1 ms 21.6 MB
057_indNegReducible ✋ ✋ 1 ms 21.5 MB
058_predWithTypeField 👍 👍 1 ms 21.7 MB
059_typeWithTypeField 👍 👍 1 ms 21.6 MB
060_typeWithTypeFieldPoly 👍 👍 1 ms 21.5 MB
061_typeWithTooHighTypeField.mk ✋ ✋ 1 ms 21.6 MB
062_emptyRec 👍 👍 1 ms 21.7 MB
063_boolRec 👍 👍 1 ms 21.5 MB
064_twoBoolRec 👍 👍 1 ms 21.7 MB
065_andRec 👍 👍 1 ms 21.6 MB
066_prodRec 👍 👍 1 ms 21.6 MB
067_pprodRec 👍 👍 1 ms 21.8 MB
068_punitRec 👍 👍 1 ms 21.5 MB
069_eqRec 👍 👍 1 ms 21.7 MB
070_nRec 👍 👍 1 ms 21.6 MB
071_rbTreeRef 👍 👍 2 ms 21.4 MB
072_boolPropRec 👍 👍 1 ms 21.8 MB
073_BogusRecursor ✋ ✋ 1 ms 21.7 MB
074_existsRec 👍 👍 1 ms 21.6 MB
075_typeSingletonRecReduction 👍 👍 1 ms 21.6 MB
076_sortElimPropRec 👍 👍 1 ms 21.6 MB
077_sortElimProp2Rec 👍 👍 1 ms 21.6 MB
078_boolRecEqns 👍 👍 1 ms 21.5 MB
079_prodRecEqns 👍 👍 1 ms 21.8 MB
080_nRecReduction 👍 👍 1 ms 21.6 MB
081_listRecReduction 👍 👍 1 ms 21.8 MB
082_RBTree.id_spec 👍 👍 3 ms 22.3 MB
083_And.right 👍 👍 1 ms 21.6 MB
084_Prod.snd 👍 👍 1 ms 21.6 MB
085_PProd.snd 👍 👍 1 ms 21.6 MB
086_PSigma.snd 👍 👍 1 ms 21.7 MB
087_projOutOfRange ✋ ✋ 1 ms 21.8 MB
088_projNotStruct ✋ ✋ 1 ms 21.7 MB
089_projProp1 👍 👍 1 ms 21.7 MB
090_projProp2 ✋ ✋ 1 ms 21.6 MB
091_projProp3 👍 👍 1 ms 21.7 MB
092_projProp4 ✋ ✋ 1 ms 21.7 MB
093_projProp5 ✋ ✋ 1 ms 21.7 MB
094_projProp6 ✋ ✋ 1 ms 21.7 MB
095_projDataIndexRec 👍 👍 1 ms 21.8 MB
096_projIndexData ✋ ✋ 1 ms 21.6 MB
097_projIndexData2 ✋ ✋ 1 ms 21.6 MB
098_projRed 👍 👍 1 ms 21.8 MB
099_ruleK 👍 👍 1 ms 21.8 MB
100_ruleKbad ✋ ✋ 1 ms 21.6 MB
101_ruleKAcc ✋ ✋ 1 ms 21.5 MB
102_aNatLit 👍 👍 1 ms 21.8 MB
103_natLitEq 👍 👍 1 ms 21.8 MB
104_proofIrrelevance 👍 👍 1 ms 21.6 MB
105_proofIrrelevanceBad ✋ ✋ 1 ms 21.7 MB
106_proofIrrelevanceWhnf 👍 👍 1 ms 21.7 MB
107_proofIrrelevanceUnderBinder 👍 👍 1 ms 21.9 MB
108_unitEta1 👍 👍 1 ms 21.7 MB
109_unitEta2 👍 👍 1 ms 21.6 MB
110_unitEta3 👍 👍 1 ms 21.6 MB
111_indexedUnitEta ✋ ✋ 1 ms 21.7 MB
112_structEta 👍 👍 1 ms 21.7 MB
113_indexedStructEta ✋ ✋ 1 ms 21.6 MB
114_funEta 👍 👍 1 ms 21.6 MB
115_funEtaDep 👍 👍 1 ms 21.5 MB
116_funEtaBad ✋ ✋ 1 ms 21.5 MB
117_reflOccLeft ✋ ✋ 1 ms 21.7 MB
118_reflOccInIndex ✋ ✋ 1 ms 21.8 MB
119_reduceCtorParamRefl.mk 👍 👍 1 ms 21.6 MB
120_reduceCtorParamRefl2.mk 👍 👍 1 ms 21.6 MB
121_rTreeRec 👍 👍 1 ms 21.7 MB
122_rtreeRecReduction 👍 👍 1 ms 21.6 MB
123_accRecType 👍 👍 1 ms 21.6 MB
124_accRecReduction 👍 👍 1 ms 21.7 MB
125_accRecNoEta ✋ ✋ 1 ms 21.6 MB
126_quotMkType 👍 👍 1 ms 21.5 MB
127_quotIndType 👍 👍 1 ms 21.6 MB
128_quotLiftType 👍 👍 1 ms 21.6 MB
129_quotSoundType 👍 👍 1 ms 21.7 MB
130_quotLiftReduction 👍 👍 1 ms 21.7 MB
131_quotIndReduction 👍 👍 1 ms 21.8 MB
132_dup_defs ✋ ✋ 1 ms 21.8 MB
133_dup_ind_def ✋ ✋ 1 ms 21.9 MB
134_dup_ctor_def ✋ ✋ 1 ms 22.2 MB
135_dup_rec_def ✋ ✋ 1 ms 21.9 MB
136_misnamed_rec_user ✋ ✋ 1 ms 21.6 MB
137_dup_rec_def2 ✋ ✋ 1 ms 21.6 MB
138_dup_ctor_rec ✋ ✋ 1 ms 21.9 MB
139_DupConCon ✋ ✋ 1 ms 21.6 MB
140_falseFromUnsafe ✋ ✋ 1 ms 21.6 MB
141_falseFromPartial ✋ ✋ 1 ms 21.5 MB

Detailed results

Test "bugs/constlevels"

Expected: ✋ reject · Size: 15.3 KB · Lines: 283 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Regression test for undefined behavior in lazy_delta_reduction_step in the official kernel

In the function lazy_delta_reduction_step, the official kernel expects unfold_definition to always succeed. However, if the constant has an incorrect number of level parameters, it actually fails, which leads to memory corruption in lazy_delta_reduction_step.

This test is to check that the official kernel and also other kernels that closely follow the logic of the official kernel correctly handle this unfolding failure.

The issue in the official kernel was originally reported as https://github.com/leanprover/lean4/issues/10577.

Test result: ✋ rejected · exit code 1 · wall time: 56 ms · instructions: 8.0 M · max rss memory: 21.6 MB

stderr:
loaded 12 declarations, 204 exprs (204 unique), 63 names in 0.000346058s
declaration order verified in 2.575e-06s
environment built in 3.3052e-05s; checking with 4 worker processes
FAIL _test (line 283): let value type mismatch for 'x'
checked 11 declarations, 1 failed, in 0.00293292s wall (2.27176e-06 core-hours over 4 workers); 4 reduction steps; peak 20 MB in one worker

Test "bugs/ctor-num-fields"

Expected: ✋ reject · Size: 34.1 KB · Lines: 622 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Proof of False via trusted numFields on a constructor.

Define a wrapper structure S with one field, and lie by saying it has 0 fields, making it look unit-like. Then definitional eta means all inhabitants are equal.

Derive a contradiction from S.mk false = S.mk true.

Nanoda and its descendants accepted this until it was fixed.

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 8.3 M · max rss memory: 22.0 MB

stderr:
loaded 25 declarations, 465 exprs (465 unique), 124 names in 0.000254997s
declaration order verified in 5.039e-06s
environment built in 2.0659e-05s; checking with 4 worker processes
FAIL _private.Test.0.S (line 235): constructor field/parameter/index counts do not match: _private.Test.0.S.mk
checked 7 declarations, 1 failed, in 0.00310107s wall (2.0987e-06 core-hours over 4 workers); 2 reduction steps; peak 20 MB in one worker

Test "bugs/eta-ctor-alias"

Expected: ✋ reject · Size: 7.2 KB · Lines: 122 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Bogus proof that f = Box.mk for every f : BoxFn, where BoxFn is a reducible alias for Bool → Box.

A checker that eta-expands a partially applied constructor (see corner-cases/eta-ctor) has to take the missing arguments from the type of the constructor application. Taking them from the type of the other side without unfolding it, here BoxFn, finds no arguments to add, then compares the (zero) given fields only, and accepts.

This bug was found by phiferd in a draft of https://github.com/leanprover/lean4/pull/15373 to the official kernel, and fixed before it was merged.

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 7.1 M · max rss memory: 21.7 MB

stderr:
loaded 5 declarations, 85 exprs (85 unique), 28 names in 0.000189274s
declaration order verified in 7.363e-06s
environment built in 1.5149e-05s; checking with 4 worker processes
FAIL etaCtorAlias (line 122): declaration type mismatch for 'etaCtorAlias'
  inferred: ((a : BoxFn) -> (((Eq.{1} BoxFn) #0) #0))
  declared: ((f : BoxFn) -> (((Eq.{1} BoxFn) #0) Box.mk))
checked 4 declarations, 1 failed, in 0.00209027s wall (1.39533e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "bugs/k-rec-conv"

Expected: ✋ reject · Size: 12.6 KB · Lines: 232 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Bogus proof that tests for incorrectly implemented K-like reduction.

fun x => x and fun _ => y are not convertible, but a checker that does treat them as convertible would accept the resulting theorem bad, which is true propositionally, but not definitionally.

Regression test for sokonanoda.

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 7.9 M · max rss memory: 21.7 MB

stderr:
loaded 9 declarations, 158 exprs (158 unique), 60 names in 0.000217397s
declaration order verified in 2.515e-06s
environment built in 1.9627e-05s; checking with 4 worker processes
FAIL bad (line 232): declaration type mismatch for 'bad'
  inferred: (((Eq.{1} T) t1) t1)
  declared: (((Eq.{1} T) t1) t2)
checked 8 declarations, 1 failed, in 0.00266411s wall (1.9099e-06 core-hours over 4 workers); 3 reduction steps; peak 20 MB in one worker

Test "bugs/large-elim-param"

Expected: ✋ reject · Size: 6.2 KB · Lines: 88 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Proof of False via incorrect large elimination restriction.

If the check for whether a level is surely not zero is implemented wrong, in particular if it incorrectly returns true for params, we can create a universe-polymorphic

inductive MyBool.{u} : Sort u | tt | ff

where the recursor MyBool.rec.{1,0} can do large elimination of a Prop. Because of proof irrelevance we have tt = ff, so we can derive a contradiction.

Found by Anthony Wang using Aristotle, breaking the mini checker for the T-shirt bounty; it was fixed the same day.

Test result: ✋ rejected · exit code 1 · wall time: 14 ms · instructions: 7.1 M · max rss memory: 21.8 MB

stderr:
loaded 5 declarations, 58 exprs (58 unique), 21 names in 0.00016564s
declaration order verified in 2.184e-06s
environment built in 1.6411e-05s; checking with 4 worker processes
FAIL MyBool (line 86): recursor 'MyBool.rec' should only eliminate into Prop
checked 3 declarations, 1 failed, in 0.00162661s wall (1.18232e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "bugs/large-elim-prop-bool"

Expected: ✋ reject · Size: 22.6 KB · Lines: 438 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Proof of False by allowing a Prop inductive to have the same recursor that the corresponding Type inductive would have.

Proof irrelevance makes .tt = .ff, but pick distinguishes between them.

Kiota accepted this until it was fixed.

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 8.1 M · max rss memory: 21.7 MB

stderr:
loaded 17 declarations, 318 exprs (318 unique), 95 names in 0.000317093s
declaration order verified in 3.146e-06s
environment built in 1.9937e-05s; checking with 4 worker processes
FAIL NewBool (line 307): recursor 'NewBool.rec' should only eliminate into Prop
checked 8 declarations, 1 failed, in 0.0025424s wall (1.94229e-06 core-hours over 4 workers); 28 reduction steps; peak 20 MB in one worker

Test "bugs/level-imax-leq"

Expected: ✋ reject · Size: 5.6 KB · Lines: 93 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Proof of False via incorrect universe level comparison for imax.

A correct kernel must reject leq(imax(u,v)+1, imax(u,v)), since at u=0, v=0 this becomes leq(1, 0) which is false. However, a checker that only compares the imax arguments structurally (without accounting for an accumulated successor offset) will incorrectly accept it.

This allows defining a universe-collapsing identity function down.{u,v} : Sort (succ (imax u v)) → Sort (imax u v), which is used to cast between True and False via Bool.rec at Sort (imax 0 0) = Prop.

Nanoda incorrectly accepted this proof until it was fixed.

Test result: ✋ rejected · exit code 1 · wall time: 13 ms · instructions: 6.7 M · max rss memory: 21.7 MB

stderr:
loaded 5 declarations, 59 exprs (59 unique), 22 names in 0.000113132s
declaration order verified in 1.963e-06s
environment built in 1.4076e-05s; checking with 4 worker processes
FAIL False (line 69): recursor 'False.rec' elimination universe is named 'u_1', expected 'u'
checked 0 declarations, 1 failed, in 0.00126034s wall (7.39964e-07 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "bugs/level-imax-normalization"

Expected: ✋ reject · Size: 5.8 KB · Lines: 96 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Proof of False via incorrect universe level normalization for imax.

A correct kernel must distinguish imax 0 v from succ(imax 0 v), since at v=0 these evaluate to 0 and 1 respectively. However, a level normalization algorithm that drops an accumulated successor offset when decomposing imax u (param v) will produce identical normal forms for both, causing the equivalence check to incorrectly return true.

This allows defining a universe-collapsing identity function down.{v} : Sort (succ (imax 0 v)) → Sort (imax 0 v), and then myProp : Prop := down.{0} Bool (a Prop that is computationally Bool). Proof irrelevance on myProp equates Bool.true and Bool.false, and Bool.rec maps this into False.

Test result: ✋ rejected · exit code 1 · wall time: 12 ms · instructions: 7.0 M · max rss memory: 21.8 MB

stderr:
loaded 6 declarations, 60 exprs (60 unique), 24 names in 0.000119013s
declaration order verified in 2.154e-06s
environment built in 1.4958e-05s; checking with 4 worker processes
FAIL down (line 77): declaration type mismatch for 'down'
  inferred: ((x : Sort((imax 0 v)+1)) -> Sort((imax 0 v)+1))
  declared: ((x : Sort((imax 0 v)+1)) -> Sort((imax 0 v)))
checked 5 declarations, 1 failed, in 0.00154847s wall (9.2406e-07 core-hours over 4 workers); 22 reduction steps; peak 19 MB in one worker

Test "bugs/nat-rec-k-lie"

Expected: ✋ reject · Size: 6.3 KB · Lines: 106 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Proof of False via trusted k on Nat.rec.

Lie by claiming Nat.rec is K-like. Then replace the major premise by Nat.zero, but nat literals bypasses K-like reduction, so two reduction rules disagree.

∀ n, g n holds by the first, and g 1 is False by the second.

A variant of bugs/rec-k-lie, which nanoda and its descendants accepted until it was fixed; at that time, nanoda itself rejected this variant, as it had no literal path for Nat.rec.

Test result: ✋ rejected · exit code 1 · wall time: 12 ms · instructions: 6.8 M · max rss memory: 22.0 MB

stderr:
loaded 6 declarations, 67 exprs (67 unique), 30 names in 0.000121648s
declaration order verified in 2.154e-06s
environment built in 1.5109e-05s; checking with 4 worker processes
FAIL Nat (line 59): recursor 'Nat.rec': parameter/index/motive/minor/K data differs from the derived recursor
checked 2 declarations, 1 failed, in 0.00119514s wall (8.13924e-07 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "bugs/nat-rec-rules"

Expected: ✋ reject · Size: 8.1 KB · Lines: 128 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Proof of False via incorrect recursor rule validation.

When processing an inductive type declaration, a correct kernel must verify that the generated recursor rules match the ones provided in the export data. A checker that accidentally compares the imported rules against themselves (instead of against independently constructed rules) will accept arbitrary recursor reduction behavior.

This test defines Nat with a wrong Nat.rec succ rule that always returns hzero (ignoring the induction hypothesis). Combined with a nat literal extension that hardcodes correct arithmetic for concrete nat literals but falls back to the wrong Nat.rec rules for symbolic arguments, this creates an inconsistency that yields a proof of False.

Nanoda incorrectly accepted this proof until it was fixed.

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 6.9 M · max rss memory: 21.9 MB

stderr:
loaded 6 declarations, 92 exprs (92 unique), 27 names in 0.000228979s
declaration order verified in 3.336e-06s
environment built in 1.8675e-05s; checking with 4 worker processes
FAIL False (line 91): recursor 'False.rec' elimination universe is named 'u_1', expected 'u'
checked 0 declarations, 1 failed, in 0.00261844s wall (1.58067e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "bugs/nested-unused-param"

Expected: ✋ reject · Size: 61.1 KB · Lines: 1.1 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Checks that the parameters of a nested inductive application are type-checked even when they do not appear in the auxiliary type generated during nested-inductive compilation.

When an inductive E has a constructor whose type contains a nested application L (E w) b, the elaboration of nested inductives replaces that occurrence with an auxiliary type. The argument b does not occur in the auxiliary declaration, so a checker that only checks the auxiliary type never sees b. A correct checker must still ensure b is well-typed; this test rejects if it is not.

Here b is a malformed projection C.0 (C.0 w) (applying a C projection to a value of the unrelated structure W), disguised by a hash collision. If the parameter is not checked, the bogus projection slips through and the resulting E can be used to build an axiom-free proof of False (boom). The projection is merely the payload; the property under test is that the nested-inductive parameter is checked.

Origin: reported as leanprover/lean4#14576 by @kiranandcode, with the original source recorded by @xrchz (https://github.com/xrchz/collatzlean); fixed in leanprover/lean4#14577.

Test result: ✋ rejected · exit code 1 · wall time: 20 ms · instructions: 14.5 M · max rss memory: 22.3 MB

stderr:
loaded 38 declarations, 826 exprs (826 unique), 208 names in 0.000511057s
declaration order verified in 6.483e-06s
environment built in 5.8801e-05s; checking with 4 worker processes
FAIL e (line 1048): invalid projection C.0
FAIL E (line 1036): invalid projection C.0
checked 33 declarations, 2 failed, in 0.00586346s wall (5.10621e-06 core-hours over 4 workers); 436 reduction steps; peak 22 MB in one worker

Test "bugs/orphan-rec"

Expected: ✋ reject · Size: 1.4 KB · Lines: 21 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Proof of False from a recursor that claims not to belong to any inductive type.

The export contains False exactly as the prelude has it — an empty Prop-valued inductive with no constructors — together with its ordinary False.rec. Smuggled into the same inductive block is a second recursor, named rogue, whose type is False itself, which has no motives, no minor premises and no rules, and whose all field is the empty list. The theorem inconsistent : False is then simply rogue.

This is the sibling of other/extra-rec, and it defeats the obvious fix for it. A checker that associates each exported recursor with the inductive type named in its all field, and then requires the recursors so associated with an inductive type to be exactly the ones it derives from that declaration, still accepts rogue: False is associated with False.rec and nothing else, and rogue is associated with nothing at all, so no comparison ever looks at it — yet it is added to the environment and inhabits the genuine empty type.

A checker must therefore reject any recursor it did not itself derive from an inductive declaration, rather than only checking the recursors that point at one. The same hole is reachable by pointing all at a name that has no declaration in the export (that variant is what other/orphan-ctor does on the constructor side).

Nanoda accepted this export until it was fixed.

Test result: ✋ rejected · exit code 1 · wall time: 14 ms · instructions: 6.4 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 10 exprs (10 unique), 7 names in 0.000100448s
declaration order verified in 2.895e-06s
environment built in 1.6852e-05s; checking with 4 worker processes
FAIL False (line 18): recursor count mismatch for 'False': export has 2, derived 1
checked 0 declarations, 1 failed, in 0.00160308s wall (1.0179e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "bugs/proj-non-structure"

Expected: ✋ reject · Size: 5.0 KB · Lines: 75 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Bad has two constructors, so projections should not be allowed. Prove false by using the second constructor, then projecting, hoping that the first constructor is used when inferring the type of the projection.

Nanoda and its descendants accepted this until it was fixed.

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 6.8 M · max rss memory: 21.9 MB

stderr:
loaded 4 declarations, 48 exprs (48 unique), 21 names in 0.000142507s
declaration order verified in 3.988e-06s
environment built in 1.5979e-05s; checking with 4 worker processes
FAIL bad (line 75): invalid projection Bad.0
checked 3 declarations, 1 failed, in 0.00222876s wall (1.42149e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "bugs/proj-of-imax-prop"

Expected: ✋ reject · Size: 19.3 KB · Lines: 321 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A closed proof of False, with no axioms, via a data projection out of a proposition whose sort is Prop only up to universe level normalization.

ImaxProp : Sort (imax 1 0) is a proposition, since imax 1 0 normalizes to 0. The exploit uses two definitionally equal spellings of that type. Proof irrelevance is stated through ImaxAsProp : Prop := ImaxProp, whose type is the literal Sort 0, so it is accepted; the data projection imaxProjBool is stated on ImaxProp, whose type is the literal Sort (imax 1 0). A kernel that tests sorts for Prop syntactically does not recognize the latter as a proposition and wrongly allows projecting its Bool field out of a proof. Congruence on the proof-irrelevance equation then equates false and true, giving False.

This is https://github.com/leanprover/lean4/pull/14613, a bug in the official kernel.

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 7.9 M · max rss memory: 21.6 MB

stderr:
loaded 19 declarations, 217 exprs (217 unique), 80 names in 0.000175229s
declaration order verified in 2.615e-06s
environment built in 1.9627e-05s; checking with 4 worker processes
FAIL imaxProjBool (line 245): invalid projection ImaxProp.0
checked 12 declarations, 1 failed, in 0.00235681s wall (1.689e-06 core-hours over 4 workers); 6 reduction steps; peak 20 MB in one worker

Test "bugs/proj-of-stuck-prop"

Expected: ✋ reject · Size: 275.7 KB · Lines: 5.3 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Proof of False by projecting the Bool field out of a proposition, exploiting that a kernel can disagree with itself about whether the structure lives in Prop.

Same underlying defect as bugs/rec-missing-ih, but with a different consequence.

Mechanism

  1. Definitional equality is not transitive here. Three functions Bool → Bool are built from Acc.rec such that a kernel reports rcA ≡ rcB and rcB ≡ rcC — both by proof irrelevance on the Acc argument — while rcA ≢ rcC, because there the two Acc proofs have different types.

  2. In the affected kernels, the defeq cache closes that relation transitively, but only for hash-equal terms. Established equalities are kept in a union-find structure, and the comparison returns early, without consulting it, when the hashes differ:

    ~~~cpp if (is_eqp(a, b)) return true; if (m_use_hash && hash(a) != hash(b)) return false; // skips the union-find ... node_ref r1 = find(to_node(a)); node_ref r2 = find(to_node(b)); if (r1 == r2) return true; ~~~

    So whether rcA ≡ rcC holds depends on the hash of the surrounding term. The constants and paddings are chosen so that the hashes collide exactly when the argument is the free variable _kernel_fresh.0, and not for the closed instantiation used later.

  3. That comparison decides a result sort. Native64ResultSortGate is a K-like inductive predicate, and its recursor is used as the result sort of the inductive family Native64ResultSortOwner: the sort Gate.rec x … Prop requested h reduces to Prop only if the requested indices are definitionally equal to the ones of Gate.intro. Hence Owner x h is a proposition in one context and a stuck sort in another:

    • Native64ResultSort.asProp is checked against a constant standing for ∀ x h, Prop, so the kernel introduces _kernel_fresh.0 for x, the hashes collide, Owner x h : Prop is accepted, and Native64ResultSortLeak.proposition is a Prop for every later declaration — including for proof irrelevance.
    • Native64ResultSortLeak.observe projects field 0 out of that proposition. There the sort of the closed term Owner false closedGate is needed, and that one is stuck — the affected kernels answer false when asked whether it is definitionally equal to Prop — so they do not see a proposition and permit projecting out the Bool field.

Proof irrelevance then identifies two Owner.mk applications carrying different Bool fields, and observing them yields False. The affected kernels rejected Native64ResultSortOwner with type expected as soon as the hashes no longer collided.

This was accepted by the official kernel at v4.28.0, v4.29.1, v4.33.0 and nightly-2026-08-01. Other kernels reject the export in one of two places: either they refuse Native64ResultSortOwner because its result type does not reduce to a sort, or they accept the type but refuse the projection of a data field out of a proposition.

Both steps are ruled out now: the projection by leanprover/lean4#14807, which makes the kernel's is_prop check require the inferred type to reduce to a sort, and the hash-gated transitivity of step 2 by leanprover/lean4#14806, which replaces the union-find defeq cache with an order-independent one. The same projection, reached without any help from that cache, is bugs/proj-of-subst-prop.

Test result: ✋ rejected · exit code 1 · wall time: 23 ms · instructions: 52.3 M · max rss memory: 26.1 MB

stderr:
loaded 120 declarations, 4367 exprs (4367 unique), 755 names in 0.000797073s
declaration order verified in 1.9426e-05s
environment built in 4.9383e-05s; checking with 4 worker processes
FAIL Native64ResultSort.asProp (line 4735): application type mismatch in ((id.{1} Sort(0)) ((Native64ResultSortOwner $0) $2))
  argument type: ((((((((Native64ResultSortGate.rec.{2} $0) (fun (index : Bool) => (fun (index : Bool) => (fun (index : Bool) => (fun (index : Bool) => (fun (proof : (((((Native64ResultSortGate $0) #3) #2) #1) #0)) => Sort(1))))))) Sort(0)) (Native64SortGateB.0.3766726852 ((fun (salt : Nat) => $0) (((OfNat.ofNat.{0} Nat) 125330) (instOfNatNat 125330))))) (Native64SortGateA.1.2023879994 ((fun (salt : Nat) => $0) (((OfNat.ofNat.{0} Nat) 125330) (instOfNatNat 125330))))) (Native64SortGateA.1.2023879994 ((fun (salt : Nat) => $0) (((OfNat.ofNat.{0} Nat) 125330) (instOfNatNat 125330))))) (Native64SortGateA.1.2023879994 ((fun (salt : Nat) => $0) (((OfNat.ofNat.{0} Nat) 125330) (instOfNatNat 125330))))) $2)
  expected: Sort(0)
FAIL Native64ResultSortOwner (line 4727): type expected: ((((((((Native64ResultSortGate.rec.{2} $8) (fun (index : Bool) => (fun (index : Bool) => (fun (index : Bool) => (fun (index : Bool) => (fun (proof : (((((Native64ResultSortGate $8) #3) #2) #1) #0)) => Sort(1))))))) Sort(0)) (Native64SortGateB.0.3766726852 ((fun (salt : Nat) => $8) (((OfNat.ofNat.{0} Nat) 125330) (instOfNatNat 125330))))) (Native64SortGateA.1.2023879994 ((fun (salt : Nat) => $8) (((OfNat.ofNat.{0} Nat) 125330) (instOfNatNat 125330))))) (Native64SortGateA.1.2023879994 ((fun (salt : Nat) => $8) (((OfNat.ofNat.{0} Nat) 125330) (instOfNatNat 125330))))) (Native64SortGateA.1.2023879994 ((fun (salt : Nat) => $8) (((OfNat.ofNat.{0} Nat) 125330) (instOfNatNat 125330))))) $9)
checked 105 declarations, 2 failed, in 0.00893658s wall (8.53098e-06 core-hours over 4 workers); 1587 reduction steps; peak 26 MB in one worker

Test "bugs/proj-of-subst-prop"

Expected: ✋ reject · Size: 254.9 KB · Lines: 4.8 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Proof of False by projecting the Bool field out of a proposition, reached by substituting a proof of one proposition for a proof of a definitionally equal one.

Mechanism

  1. Definitional equality is not transitive here. a, b and c are three Bools built from Acc.rec such that a kernel reports a ≡ b and b ≡ c — both by proof irrelevance on the Acc argument, the latter after some iota steps — while a ≢ c, because there the two Acc proofs have different types (Acc (· < ·) 1 vs. Acc (· < ·) 0).

  2. So P := a = b and Q := a = c are definitionally equal types whose proofs behave differently. gate h := Eq.rec (motive := fun _ _ => Type) Prop h K-reduces to Prop for h : P, because that reduction only needs the type of h to be definitionally equal to the type a = a of Eq.refl a, i.e. b ≡ a. For the closed witness : Q it stays stuck, since that would need c ≡ a.

  3. An inductive family is declared over the reducing side and used on the stuck one. Owner : ∀ (h : P), gate h is accepted as a family of propositions — its recursor only eliminates into Prop. Owner witness is well-typed, since Q ≡ P, but its sort does not reduce to Prop, so the projection observe is permitted to extract the Bool field from an inhabitant.

Proof irrelevance then identifies two Owner.mk applications carrying different Bool fields, and observing them yields False, with no axioms involved.

Unlike bugs/rec-missing-ih and bugs/proj-of-stuck-prop, this needs no interference from the definitional-equality cache: every comparison above comes out the same way in a fresh type-checker session, so it is independent of whether, and how, such a cache is keyed. What it does need is that the sort of an inductive family is re-examined after a substitution that definitional equality permits.

The projection in the last step is ruled out by leanprover/lean4#14807, which makes the kernel's is_prop check require the inferred type to reduce to a sort: a stuck sort then raises (kernel) type expected instead of answering that the type is not a proposition.

Test result: ✋ rejected · exit code 1 · wall time: 21 ms · instructions: 55.6 M · max rss memory: 23.7 MB

stderr:
loaded 113 declarations, 4004 exprs (4004 unique), 712 names in 0.000858698s
declaration order verified in 2.112e-05s
environment built in 4.5796e-05s; checking with 4 worker processes
FAIL PR14806Subst.observe (line 4827): type expected: (PR14806Subst.Owner PR14806Subst.witness)
checked 111 declarations, 1 failed, in 0.00845755s wall (8.09633e-06 core-hours over 4 workers); 2405 reduction steps; peak 23 MB in one worker

Test "bugs/rec-k-lie"

Expected: ✋ reject · Size: 5.3 KB · Lines: 87 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

False theorem via trusted k on a recursor.

Define MyBool with two constructors, and lie by claiming its recursor is K-like, so the major premise is replaced by the first constructor without being examined.

disc MyBool.true is then True rather than False.

MyBool rather than Bool because a module that overwrites an imported constant cannot be re-imported by the exporter.

Nanoda and its descendants accepted this until it was fixed.

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 6.7 M · max rss memory: 21.7 MB

stderr:
loaded 5 declarations, 49 exprs (49 unique), 30 names in 0.000109244s
declaration order verified in 2.375e-06s
environment built in 1.4547e-05s; checking with 4 worker processes
FAIL MyBool (line 35): recursor 'MyBool.rec': parameter/index/motive/minor/K data differs from the derived recursor
checked 1 declarations, 1 failed, in 0.00192472s wall (9.65068e-07 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "bugs/rec-missing-ih"

Expected: ✋ reject · Size: 289.6 KB · Lines: 5.5 k · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Proof of False from a generated recursor whose reduction rule drops the induction hypothesis.

Mechanism

  1. Definitional equality is not transitive here. The test builds three functions Bool → Bool from Acc.rec for which a kernel reports rcA ≡ rcB and rcB ≡ rcC — both by proof irrelevance on the Acc argument, the latter after some iota steps — but rcA ≢ rcC, because there the two Acc proofs have different types (Acc (· < ·) 1 vs. Acc (· < ·) 0).

  2. In the affected kernels, the defeq cache closes that relation transitively, but only for hash-equal terms. Established equalities are kept in a union-find structure, and the comparison returns early, without consulting it, when the hashes differ:

    ~~~cpp if (is_eqp(a, b)) return true; if (m_use_hash && hash(a) != hash(b)) return false; // skips the union-find ... node_ref r1 = find(to_node(a)); node_ref r2 = find(to_node(b)); if (r1 == r2) return true; ~~~

    So whether rcA ≡ rcC holds depends on the hash of the surrounding term. The three constants and the two paddings are picked so that the hashes collide for the free variables that the affected implementations create while building the minor premises of the recursor (_ind_fresh.3, _ind_fresh.9), but not for the pass that builds the recursor rules (_ind_fresh.14).

  3. A K-like reduction is made to depend on that comparison. Native64TwoHashGate is a K-like inductive predicate (one parameter, four Bool indices, one field-less constructor pinning the indices), so reducing Gate.rec … h requires the indices of h's type to be definitionally equal to the ones of Gate.intro's result type. Native64TwoHashOwner.step has a recursive argument whose type is such a Gate.rec application, which therefore reduces to Owner in one pass but not in the other.

The resulting Native64TwoHashOwner.rec has a step minor premise expecting four arguments (including the induction hypothesis) but a rule that applies it to only three, so the ih binder swallows the next argument. That makes the Prop-valued badProp reduce to Bool, and a Prop with two distinguishable inhabitants gives False.

Affected kernels not only accept these declarations, they also re-derive the same broken recursor when replaying the export data. This was the case for the official kernel at v4.28.0, v4.29.1, v4.33.0 and nightly-2026-08-01. Kernels that construct the recursor independently reject the export, mostly with an error about Native64TwoHashOwner.step having an invalid occurrence of the datatype being declared — which is also what the affected kernels reported as soon as one of the hashes no longer collided.

Fixed by leanprover/lean4#14806, which replaces the union-find defeq cache with an order-independent one, so that a hash collision can no longer make a comparison succeed that fails on its own.

Test result: ✋ rejected · exit code 1 · wall time: 21 ms · instructions: 54.9 M · max rss memory: 23.7 MB

stderr:
loaded 118 declarations, 4596 exprs (4596 unique), 793 names in 0.000662852s
declaration order verified in 1.2493e-05s
environment built in 3.8682e-05s; checking with 4 worker processes
FAIL Native64TwoHashOwner (line 4811): arg #3 of 'Native64TwoHashOwner.step' has a non valid occurrence of the datatypes being declared
checked 108 declarations, 1 failed, in 0.00865516s wall (7.70263e-06 core-hours over 4 workers); 1754 reduction steps; peak 23 MB in one worker

Test "bugs/rec-of-subst-prop"

Expected: ✋ reject · Size: 269.2 KB · Lines: 5.1 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Proof of False from a Prop that carries a Type field, recovered through the recursor instead of a projection.

A second variant of bugs/proj-of-subst-prop, sharing its first two steps:

  1. Definitional equality is not transitive on three Bools built from Acc.rec — gateA ≡ gateB and gateB ≡ gateC by proof irrelevance on the Acc argument, but gateA ≢ gateC — so GateP := gateA = gateB and GateQ := gateA = gateC are definitionally equal types whose proofs behave differently under Eq.rec. resultSort h K-reduces to Prop for a variable h : GateP and stays stuck for the closed gateWitness : GateQ.

  2. Issue.Owner : ∀ (h : GateP), resultSort h is therefore accepted as a family of propositions whose constructor carries a field A : Type, while Owner gateWitness — well-typed, since GateQ ≡ GateP — has a sort that does not reduce to Prop.

Where bugs/proj-of-subst-prop then projects the field out, this variant eliminates Owner with its own Prop-only recursor into Fiber X := Acc emptyTypeRel X, which is a proposition, and recovers the data from there: Acc.rec eliminates Acc into Type, and propext transports an Acc proof between two Fiber types. Proof irrelevance identifies Owner.mk gateWitness Empty with Owner.mk gateWitness Unit, so the identity function of one type is applied to a value of the other, and Empty becomes inhabited. The proof of False uses propext and no other axiom.

Because no projection is involved, the guard that stops bugs/proj-of-subst-prop — refusing to project a data field out of a proposition — never fires here. A checker has to refuse the substitution, or the stuck result sort of Issue.Owner, instead.

Both variants are ruled out by leanprover/lean4#14807, which makes the kernel's is_prop check require the inferred type to reduce to a sort: Issue.Owner is then rejected with (kernel) type expected.

The exploit is by Daniel Selsam (OpenAI), generated with OpenAI's internal models, and is the regression test added in leanprover/lean4#14847.

Test result: ✋ rejected · exit code 1 · wall time: 21 ms · instructions: 55.3 M · max rss memory: 23.6 MB

stderr:
loaded 130 declarations, 4165 exprs (4165 unique), 780 names in 0.000840894s
declaration order verified in 1.6832e-05s
environment built in 4.9463e-05s; checking with 4 worker processes
FAIL Issue.opaqueEndpoint (line 4760): declaration type mismatch for 'Issue.opaqueEndpoint'
  inferred: ((p : Issue.ModeP) -> (((Eq.{1} Nat) ((Nat.add (Issue.modeG Issue.modeQ)) 0)) ((Nat.add (Issue.modeG Issue.modeQ)) 0)))
  declared: ((p : Issue.ModeP) -> (((Eq.{1} Nat) ((Nat.add (Issue.modeG #0)) 0)) ((Nat.add (Issue.modeG Issue.modeQ)) 0)))
checked 116 declarations, 1 failed, in 0.00956853s wall (9.01795e-06 core-hours over 4 workers); 2279 reduction steps; peak 23 MB in one worker

Test "cedar"

Expected: 👍 accept · Size: 832.0 MB · Lines: 15.3 M · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Lean formalization of, and proofs about, Cedar.

Auto-generated documentation is available at https://cedar-policy.github.io/cedar-spec/docs/.

This test case exports the whole Cedar module and as such contains even unused parts Init and Batteries.

Test result: 👍 accepted · exit code 0 · wall time: 24.1 s · instructions: 461.0 G · max rss memory: 1015.4 MB

stderr:
loaded 143203 declarations, 14152792 exprs (14152792 unique), 1019732 names in 2.36305s
declaration order verified in 0.114353s
environment built in 0.0646236s; checking with 4 worker processes
checked 143203 declarations, 0 failed, in 21.5997s wall (0.0239544 core-hours over 4 workers); 90538782 reduction steps; peak 1015 MB in one worker

Test "con-leche"

Expected: 👍 accept · Size: 525.9 MB · Lines: 10.0 M · lean4export: 3.1.0 · Lean: 4.33.0 · 📄 Declaration · 🔗 Source

The con-leche development's three theorems: the consistency proof of its verified checker — model_exists, every environment the checker accepts has a set-theoretic model, and its corollary no_proof_of_False, no proof of False is accepted — and the equivalence of its byte-level parser with a naive reference (scanLineSpec_eq_scanLineFwd), each with its dependency cone.

Test result: 👍 accepted · exit code 0 · wall time: 28.6 s · instructions: 456.7 G · max rss memory: 617.3 MB

stderr:
loaded 26819 declarations, 9679077 exprs (9679077 unique), 337090 names in 1.75534s
declaration order verified in 0.106542s
environment built in 0.0107156s; checking with 4 worker processes
checked 26819 declarations, 0 failed, in 26.8222s wall (0.0292153 core-hours over 4 workers); 79091265 reduction steps; peak 617 MB in one worker

Test "corner-cases/alg-conv-trans-acc"

Expected: 🤷 either · Size: 66.4 KB · Lines: 1.2 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

As Lean's type theory has undecidable conversion (a.k.a. definitional equality), there are bound to be gaps between so called "algorithmic" conversion (that which is implemented by a typechecker), and the "declarative" conversion.

In the official kernel, algorithmic conversion fails to be transitive. f 1 a is a normal form: a is a variable, so Acc.rec cannot fire on it. Proof irrelevance admits any other proof of Acc (· < ·) 1 in its place, and Acc.intro 1 fun _ => Acc.inv a carries a constructor at the head, so it reduces. left is that substitution, right the reduction it unblocks, and trans chains the two.

acc asks for the endpoints on their own, which means inventing the middle term: choosing, among the proofs of a proposition, the one that happens to reduce the right way. The kernel has no reason to go looking, the left side being normal already, and unfolding regardless does not terminate here, as each step makes the term larger.

References:

  • Mario Carneiro, The Type Theory of Lean, MSc thesis

Test result: ✋ rejected · exit code 1 · wall time: 22 ms · instructions: 17.6 M · max rss memory: 23.0 MB

stderr:
loaded 40 declarations, 920 exprs (920 unique), 200 names in 0.000413887s
declaration order verified in 7.284e-06s
environment built in 2.8644e-05s; checking with 4 worker processes
FAIL trans (line 1176): declaration type mismatch for 'trans'
  inferred: ((a : (((Acc.{1} Nat) (fun (x1._@.Test.1043551373._hygCtx._hyg.6 : Nat) => (fun (x2._@.Test.1043551373._hygCtx._hyg.6 : Nat) => ((((LT.lt.{0} Nat) instLTNat) #1) #0)))) (((OfNat.ofNat.{0} Nat) 1) (instOfNatNat 1)))) -> (((Eq.{1} Bool) ((f (((OfNat.ofNat.{0} Nat) 1) (instOfNatNat 1))) #0)) ((f (((OfNat.ofNat.{0} Nat) 1) (instOfNatNat 1))) #0)))
  declared: ((a : (((Acc.{1} Nat) (fun (x1._@.Test.1043551373._hygCtx._hyg.6 : Nat) => (fun (x2._@.Test.1043551373._hygCtx._hyg.6 : Nat) => ((((LT.lt.{0} Nat) instLTNat) #1) #0)))) (((OfNat.ofNat.{0} Nat) 1) (instOfNatNat 1)))) -> (((Eq.{1} Bool) ((f (((OfNat.ofNat.{0} Nat) 1) (instOfNatNat 1))) #0)) ((f (((OfNat.ofNat.{0} Nat) 0) (instOfNatNat 0))) ((((((Acc.inv.{1} Nat) (fun (x1._@.Test.1043551373._hygCtx._hyg.6 : Nat) => (fun (x2._@.Test.1043551373._hygCtx._hyg.6 : Nat) => ((((LT.lt.{0} Nat) instLTNat) #1) #0)))) (((OfNat.ofNat.{0} Nat) 1) (instOfNatNat 1))) (((OfNat.ofNat.{0} Nat) 0) (instOfNatNat 0))) #0) (Nat.lt_succ_self (((OfNat.ofNat.{0} Nat) 0) (instOfNatNat 0)))))))
checked 39 declarations, 1 failed, in 0.0064774s wall (5.85821e-06 core-hours over 4 workers); 488 reduction steps; peak 22 MB in one worker

Test "corner-cases/alg-conv-trans-acc-left"

Expected: 🤷 either · Size: 67.4 KB · Lines: 1.2 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The creative half of corner-cases/alg-conv-trans-acc. Acc.rec is stuck on the variable a, and proof irrelevance admits any other proof of Acc (· < ·) 1 in its place, including one with a constructor at the head. Given both sides, a checker verifies this immediately; producing the right-hand side unprompted is the step no algorithm takes.

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 17.4 M · max rss memory: 22.4 MB

stderr:
loaded 41 declarations, 934 exprs (934 unique), 205 names in 0.000329198s
declaration order verified in 7.515e-06s
environment built in 2.8864e-05s; checking with 4 worker processes
checked 41 declarations, 0 failed, in 0.00570179s wall (5.11178e-06 core-hours over 4 workers); 502 reduction steps; peak 22 MB in one worker

Test "corner-cases/alg-conv-trans-acc-right"

Expected: 🤷 either · Size: 67.6 KB · Lines: 1.2 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The mechanical half of corner-cases/alg-conv-trans-acc. With a constructor in the major premise, Acc.rec fires and step descends to the predecessor 0.

Test result: 👍 accepted · exit code 0 · wall time: 21 ms · instructions: 17.9 M · max rss memory: 22.3 MB

stderr:
loaded 41 declarations, 941 exprs (941 unique), 205 names in 0.000345408s
declaration order verified in 5.941e-06s
environment built in 2.6169e-05s; checking with 4 worker processes
checked 41 declarations, 0 failed, in 0.00646081s wall (5.84234e-06 core-hours over 4 workers); 639 reduction steps; peak 22 MB in one worker

Test "corner-cases/alg-conv-trans-quot"

Expected: 🤷 either · Size: 8.5 KB · Lines: 169 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

left composed with right. Quotients of propositions cause algorithmic conversion transitivity to fail because the typechecker must creatively synthesise the representative of the quotient, and proof irrelevance is definitional.

References:

  • Mario Carneiro, The Type Theory of Lean, MSc thesis

Test result: ✋ rejected · exit code 1 · wall time: 18 ms · instructions: 7.3 M · max rss memory: 21.7 MB

stderr:
loaded 6 declarations, 127 exprs (127 unique), 31 names in 0.000145062s
declaration order verified in 2.365e-06s
environment built in 1.7923e-05s; checking with 4 worker processes
FAIL trans (line 169): declaration type mismatch for 'trans'
  inferred: ((P : Sort(0)) -> ((r : ((a._@._internal._hyg.0 : #0) -> ((a._@._internal._hyg.0 : #1) -> Sort(0)))) -> ((α : Sort(1)) -> ((f : ((a : #2) -> #1)) -> ((h : ((x : #3) -> ((y : #4) -> ((a._@._internal._hyg.0 : ((#4 #1) #0)) -> (((Eq.{1} #4) (#3 #2)) (#3 #1)))))) -> ((q : ((Quot.{0} #4) #3)) -> ((z : #5) -> (((Eq.{1} #4) ((((((Quot.lift.{0, 1} #6) #5) #4) #3) #2) #1)) ((((((Quot.lift.{0, 1} #6) #5) #4) #3) #2) #1)))))))))
  declared: ((P : Sort(0)) -> ((r : ((a._@._internal._hyg.0 : #0) -> ((a._@._internal._hyg.0 : #1) -> Sort(0)))) -> ((α : Sort(1)) -> ((f : ((a : #2) -> #1)) -> ((h : ((x : #3) -> ((y : #4) -> ((a._@._internal._hyg.0 : ((#4 #1) #0)) -> (((Eq.{1} #4) (#3 #2)) (#3 #1)))))) -> ((q : ((Quot.{0} #4) #3)) -> ((z : #5) -> (((Eq.{1} #4) ((((((Quot.lift.{0, 1} #6) #5) #4) #3) #2) #1)) (#3 #0)))))))))
checked 5 declarations, 1 failed, in 0.00341123s wall (1.91529e-06 core-hours over 4 workers); 0 reduction steps; peak 21 MB in one worker

Test "corner-cases/alg-conv-trans-quot-left"

Expected: 🤷 either · Size: 8.6 KB · Lines: 173 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Quot r is a Prop, so proof irrelevance relates q and Quot.mk r z. However the official kernel does WHNF first, reducing the right side to f z, so congruence never compares the arguments.

Test result: ✋ rejected · exit code 1 · wall time: 19 ms · instructions: 7.3 M · max rss memory: 21.6 MB

stderr:
loaded 6 declarations, 131 exprs (131 unique), 31 names in 0.000117941s
declaration order verified in 2.765e-06s
environment built in 1.8565e-05s; checking with 4 worker processes
FAIL left (line 173): declaration type mismatch for 'left'
  inferred: ((P : Sort(0)) -> ((r : ((a._@._internal._hyg.0 : #0) -> ((a._@._internal._hyg.0 : #1) -> Sort(0)))) -> ((α : Sort(1)) -> ((f : ((a : #2) -> #1)) -> ((h : ((x : #3) -> ((y : #4) -> ((a._@._internal._hyg.0 : ((#4 #1) #0)) -> (((Eq.{1} #4) (#3 #2)) (#3 #1)))))) -> ((q : ((Quot.{0} #4) #3)) -> ((z : #5) -> (((Eq.{1} #4) ((((((Quot.lift.{0, 1} #6) #5) #4) #3) #2) #1)) ((((((Quot.lift.{0, 1} #6) #5) #4) #3) #2) #1)))))))))
  declared: ((P : Sort(0)) -> ((r : ((a._@._internal._hyg.0 : #0) -> ((a._@._internal._hyg.0 : #1) -> Sort(0)))) -> ((α : Sort(1)) -> ((f : ((a : #2) -> #1)) -> ((h : ((x : #3) -> ((y : #4) -> ((a._@._internal._hyg.0 : ((#4 #1) #0)) -> (((Eq.{1} #4) (#3 #2)) (#3 #1)))))) -> ((q : ((Quot.{0} #4) #3)) -> ((z : #5) -> (((Eq.{1} #4) ((((((Quot.lift.{0, 1} #6) #5) #4) #3) #2) #1)) ((((((Quot.lift.{0, 1} #6) #5) #4) #3) #2) (((Quot.mk.{0} #6) #5) #0))))))))))
checked 5 declarations, 1 failed, in 0.00351612s wall (1.95107e-06 core-hours over 4 workers); 0 reduction steps; peak 21 MB in one worker

Test "corner-cases/alg-conv-trans-quot-left-def"

Expected: 🤷 either · Size: 10.5 KB · Lines: 208 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

left with Quot.lift behind a definition. WHNF does not unfold lift, so the arguments are compared and proof irrelevance applies.

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 7.4 M · max rss memory: 21.6 MB

stderr:
loaded 8 declarations, 160 exprs (160 unique), 34 names in 0.000236584s
declaration order verified in 6.472e-06s
environment built in 2.2612e-05s; checking with 4 worker processes
checked 8 declarations, 0 failed, in 0.00431429s wall (2.39063e-06 core-hours over 4 workers); 0 reduction steps; peak 20 MB in one worker

Test "corner-cases/alg-conv-trans-quot-right"

Expected: 🤷 either · Size: 9.0 KB · Lines: 180 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Quotient computation rule.

Test result: 👍 accepted · exit code 0 · wall time: 21 ms · instructions: 7.2 M · max rss memory: 21.7 MB

stderr:
loaded 7 declarations, 136 exprs (136 unique), 32 names in 0.00020773s
declaration order verified in 2.815e-06s
environment built in 1.6702e-05s; checking with 4 worker processes
checked 7 declarations, 0 failed, in 0.00413702s wall (1.96978e-06 core-hours over 4 workers); 2 reduction steps; peak 20 MB in one worker

Test "corner-cases/eta-ctor"

Expected: 🤷 either · Size: 9.0 KB · Lines: 148 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Function eta between a partially applied constructor and a free variable. The official kernel does not trigger eta expansion here, but a checker may accept the equality by expanding the functions. See https://github.com/leanprover/lean4/issues/12520 for a discussion; the official kernel may adopt eta-expansion of partially applied constructors, see https://github.com/leanprover/lean4/pull/15373. For a bug in a draft of that change, see bugs/eta-ctor-alias.

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 7.2 M · max rss memory: 21.7 MB

stderr:
loaded 6 declarations, 104 exprs (104 unique), 34 names in 0.000174869s
declaration order verified in 2.375e-06s
environment built in 1.5689e-05s; checking with 4 worker processes
FAIL etaCtor (line 148): declaration type mismatch for 'etaCtor'
  inferred: ((a : ((proof : True) -> T)) -> (((Eq.{1} ((proof : True) -> T)) #0) #0))
  declared: ((x : ((proof : True) -> T)) -> (((Eq.{1} ((proof : True) -> T)) (T.mk (T.val (#0 True.intro)))) #0))
checked 5 declarations, 1 failed, in 0.00276466s wall (1.79659e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/eta-rec-struct"

Expected: 🤷 either · Size: 9.5 KB · Lines: 174 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Function eta between a recursor of a structure that is missing its major premise and a free variable.

Prod.rec (fun b c => a (b, c)) and a are convertible: eta-expanding the former gives fun p => Prod.rec (fun b c => a (b, c)) p, whose body reduces, by structure eta on p, to a (p.1, p.2), and that is convertible to a p. The official kernel eta-expands only when the other side is a lambda, so it rejects this, while it accepts the equation of each side with fun p => a p.

The same issue with a recursor with rule K is corner-cases/eta-rule-k. The official kernel may adopt eta-expansion of such partial recursor applications, see https://github.com/leanprover/lean4/pull/15374 and https://github.com/leanprover/lean4/issues/12520.

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 7.4 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 124 exprs (124 unique), 38 names in 0.000201869s
declaration order verified in 3.426e-06s
environment built in 1.9186e-05s; checking with 4 worker processes
FAIL etaRecStruct (line 174): declaration type mismatch for 'etaRecStruct'
  inferred: ((a : ((a._@._internal._hyg.0 : ((Prod.{0, 0} Bool) Bool)) -> Bool)) -> (((Eq.{1} ((a._@._internal._hyg.0 : ((Prod.{0, 0} Bool) Bool)) -> Bool)) #0) #0))
  declared: ((a : ((a._@._internal._hyg.0 : ((Prod.{0, 0} Bool) Bool)) -> Bool)) -> (((Eq.{1} ((a._@._internal._hyg.0 : ((Prod.{0, 0} Bool) Bool)) -> Bool)) ((((Prod.rec.{1, 0, 0} Bool) Bool) (fun (x._@.Test.3091511195._hygCtx._hyg.21 : ((Prod.{0, 0} Bool) Bool)) => Bool)) (fun (b : Bool) => (fun (c : Bool) => (#2 ((((Prod.mk.{0, 0} Bool) Bool) #1) #0)))))) #0))
checked 3 declarations, 1 failed, in 0.00336147s wall (2.50781e-06 core-hours over 4 workers); 0 reduction steps; peak 20 MB in one worker

Test "corner-cases/eta-rule-k"

Expected: 🤷 either · Size: 6.5 KB · Lines: 121 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Function eta between a partially applied recursor with rule K and a free variable. The official kernel does not trigger eta expansion here, but a checker may accept the equality by expanding the functions. See https://github.com/leanprover/lean4/issues/12520 for a discussion; the official kernel may adopt eta-expansion of such partial recursor applications, see https://github.com/leanprover/lean4/pull/15374. The same issue for a structure recursor is corner-cases/eta-rec-struct.

Test result: ✋ rejected · exit code 1 · wall time: 19 ms · instructions: 7.1 M · max rss memory: 21.9 MB

stderr:
loaded 3 declarations, 85 exprs (85 unique), 29 names in 0.000230172s
declaration order verified in 6.082e-06s
environment built in 2.0559e-05s; checking with 4 worker processes
FAIL etaRuleK (line 121): declaration type mismatch for 'etaRuleK'
  inferred: ((a : ((a._@._internal._hyg.0 : (((Eq.{1} Bool) Bool.true) Bool.true)) -> Bool)) -> (((Eq.{1} ((a._@._internal._hyg.0 : (((Eq.{1} Bool) Bool.true) Bool.true)) -> Bool)) #0) #0))
  declared: ((a : ((a._@._internal._hyg.0 : (((Eq.{1} Bool) Bool.true) Bool.true)) -> Bool)) -> (((Eq.{1} ((a._@._internal._hyg.0 : (((Eq.{1} Bool) Bool.true) Bool.true)) -> Bool)) (((((Eq.rec.{1, 1} Bool) Bool.true) (fun (x._@.Test.1420384072._hygCtx._hyg.30 : Bool) => (fun (x._@.Test.1420384072._hygCtx._hyg.32 : (((Eq.{1} Bool) Bool.true) #0)) => Bool))) (#0 ((Eq.refl.{1} Bool) Bool.true))) Bool.true)) #0))
checked 2 declarations, 1 failed, in 0.00340591s wall (2.04228e-06 core-hours over 4 workers); 0 reduction steps; peak 20 MB in one worker

Test "corner-cases/eta-struct-major-and"

Expected: 🤷 either · Size: 9.4 KB · Lines: 175 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Structure eta on a recursor's major premise, for a structure in Prop.

And.rec f ⟨x.1, x.2⟩ reduces to f x.1 x.2. And.rec f x, with a variable x : P ∧ Q, also reduces to that if the major premise is expanded by structure eta, but the official kernel does not perform structure eta on majors whose type is a proposition, so it is stuck, and conversion is not transitive (or congruent) here.

Eta for such majors is fine for structures that eliminate into every sort, like And, whose fields are all proofs. It must not be done for propositions that eliminate only into Prop, like Exists, which have no projections. The official kernel may adopt this, see https://github.com/leanprover/lean4/pull/15371, https://github.com/leanprover/lean4/issues/3213 and the overall plan in https://github.com/leanprover/lean4/issues/14977.

Test result: ✋ rejected · exit code 1 · wall time: 19 ms · instructions: 7.6 M · max rss memory: 21.6 MB

stderr:
loaded 5 declarations, 130 exprs (130 unique), 36 names in 0.000220574s
declaration order verified in 2.224e-06s
environment built in 2.2803e-05s; checking with 4 worker processes
FAIL andMajorEta (line 175): declaration type mismatch for 'andMajorEta'
  inferred: ((P : Sort(0)) -> ((Q : Sort(0)) -> ((A : Sort(1)) -> ((f : ((a._@._internal._hyg.0 : #2) -> ((a._@._internal._hyg.0 : #2) -> #2))) -> ((x : ((And #3) #2)) -> (((Eq.{1} #2) (((((And.rec.{1} #4) #3) (fun (x._@.Test.3893811644._hygCtx._hyg.27 : ((And #4) #3)) => #3)) #1) #0)) (((((And.rec.{1} #4) #3) (fun (x._@.Test.3893811644._hygCtx._hyg.27 : ((And #4) #3)) => #3)) #1) #0)))))))
  declared: ((P : Sort(0)) -> ((Q : Sort(0)) -> ((A : Sort(1)) -> ((f : ((a._@._internal._hyg.0 : #2) -> ((a._@._internal._hyg.0 : #2) -> #2))) -> ((x : ((And #3) #2)) -> (((Eq.{1} #2) (((((And.rec.{1} #4) #3) (fun (x._@.Test.3893811644._hygCtx._hyg.27 : ((And #4) #3)) => #3)) #1) ((((And.intro #4) #3) (((And.left #4) #3) #0)) (((And.right #4) #3) #0)))) (((((And.rec.{1} #4) #3) (fun (x._@.Test.3893811644._hygCtx._hyg.27 : ((And #4) #3)) => #3)) #1) #0)))))))
checked 4 declarations, 1 failed, in 0.00406485s wall (2.4525e-06 core-hours over 4 workers); 0 reduction steps; peak 21 MB in one worker

Test "corner-cases/eta-struct-major-and-no-whnf"

Expected: 🤷 either · Size: 24.0 KB · Lines: 421 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The combination of corner-cases/eta-struct-major-and and corner-cases/eta-struct-major-no-whnf.

andConst h is And.rec (fun _ _ => 1) h, applied here to a proof of True ∧ True that has no weak head normal form (built from Coquand's paradox, via propext). A checker that eta-expands the And major premise before reducing it accepts the equation with 1 immediately. A checker that first reduces the major premise does not terminate, and the official kernel today, which reduces the major and then does not eta-expand propositions, does not terminate either.

This shows why, once eta applies to majors in Prop, the expansion has to happen before reduction: proofs need not normalize, and otherwise that non-termination leaks into the conversion of data. See https://github.com/leanprover/lean4/pull/15351, https://github.com/leanprover/lean4/pull/15371 and https://github.com/leanprover/lean4/issues/14977.

Test result: ⌛ timeout · exit code -9 · wall time: 1.0 m · max rss memory: 0 B

stderr:
Killed after exceeding the timeout of 1.0 m.
loaded 18 declarations, 309 exprs (309 unique), 89 names in 0.000368321s
declaration order verified in 3.095e-06s
environment built in 2.7361e-05s; checking with 4 worker processes

Test "corner-cases/eta-struct-major-no-whnf"

Expected: 🤷 either · Size: 32.2 KB · Lines: 582 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Structure eta on a recursor's major premise, applied before trying to reduce the major to a constructor.

prodConst loopPair is Prod.rec (fun _ _ => 1) loopPair, and loopPair is an Acc.rec whose major premise is a proof with no weak head normal form (built from Coquand's paradox, via propext). A checker that first reduces the major premise to weak head normal form, as the official kernel does today, does not terminate here. Expanding the major premise to (loopPair.1, loopPair.2) first lets the recursor fire without ever looking at loopPair, and the equation with 1 holds.

The result of the reduction is the same either way (structure eta is part of the theory), so the question is only one of termination of the algorithm. The official kernel may adopt this order, see https://github.com/leanprover/lean4/pull/15351 and the overall plan in https://github.com/leanprover/lean4/issues/14977.

Test result: ⌛ timeout · exit code -9 · wall time: 1.0 m · max rss memory: 0 B

stderr:
Killed after exceeding the timeout of 1.0 m.
loaded 22 declarations, 434 exprs (434 unique), 118 names in 0.000386634s
declaration order verified in 6.802e-06s
environment built in 2.3714e-05s; checking with 4 worker processes

Test "corner-cases/eta-unit-like-nested"

Expected: 🤷 either · Size: 16.0 KB · Lines: 256 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Unit-like eta for a structure whose fields are proofs, Unit, and (after instantiating the parameters) a function into a unit-like structure.

The official kernel applies eta for unit-like types (any two inhabitants are convertible) only to structures without fields. With that criterion, conversion is not transitive: both p and q are convertible to the same canonical inhabitant (e.g. fun _ => () or ⟨()⟩), but not to each other. Extending the criterion to Pi types whose codomain is unit-like and to structures whose fields are all proofs or unit-like fixes that. The official kernel may adopt this, see https://github.com/leanprover/lean4/pull/15372, https://github.com/leanprover/lean4/issues/2258 and the overall plan in https://github.com/leanprover/lean4/issues/14977.

Test result: ✋ rejected · exit code 1 · wall time: 35 ms · instructions: 8.1 M · max rss memory: 21.6 MB

stderr:
loaded 9 declarations, 191 exprs (191 unique), 51 names in 0.000458589s
declaration order verified in 4.358e-06s
environment built in 5.0535e-05s; checking with 4 worker processes
FAIL unitLikeNested (line 256): declaration type mismatch for 'unitLikeNested'
  inferred: ((p : ((Mixed Nat) ((a._@._internal._hyg.0 : Bool) -> UnitField))) -> ((a : ((Mixed Nat) ((a._@._internal._hyg.0 : Bool) -> UnitField))) -> (((Eq.{1} ((Mixed Nat) ((a._@._internal._hyg.0 : Bool) -> UnitField))) #0) #0)))
  declared: ((p : ((Mixed Nat) ((a._@._internal._hyg.0 : Bool) -> UnitField))) -> ((q : ((Mixed Nat) ((a._@._internal._hyg.0 : Bool) -> UnitField))) -> (((Eq.{1} ((Mixed Nat) ((a._@._internal._hyg.0 : Bool) -> UnitField))) #1) #0)))
checked 8 declarations, 1 failed, in 0.00840248s wall (5.02684e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/eta-unit-like-pi"

Expected: 🤷 either · Size: 5.6 KB · Lines: 101 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Unit-like eta for a function type: any two p q : α → Unit are equal.

The official kernel applies eta for unit-like types (any two inhabitants are convertible) only to structures without fields. With that criterion, conversion is not transitive: both p and q are convertible to the same canonical inhabitant (e.g. fun _ => () or ⟨()⟩), but not to each other. Extending the criterion to Pi types whose codomain is unit-like and to structures whose fields are all proofs or unit-like fixes that. The official kernel may adopt this, see https://github.com/leanprover/lean4/pull/15372, https://github.com/leanprover/lean4/issues/2258 and the overall plan in https://github.com/leanprover/lean4/issues/14977.

Test result: ✋ rejected · exit code 1 · wall time: 25 ms · instructions: 6.9 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 71 exprs (71 unique), 22 names in 0.000211025s
declaration order verified in 9.297e-06s
environment built in 2.3844e-05s; checking with 4 worker processes
FAIL unitLikePi (line 101): declaration type mismatch for 'unitLikePi'
  inferred: ((α : Sort(1)) -> ((p : ((a._@._internal._hyg.0 : #0) -> Unit)) -> ((q : ((a._@._internal._hyg.0 : #1) -> Unit)) -> (((Eq.{1} ((a._@._internal._hyg.0 : #2) -> Unit)) #0) #0))))
  declared: ((α : Sort(1)) -> ((p : ((a._@._internal._hyg.0 : #0) -> Unit)) -> ((q : ((a._@._internal._hyg.0 : #1) -> Unit)) -> (((Eq.{1} ((a._@._internal._hyg.0 : #2) -> Unit)) #1) #0))))
checked 3 declarations, 1 failed, in 0.00282311s wall (2.2922e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/eta-unit-like-proof-field"

Expected: 🤷 either · Size: 6.5 KB · Lines: 111 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Unit-like eta for a structure in Type whose only field is a proof of True.

The official kernel applies eta for unit-like types (any two inhabitants are convertible) only to structures without fields. With that criterion, conversion is not transitive: both p and q are convertible to the same canonical inhabitant (e.g. fun _ => () or ⟨()⟩), but not to each other. Extending the criterion to Pi types whose codomain is unit-like and to structures whose fields are all proofs or unit-like fixes that. The official kernel may adopt this, see https://github.com/leanprover/lean4/pull/15372, https://github.com/leanprover/lean4/issues/2258 and the overall plan in https://github.com/leanprover/lean4/issues/14977.

Test result: ✋ rejected · exit code 1 · wall time: 25 ms · instructions: 7.0 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 78 exprs (78 unique), 25 names in 0.000273983s
declaration order verified in 2.985e-06s
environment built in 2.3554e-05s; checking with 4 worker processes
FAIL unitLikeProofField (line 111): declaration type mismatch for 'unitLikeProofField'
  inferred: ((p : ProofField) -> ((a : ProofField) -> (((Eq.{1} ProofField) #0) #0)))
  declared: ((p : ProofField) -> ((q : ProofField) -> (((Eq.{1} ProofField) #1) #0)))
checked 3 declarations, 1 failed, in 0.00336634s wall (2.4918e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/eta-unit-like-struct"

Expected: 🤷 either · Size: 6.7 KB · Lines: 115 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Unit-like eta for a structure whose only field is of type Unit.

The official kernel applies eta for unit-like types (any two inhabitants are convertible) only to structures without fields. With that criterion, conversion is not transitive: both p and q are convertible to the same canonical inhabitant (e.g. fun _ => () or ⟨()⟩), but not to each other. Extending the criterion to Pi types whose codomain is unit-like and to structures whose fields are all proofs or unit-like fixes that. The official kernel may adopt this, see https://github.com/leanprover/lean4/pull/15372, https://github.com/leanprover/lean4/issues/2258 and the overall plan in https://github.com/leanprover/lean4/issues/14977.

Test result: ✋ rejected · exit code 1 · wall time: 27 ms · instructions: 7.0 M · max rss memory: 21.7 MB

stderr:
loaded 5 declarations, 80 exprs (80 unique), 26 names in 0.000226184s
declaration order verified in 4.398e-06s
environment built in 3.0618e-05s; checking with 4 worker processes
FAIL unitLikeStruct (line 115): declaration type mismatch for 'unitLikeStruct'
  inferred: ((p : UnitField) -> ((a : UnitField) -> (((Eq.{1} UnitField) #0) #0)))
  declared: ((p : UnitField) -> ((q : UnitField) -> (((Eq.{1} UnitField) #1) #0)))
checked 4 declarations, 1 failed, in 0.00335386s wall (2.78332e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/imax-right-successor"

Expected: 🤷 either · Size: 806 B · Lines: 21 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Universe-level normalization corner cases. The declarations use imax u 1 and imax u (v + 1) where their declared types use the corresponding max levels. A checker may reject these hand-crafted exports using a more conservative normalization, or accept them by recognizing that the right operand is nonzero.

Test result: ✋ rejected · exit code 1 · wall time: 29 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 4 exprs (4 unique), 4 names in 0.000238687s
declaration order verified in 1.5138e-05s
environment built in 2.8895e-05s; checking with 4 worker processes
FAIL imaxRightOne (line 11): declaration type mismatch for 'imaxRightOne'
  inferred: Sort((imax u 1)+1)
  declared: Sort((max u 1)+1)
checked 0 declarations, 1 failed, in 0.00506972s wall (2.3091e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/let-value-type-mismatch"

Expected: 🤷 either · Size: 601 B · Lines: 13 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

A let has a mismatched annotation, but substitution removes the mismatch.

In readable notation, the exported declaration is:

def EcosystemCase : Sort 2 := let u : Sort 1 := Sort 1; u

The value Sort 1 has type Sort 2, rather than the annotated Sort 1. Checking the supplied let can therefore reject it. Substituting its value for u gives def EcosystemCase : Sort 2 := Sort 1, whose types match.

This records the choice to check the supplied annotation or first simplify the let. The discussion of this exact example supports allowing either outcome as practical checker policy, while leaving a completely authoritative answer open. This is not a false-theorem example.

Test result: ✋ rejected · exit code 1 · wall time: 32 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 5 exprs (5 unique), 4 names in 0.000241643s
declaration order verified in 3.757e-06s
environment built in 2.4646e-05s; checking with 4 worker processes
FAIL EcosystemCase (line 13): let value type mismatch for 'u'
checked 0 declarations, 1 failed, in 0.00668065s wall (3.74401e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/nested-nonuniform-param"

Expected: 🤷 either · Size: 9.2 KB · Lines: 142 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Checks that a parameter supplied to a nested inductive occurrence really acts as the datatype's parameter, i.e. that it is the parameter itself and does not change between recursive occurrences (as is already enforced for non-nested occurrences).

The inductive E : W → Type has constructor E.mk : (w : W) → L (E ⟨false⟩) → E w, where L (α : Type) is nested. The occurrence E ⟨false⟩ inside the nested L uses the constant ⟨false⟩ in the position of E's parameter, instead of the actual parameter w. That argument is type-correct, so it is not caught by merely type-checking the nested application (leanprover/lean4#14577); a correct checker must also verify that it is the expected parameter.

This particular declaration is not known to yield a proof of False: here L stores no value of type α, so the nested occurrence is phantom and E w is isomorphic to Unit for every w. The variant where L actually stores an α (so recursion would descend into an E ⟨false⟩ while the motive is fixed at E w) is already rejected by the kernel's positivity check ("non valid occurrence"). Since it is not a demonstrated unsoundness, it is not settled whether a checker should accept or reject it, so the expected outcome is either and the test does not count towards completeness or soundness.

Origin: raised by @arthur-adjedj on leanprover/lean4#14577 (https://github.com/leanprover/lean4/pull/14577#issuecomment-5101819377) as a case not covered by that PR's fix; related to leanprover/lean4#14576.

Test result: 👍 accepted · exit code 0 · wall time: 29 ms · instructions: 7.6 M · max rss memory: 21.7 MB

stderr:
loaded 4 declarations, 108 exprs (108 unique), 27 names in 0.000405409s
declaration order verified in 7.825e-06s
environment built in 2.129e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.0040662s wall (2.97779e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/positivity-whnf"

Expected: 🤷 either · Size: 4.7 KB · Lines: 81 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

A recursive occurrence appears in an unused argument of a reducible definition in a constructor field.

The declaration has the following shape:

def Ignore (A B : Type) : Type := A

inductive T : Type where
  | mk (f : Ignore Unit T -> T) : T

Ignore takes a second type argument but does not use it, so Ignore Unit T reduces to Unit. A checker that inspects the unreduced constructor field may reject the syntactic occurrence of T in the domain of the arrow. A checker that first weak-head-normalizes the field type may instead see (Unit -> T) -> T and accept it. The test therefore has outcome eithe r.

A checker may reject it syntactically or accept it after reducing the field type.

Test result: ✋ rejected · exit code 1 · wall time: 37 ms · instructions: 6.6 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 50 exprs (50 unique), 23 names in 0.000827359s
declaration order verified in 2.3134e-05s
environment built in 2.9525e-05s; checking with 4 worker processes
FAIL LALReduciblePositivity (line 81): arg #1 of 'LALReduciblePositivity.mk' has a non positive occurrence of the datatypes being declared
checked 3 declarations, 1 failed, in 0.00711132s wall (5.66241e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/proj-maybe-prop"

Expected: 🤷 either · Size: 8.1 KB · Lines: 131 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projecting out of a structure that may or may not be a proposition.

MaybeProp is a structure whose sort is a bare level parameter: a proposition for u := 0 and a data type for every other u. Lean's inductive command refuses to declare one ("the resulting universe is not Prop, but it may be Prop for some parameter values"), but the kernel accepts it. The exported definition projects out its first field, field : PUnit.{u}.

The official kernel accepts this. The field is not a proof for every u, but the projection is sound at every instantiation: MaybeProp.{u} is a proposition only for u := 0, and there the field's type PUnit.{0} is a proposition too. That is no coincidence. A structure that is not a Prop had every constructor field's universe checked against its resulting universe (see the tutorial's typeWithTooHighTypeField), here u ≤ u, and such an inequality survives instantiation — so wherever the structure does turn out to be a proposition, so do all of its fields.

At the same time, the official kernel here allows more projections than the recursor allows: MaybeProp.rec eliminates into Prop only, so this projection cannot be expressed through the recursor. The elaborator does not currently rely on this extra power, so for now it is reasonable for a checker to be more restrictive here and reject the projection — for example by asking "could this be a proposition?" and then demanding that the field be definitely a proof. See https://github.com/leanprover/lean4/issues/7637 for discussion.

Test result: 👍 accepted · exit code 0 · wall time: 35 ms · instructions: 7.2 M · max rss memory: 21.8 MB

stderr:
loaded 5 declarations, 92 exprs (92 unique), 31 names in 0.00053905s
declaration order verified in 3.537e-06s
environment built in 2.8303e-05s; checking with 4 worker processes
checked 5 declarations, 0 failed, in 0.00389852s wall (3.26269e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/proj-maybe-prop-past"

Expected: 🤷 either · Size: 8.1 KB · Lines: 131 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The same as corner-cases/proj-maybe-prop, for a projection that only has to step over such a field.

MaybeProp.tail is a proof for every u, so the field asked for here is unobjectionable even under the restrictive reading. But reaching it means walking past field, which proof depends on, and that is where the check on a genuine proposition (the tutorial's projProp6) fires. A checker that rejects corner-cases/proj-maybe-prop therefore rejects this one as well, at field 0 rather than at field 2, and that remains a reasonable choice for the same reason. See https://github.com/leanprover/lean4/issues/7637 for discussion.

Test result: 👍 accepted · exit code 0 · wall time: 36 ms · instructions: 7.1 M · max rss memory: 21.7 MB

stderr:
loaded 5 declarations, 92 exprs (92 unique), 31 names in 0.000483255s
declaration order verified in 3.667e-06s
environment built in 3.3893e-05s; checking with 4 worker processes
checked 5 declarations, 0 failed, in 0.00783918s wall (5.63184e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/proof-param-ok"

Expected: 👍 accept · Size: 2.9 KB · Lines: 53 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Keeps two proof parameters in their declared order in an inductive constructor result.

Test result: 👍 accepted · exit code 0 · wall time: 32 ms · instructions: 6.6 M · max rss memory: 21.8 MB

stderr:
loaded 1 declarations, 39 exprs (39 unique), 10 names in 0.000439773s
declaration order verified in 6.221e-06s
environment built in 2.7411e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00636536s wall (3.76003e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/proof-param-swap"

Expected: 🤷 either · Size: 2.9 KB · Lines: 53 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Swaps two proof parameters in an inductive constructor result. Checkers may either reject the swap or accept it using proof irrelevance.

Test result: ✋ rejected · exit code 1 · wall time: 33 ms · instructions: 6.5 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 39 exprs (39 unique), 10 names in 0.00043803s
declaration order verified in 9.338e-06s
environment built in 2.9105e-05s; checking with 4 worker processes
FAIL LALProofParameterSwap (line 53): invalid return type for 'LALProofParameterSwap.mk'
checked 0 declarations, 1 failed, in 0.00703697s wall (3.7105e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "corner-cases/subject-reduction-redex"

Expected: 🤷 either · Size: 66.6 KB · Lines: 1.2 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Test for subject reduction, as in Carneiro's thesis.

The annotation on the lambda writes the middle term of corner-cases/alg-conv-trans-acc down by hand, sparing the kernel from having to invent it. The body checks against right, the argument against left, and the two endpoints are never compared.

References:

  • Mario Carneiro, The Type Theory of Lean, MSc thesis

Test result: 👍 accepted · exit code 0 · wall time: 41 ms · instructions: 17.9 M · max rss memory: 22.3 MB

stderr:
loaded 42 declarations, 924 exprs (924 unique), 206 names in 0.0007316s
declaration order verified in 1.3405e-05s
environment built in 4.9984e-05s; checking with 4 worker processes
checked 42 declarations, 0 failed, in 0.0136339s wall (1.20089e-05 core-hours over 4 workers); 681 reduction steps; peak 22 MB in one worker

Test "corner-cases/subject-reduction-reduct"

Expected: 🤷 either · Size: 65.5 KB · Lines: 1.2 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Beta erases the annotation of corner-cases/subject-reduction-redex, and with it the middle term, leaving the two endpoints to compare: the conversion of corner-cases/alg-conv-trans-acc. A term the kernel accepts thus reduces to one it rejects.

References:

  • Mario Carneiro, The Type Theory of Lean, MSc thesis

Test result: ✋ rejected · exit code 1 · wall time: 38 ms · instructions: 17.4 M · max rss memory: 22.9 MB

stderr:
loaded 41 declarations, 906 exprs (906 unique), 202 names in 0.000876341s
declaration order verified in 1.9627e-05s
environment built in 6.0864e-05s; checking with 4 worker processes
FAIL reduct (line 1165): application type mismatch in ($11 $12)
  argument type: ($9 ((f (((OfNat.ofNat.{0} Nat) 1) (instOfNatNat 1))) $8))
  expected: ($9 ((f (((OfNat.ofNat.{0} Nat) 0) (instOfNatNat 0))) (redex._proof_1 $8)))
checked 40 declarations, 1 failed, in 0.0121868s wall (1.09383e-05 core-hours over 4 workers); 522 reduction steps; peak 22 MB in one worker

Test "cslib"

Expected: 👍 accept · Size: 2.3 GB · Lines: 42.7 M · lean4export: 3.1.0 · Lean: 4.34.0 · 📄 Declaration · 🔗 Source

The Lean Computer Science Library (CSLib).

Test result: 👍 accepted · exit code 0 · wall time: 2.1 m · instructions: 1.7 T · max rss memory: 2.5 GB

stderr:
loaded 383976 declarations, 40045123 exprs (40045123 unique), 2248524 names in 12.7817s
declaration order verified in 0.500623s
environment built in 0.253995s; checking with 4 worker processes
checked 383976 declarations, 0 failed, in 112.383s wall (0.124815 core-hours over 4 workers); 226710711 reduction steps; peak 2570 MB in one worker

Test "init"

Expected: 👍 accept · Size: 331.5 MB · Lines: 6.5 M · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The Init module export from Lean 4 core.

This test contains the fundamental building blocks of Lean 4, including:

  • Basic data types (Nat, List, Array, String, etc.)
  • Core tactics and syntax
  • Foundational mathematical structures
  • Essential metaprogramming infrastructure

This is one of the smallest meaningful test cases, making it ideal for initial checker validation and debugging.

Test result: 👍 accepted · exit code 0 · wall time: 10.5 s · instructions: 221.8 G · max rss memory: 392.0 MB

stderr:
loaded 58170 declarations, 6132277 exprs (6132277 unique), 296040 names in 0.770717s
declaration order verified in 0.0419569s
environment built in 0.0216061s; checking with 4 worker processes
checked 58170 declarations, 0 failed, in 9.64731s wall (0.010701 core-hours over 4 workers); 51915309 reduction steps; peak 391 MB in one worker

Test "init-prelude"

Expected: 👍 accept · Size: 3.6 MB · Lines: 64.1 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The Init.Prelude module export.

Test result: 👍 accepted · exit code 0 · wall time: 57 ms · instructions: 607.6 M · max rss memory: 29.4 MB

stderr:
loaded 1824 declarations, 54799 exprs (54799 unique), 7373 names in 0.00898535s
declaration order verified in 0.000339586s
environment built in 0.000490648s; checking with 4 worker processes
checked 1824 declarations, 0 failed, in 0.033876s wall (3.55742e-05 core-hours over 4 workers); 33480 reduction steps; peak 26 MB in one worker

Test "mathlib"

Expected: 👍 accept · Size: 5.8 GB · Lines: 109.8 M · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The complete Mathlib library export.

This test contains all the mathematical definitions, theorems, and proofs from Mathlib, representing the largest and most comprehensive test case in the Lean kernel arena.

Test result: 👍 accepted · exit code 0 · wall time: 9.1 m · instructions: 5.9 T · max rss memory: 7.0 GB

stderr:
loaded 702040 declarations, 104860875 exprs (104860875 unique), 4184135 names in 19.6254s
declaration order verified in 1.07783s
environment built in 0.500876s; checking with 4 worker processes
checked 702040 declarations, 0 failed, in 522.685s wall (0.580479 core-hours over 4 workers); 740844580 reduction steps; peak 7172 MB in one worker

Test "navier-stokes-euler"

Expected: 👍 accept · Size: 1.5 GB · Lines: 28.6 M · lean4export: 3.1.0 · Lean: 4.34.0-rc2 · 📄 Declaration · 🔗 Source

OpenAI's Lean formalization of finite-time blowup for the three-dimensional incompressible Navier–Stokes equations with smooth forcing (on Euclidean space and on the periodic torus), and of unforced Euler blowup. See https://github.com/openai/NavierStokesAndEuler/.

This test exports the main results listed in the project's formalization.yaml, together with their dependencies.

Test result: 👍 accepted · exit code 0 · wall time: 4.5 m · instructions: 2.4 T · max rss memory: 1.8 GB

stderr:
loaded 126468 declarations, 27747197 exprs (27747197 unique), 691465 names in 4.06756s
declaration order verified in 0.351429s
environment built in 0.0990128s; checking with 4 worker processes
checked 126468 declarations, 0 failed, in 268.638s wall (0.298468 core-hours over 4 workers); 405506772 reduction steps; peak 1778 MB in one worker

Test "other/extra-rec"

Expected: ✋ reject · Size: 1.4 KB · Lines: 21 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Proof of False from an extra recursor that no inductive declaration could produce.

The export contains False exactly as the prelude has it — an empty Prop-valued inductive with no constructors — together with its ordinary False.rec. Smuggled into the same inductive group is a second recursor, named rogue, whose type is False itself and which has no motives, no minor premises and no rules. The theorem inconsistent : False is then simply rogue.

A checker must derive the recursors of an inductive group from the inductive declaration and reject any exported recursor that is not one of them; here that fails on the name (rogue is not False.rec) as well as on the type. A checker that instead registers exported recursors as given ends up with an inhabitant of the genuine empty type.

This is a different gap from bugs/nat-rec-rules, which perturbs the rules of a legitimate recursor: here an entire recursor constant is fabricated, so validating only the rules of the recursors one expects does not catch it.

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 6.4 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 10 exprs (10 unique), 7 names in 0.000113002s
declaration order verified in 2.164e-06s
environment built in 1.5539e-05s; checking with 4 worker processes
FAIL False (line 18): recursor count mismatch for 'False': export has 2, derived 1
checked 0 declarations, 1 failed, in 0.00175226s wall (1.10752e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "other/level-index-out-of-order"

Expected: 👍 accept · Size: 328 B · Lines: 6 · lean4export: 0.1.0 · Lean: 4.29.1 · 📄 Declaration

Lean4export will create internalization-table references contiguously in order: in references for names, il references for levels, and ie references for expressions all work this way.

However, the spec merely requires that these are integers. It's reasonable for an implementation to assume these are approximately dense (and to treat them as array indices instead of hashtable entries), but a kernel should handle skipped indices or out-of-order indices.

This test checks that the kernel doesn't require internaliation-table references to be presented in ascending order. If the level referenes 2 and 1 were swapped, this would be the expected encoding of axiom foo : Sort 2. This encoding should be equivalent.

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 6.2 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 1 exprs (1 unique), 1 names in 0.000147307s
declaration order verified in 2.255e-06s
environment built in 2.3855e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.0031088s wall (1.43195e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "other/nat-lit-add"

Expected: 👍 accept · Size: 26.0 KB · Lines: 478 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The kernel's Nat extension reduces Nat.add applied to two literals to a literal, instead of unfolding the numerals to Nat.succ chains. The arguments here are large enough that unfolding is not a practical alternative, so a checker that only implements natLitEq-style literal↔succ conversion will not get this for free.

Exported as natAddLit : Nat.add 123456789 987654321 = 1111111110 := rfl. The application is Nat.add on .lits (not HAdd/OfNat).

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 9.4 M · max rss memory: 21.9 MB

stderr:
loaded 16 declarations, 363 exprs (363 unique), 90 names in 0.000829104s
declaration order verified in 4.989e-06s
environment built in 2.0268e-05s; checking with 4 worker processes
checked 16 declarations, 0 failed, in 0.00406637s wall (3.2585e-06 core-hours over 4 workers); 106 reduction steps; peak 20 MB in one worker

Test "other/nat-lit-add-bad"

Expected: ✋ reject · Size: 25.3 KB · Lines: 465 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The claimed result of Nat.add on two literals does not match the kernel's literal arithmetic:

natAddLitBad : Nat.add 123456789 987654321 = 1111111111
  := Eq.refl (Nat.add 123456789 987654321)

The value is well-typed as @Eq Nat (Nat.add …) (Nat.add …) and is injected with debug.skipKernelTC. A sound checker must reject the declaration type mismatch against the claimed = 1111111111.

Test result: ✋ rejected · exit code 1 · wall time: 21 ms · instructions: 9.4 M · max rss memory: 21.8 MB

stderr:
loaded 15 declarations, 352 exprs (352 unique), 89 names in 0.000926597s
declaration order verified in 5.56e-06s
environment built in 2.4736e-05s; checking with 4 worker processes
FAIL natAddLitBad (line 465): declaration type mismatch for 'natAddLitBad'
  inferred: (((Eq.{1} Nat) ((Nat.add (((OfNat.ofNat.{0} Nat) 123456789) (instOfNatNat 123456789))) (((OfNat.ofNat.{0} Nat) 987654321) (instOfNatNat 987654321)))) ((Nat.add (((OfNat.ofNat.{0} Nat) 123456789) (instOfNatNat 123456789))) (((OfNat.ofNat.{0} Nat) 987654321) (instOfNatNat 987654321))))
  declared: (((Eq.{1} Nat) ((Nat.add (((OfNat.ofNat.{0} Nat) 123456789) (instOfNatNat 123456789))) (((OfNat.ofNat.{0} Nat) 987654321) (instOfNatNat 987654321)))) (((OfNat.ofNat.{0} Nat) 1111111111) (instOfNatNat 1111111111)))
checked 14 declarations, 1 failed, in 0.00499733s wall (3.82407e-06 core-hours over 4 workers); 62 reduction steps; peak 21 MB in one worker

Test "other/nat-lit-ble"

Expected: 👍 accept · Size: 28.8 KB · Lines: 520 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Nat.ble on two literals reduces to a Bool constructor: Nat.ble 1000000 1000001 = true. Same Nat-literal extension as nat-lit-add; the result is Bool rather than Nat.

Test result: 👍 accepted · exit code 0 · wall time: 27 ms · instructions: 9.7 M · max rss memory: 21.8 MB

stderr:
loaded 17 declarations, 394 exprs (394 unique), 100 names in 0.000930153s
declaration order verified in 5.239e-06s
environment built in 3.4195e-05s; checking with 4 worker processes
checked 17 declarations, 0 failed, in 0.006456s wall (4.79418e-06 core-hours over 4 workers); 105 reduction steps; peak 20 MB in one worker

Test "other/nat-lit-sub"

Expected: 👍 accept · Size: 30.0 KB · Lines: 561 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Nat.sub on two literals truncates at zero: Nat.sub 1000000 1000001 = 0. Same Nat-literal extension as nat-lit-add; the numerals are large enough that unfolding Nat.sub to a Nat.succ recursor is not a practical path.

Test result: 👍 accepted · exit code 0 · wall time: 23 ms · instructions: 9.8 M · max rss memory: 21.9 MB

stderr:
loaded 20 declarations, 393 exprs (393 unique), 139 names in 0.000510627s
declaration order verified in 5.44e-06s
environment built in 2.8503e-05s; checking with 4 worker processes
checked 20 declarations, 0 failed, in 0.0048857s wall (4.07014e-06 core-hours over 4 workers); 129 reduction steps; peak 20 MB in one worker

Test "other/orphan-ctor"

Expected: ✋ reject · Size: 1.4 KB · Lines: 22 · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration

Proof of False from a constructor of an inductive type that does not exist.

The export contains False exactly as the prelude has it — an empty Prop-valued inductive with no constructors, its ctors field is the empty list — together with its ordinary False.rec. Smuggled into the same inductive block is a constructor named rogue, of type False, with no parameters and no fields, whose induct field names Orphan, a name for which the export has no declaration at all. The theorem inconsistent : False is then simply rogue.

A checker must derive the constructors of an inductive group from the inductive declarations and reject any exported constructor that is not one of them; here that fails because False has no constructors, and the inductive type rogue claims to come from does not exist. A checker that instead registers exported constructors as given — or that only checks constructors whose induct field points at a declaration it knows — ends up with an inhabitant of the genuine empty type.

This is the constructor-side counterpart of bugs/orphan-rec: in both cases the bogus declaration escapes by not being attached to any inductive declaration that the checker verifies, rather than by disagreeing with one.

Test result: ✋ rejected · exit code 1 · wall time: 19 ms · instructions: 6.4 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 10 exprs (10 unique), 8 names in 0.000137748s
declaration order verified in 2.394e-06s
environment built in 1.585e-05s; checking with 4 worker processes
FAIL False (line 19): constructor count mismatch in inductive block
checked 0 declarations, 1 failed, in 0.00317499s wall (1.38968e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "other/proj-of-prop"

Expected: ✋ reject · Size: 3.9 KB · Lines: 56 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A proof of False via a projection from a Prop-typed structure whose constructor was applied to an ill-typed argument. The exported term is

badFalse : False := (Wrapper.mk True.intro).p

where Wrapper : Prop has a single field p : False, so Wrapper.mk expects a proof of False but is given True.intro : True.

A sound checker must reject this. A checker that types a projection by inferring (rather than checking) its structure argument — i.e. that trusts the structure to be well-typed instead of verifying the constructor's argument types against its binders — will accept it, because Wrapper.mk True.intro still formally inhabits Wrapper at the structural level, and the p projection is then read back out at the declared field type False.

Test result: ✋ rejected · exit code 1 · wall time: 18 ms · instructions: 6.7 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 35 exprs (35 unique), 15 names in 0.000649367s
declaration order verified in 4.648e-06s
environment built in 2.685e-05s; checking with 4 worker processes
FAIL badFalse (line 56): application type mismatch in (Wrapper.mk True.intro)
  argument type: True
  expected: False
checked 3 declarations, 1 failed, in 0.00286963s wall (1.73039e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "other/sparse-name-index"

Expected: 👍 accept · Size: 292 B · Lines: 4 · lean4export: 0.1.0 · Lean: 4.29.1 · 📄 Declaration

Lean4export will create internalization-table references contiguously in order: in references for names, il references for levels, and ie references for expressions all work this way.

However, the spec merely requires that these are integers. It's reasonable for an implementation to assume these are approximately dense (and to treat them as array indices instead of hashtable entries), but a kernel should handle skipped indices or out-of-order indices.

This test checks that a kernel doesn't require internalization-table references to be assigned sequentially starting from 1. If the "2" and "4" were replaced by "1" and "0", respectively, this would be the expected encoding of axiom foo : Prop. This encoding should be equivalent.

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 6.2 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 1 exprs (1 unique), 1 names in 0.000148859s
declaration order verified in 2.815e-06s
environment built in 1.8275e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.004248s wall (2.05399e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "perf/app-lam"

Expected: 👍 accept · Size: 1.2 MB · Lines: 28.6 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A synthetically generated term with n levels of alternating applications and lambdas, with DAG sharing.

At each level, a constant is applied to two identical lambda arguments. The export format records these as a single shared expression (DAG). Each lambda body grows with the nesting depth, referencing all enclosing binders.

This tests two aspects of checker performance:

Infer cache: Since both arguments at each level are the same expression, a checker without an infer cache re-infers the type of each shared subterm, doubling work at every level — O(2ⁿ) total.

Substitution cost: Even with a cache, type-inferring each lambda requires substituting into its body (size O(n)) at each of the n levels, giving O(n²) total. Whether this cost arises depends on the checker's binder representation.

Test result: 👍 accepted · exit code 0 · wall time: 2.5 s · instructions: 14.2 G · max rss memory: 78.0 MB

stderr:
loaded 22 declarations, 24430 exprs (24430 unique), 4110 names in 0.00519336s
declaration order verified in 4.6417e-05s
environment built in 2.3775e-05s; checking with 4 worker processes
checked 22 declarations, 0 failed, in 2.45043s wall (0.000681506 core-hours over 4 workers); 72 reduction steps; peak 77 MB in one worker

Test "perf/args-before-unfold"

Expected: 👍 accept · Size: 44.5 KB · Lines: 1.2 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

count #n      and      count (N.add #(n-1) #1)

where #k is the numeral with k successors, and count #k evaluates to #k in Θ(k²) reductions.

N.add #(n-1) #1 reduces to #n in n steps, so the two arguments agree for Θ(n), and the applications agree with them without count ever being unfolded. Evaluating both applications costs Θ(n²). The test asks whether a checker tries the arguments of a shared head constant before unfolding it.

N=1000 in the Lean source. From Courant and Leroy, POPL 2026, §10.

Test result: 👍 accepted · exit code 0 · wall time: 28 ms · instructions: 32.9 M · max rss memory: 24.8 MB

stderr:
loaded 5 declarations, 1106 exprs (1106 unique), 43 names in 0.000749114s
declaration order verified in 6.222e-06s
environment built in 1.6181e-05s; checking with 4 worker processes
checked 5 declarations, 0 failed, in 0.0122932s wall (4.32649e-06 core-hours over 4 workers); 3006 reduction steps; peak 24 MB in one worker

Test "perf/beta-ladder"

Expected: 👍 accept · Size: 450.6 KB · Lines: 10.4 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check reduces

(fun x₁ => … (fun xₙ => x₁ + (x₂ + (… + (xₙ + 0)))) 0 …) 0

to 0, through n beta redexes over a body that reads every binder.

Reducing the ladder takes n beta steps whatever a checker does, so the test is what one step costs. Substituting into the body on entry to binder k copies the n − k redexes still below it, and those copies sum to Θ(n²). Carrying the substitution in an environment leaves the body untouched, for Θ(n).

N=2000 in the Lean source.

Test result: 👍 accepted · exit code 0 · wall time: 671 ms · instructions: 4.0 G · max rss memory: 47.4 MB

stderr:
loaded 12 declarations, 10284 exprs (10284 unique), 78 names in 0.00258107s
declaration order verified in 2.106e-05s
environment built in 2.4155e-05s; checking with 4 worker processes
checked 12 declarations, 0 failed, in 0.653189s wall (0.000183558 core-hours over 4 workers); 16057 reduction steps; peak 47 MB in one worker

Test "perf/church-numerals"

Expected: 👍 accept · Size: 9.6 KB · Lines: 227 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

cmul (cnum n) (cnum (n+1))      and      cmul (cnum (n+1)) (cnum n)

where cnum k is the Church numeral fun X s z => s (s (... z)) and cmul a b iterates b as many times as a counts.

Both sides have the normal form with n(n+1) applications of the bound s. Unfolding cmul on the left leaves cnum n X (cnum (n+1) X s), where each of the n occurrences of the bound function copies the redex cnum (n+1) X s, so the normal form takes n(n+1) beta steps and shares nothing. No other delta step is available, so the Θ(n²) measured is beta reduction under binders and little else.

N=120 in the Lean source, giving a reduction depth of 14520. From the conv_eval benchmark of András Kovács' smalltt.

Test result: 👍 accepted · exit code 0 · wall time: 38 ms · instructions: 101.8 M · max rss memory: 31.5 MB

stderr:
loaded 4 declarations, 197 exprs (197 unique), 21 names in 0.000463379s
declaration order verified in 6.302e-06s
environment built in 1.8444e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.0227261s wall (7.18876e-06 core-hours over 4 workers); 253 reduction steps; peak 31 MB in one worker

Test "perf/discarded-argument"

Expected: 👍 accept · Size: 15.9 KB · Lines: 367 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

dropArg (count #n)      and      dropArg (count #(n+1))

where count #k evaluates to the numeral #k in Θ(k²) reductions, and dropArg maps every numeral to N.O.

Unfolding dropArg leaves N.O against N.O, for Θ(1). Comparing the arguments first evaluates two numerals of different value, for Θ(n²), and then throws that answer away. The test asks whether a checker unfolds a constant before looking at an argument the constant never uses.

N=200 in the Lean source. From Courant and Leroy, POPL 2026, §10.

Test result: 👍 accepted · exit code 0 · wall time: 31 ms · instructions: 59.3 M · max rss memory: 25.0 MB

stderr:
loaded 6 declarations, 309 exprs (309 unique), 48 names in 0.000665838s
declaration order verified in 8.286e-06s
environment built in 2.5879e-05s; checking with 4 worker processes
checked 6 declarations, 0 failed, in 0.0139732s wall (5.18802e-06 core-hours over 4 workers); 14803 reduction steps; peak 24 MB in one worker

Test "perf/discarded-argument-match"

Expected: 👍 accept · Size: 29.2 KB · Lines: 606 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

discarded-argument.lean with count and N.add written by structural recursion, so the declaration to check is the same

dropArg (count #n)      and      dropArg (count #(n+1))

over definitions that unfold through brecOn rather than through N.rec.

brecOn reduces via the course-of-values table N.below #k = m #(k-1) ×' (m #(k-2) ×' (… ×' PUnit)), a k-deep tuple holding the result at every predecessor. The compiled count reads only x.1, so the rest of the table is built and never read, and typing each projection forces N.below to the depth of that projection.

N=200 in the Lean source, matching its pair.

Test result: 👍 accepted · exit code 0 · wall time: 50 ms · instructions: 216.5 M · max rss memory: 25.3 MB

stderr:
loaded 17 declarations, 496 exprs (496 unique), 85 names in 0.00052822s
declaration order verified in 5.25e-06s
environment built in 2.0789e-05s; checking with 4 worker processes
checked 17 declarations, 0 failed, in 0.0326205s wall (1.15305e-05 core-hours over 4 workers); 46358 reduction steps; peak 25 MB in one worker

Test "perf/folded-constant-first"

Expected: 👍 accept · Size: 52.0 KB · Lines: 1.3 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

tagged (count #n)      and      (false, count #n)

where tagged m = (isZero m, m), so unfolding the left side leaves the same application count #n in both components, forced by isZero in one and plain in the other.

The plain occurrences are identical, for Θ(1); the forced one evaluates count #n once. The order matters for a checker that leaves a constant unfolded once it reduces it: reducing the forced component first replaces count #n by its value on one side, and the plain comparison then faces a folded application against an evaluated one. Here the forcing component comes first; folded-constant-last.lean swaps them, and the ratio between the two files is what that costs.

N=1000 in the Lean source. From Courant and Leroy, POPL 2026, §10, where the two orders cost Rocq 3 × 10⁻⁵ s and 0.078 s.

Test result: 👍 accepted · exit code 0 · wall time: 27 ms · instructions: 29.0 M · max rss memory: 26.8 MB

stderr:
loaded 9 declarations, 1180 exprs (1180 unique), 65 names in 0.000552005s
declaration order verified in 5.851e-06s
environment built in 1.9457e-05s; checking with 4 worker processes
checked 9 declarations, 0 failed, in 0.0110127s wall (4.45868e-06 core-hours over 4 workers); 20033 reduction steps; peak 26 MB in one worker

Test "perf/folded-constant-last"

Expected: 👍 accept · Size: 51.0 KB · Lines: 1.3 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

tagged (count #n)      and      (count #n, false)

where tagged m = (m, isZero m): folded-constant-first.lean with the components swapped, so the plain occurrences of count #n are compared before anything forces the application.

N=1000 in the Lean source. From Courant and Leroy, POPL 2026, §10.

Test result: 👍 accepted · exit code 0 · wall time: 28 ms · instructions: 29.0 M · max rss memory: 26.8 MB

stderr:
loaded 9 declarations, 1180 exprs (1180 unique), 65 names in 0.00114226s
declaration order verified in 7.444e-06s
environment built in 2.663e-05s; checking with 4 worker processes
checked 9 declarations, 0 failed, in 0.00999062s wall (4.49205e-06 core-hours over 4 workers); 20033 reduction steps; peak 26 MB in one worker

Test "perf/fueled-chain"

Expected: 👍 accept · Size: 848.6 KB · Lines: 17.3 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Distilled from con-leche's fuel-bridge (_datF) lemmas, the declarations on which nanobruijn times out on the con-leche test.

Fueled α packages a fuel-indexed family p : Nat → Except Unit α with a proof whose type mentions p twice under binders. A _datF lemma states that running a monadic function in Fueled and extracting at fuel F equals running it in Except Unit, proved by unfolding and rewriting with the atF lemmas for bind/pure/throw/ite. What is left for the kernel is a definitional equality between two monadic programs that differ only in the monad instance, under one binder per bind and a do-notation join point per unless … throw guard.

chainN (N = 6, 9, 12) has N binds, each followed by a guard. A checker that recognises the unfolded and the literal program as equal outright is fast (nanoda: 2 ms, 18 ms, 32 ms); one that compares them structurally unfolds bind to Subtype.mk p h and, through proof irrelevance on the hs, re-compares the rest of the program twice per guard (nanobruijn: 19 ms, 4.1 s, 256 s). Without the guards it is cheap for both.

Test result: 👍 accepted · exit code 0 · wall time: 97 ms · instructions: 614.2 M · max rss memory: 26.9 MB

stderr:
loaded 143 declarations, 16168 exprs (16168 unique), 942 names in 0.0043628s
declaration order verified in 7.0753e-05s
environment built in 7.6564e-05s; checking with 4 worker processes
checked 143 declarations, 0 failed, in 0.0736392s wall (4.26464e-05 core-hours over 4 workers); 13621 reduction steps; peak 26 MB in one worker

Test "perf/grind-ring-5"

Expected: 👍 accept · Size: 9.8 MB · Lines: 200.3 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A grind tactic test from the Lean 4 test suite.

This produces a theorem with a rather large proof term that needs fast reduction.

Test result: 👍 accepted · exit code 0 · wall time: 560 ms · instructions: 4.9 G · max rss memory: 86.3 MB

stderr:
loaded 2273 declarations, 181939 exprs (181939 unique), 16048 names in 0.0325353s
declaration order verified in 0.000897783s
environment built in 0.000503915s; checking with 4 worker processes
checked 2273 declarations, 0 failed, in 0.510402s wall (0.000294453 core-hours over 4 workers); 2375752 reduction steps; peak 86 MB in one worker

Test "perf/identical-nesting"

Expected: 👍 accept · Size: 8.7 KB · Lines: 172 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

f4 (f4 (... (f4 N.O) ...))      and      f4 (f4 (... (f4 N.O) ...))

n applications of f4 on each side, the same term twice, where f0 is the identity on N and each of f1, f2, f3, f4 applies its predecessor twice, so the nesting expands into 16n applications of f0.

The test asks whether a checker compares the two sides before it starts unfolding, which answers in Θ(n). Unfolding one side at a time offers 16n applications to choose from per side, and the reachable pairs of partially unfolded sides grow exponentially in n.

N=30 in the Lean source. From Courant and Leroy, POPL 2026, §10.

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 7.1 M · max rss memory: 21.5 MB

stderr:
loaded 8 declarations, 128 exprs (128 unique), 32 names in 0.000699712s
declaration order verified in 4.9e-06s
environment built in 1.8485e-05s; checking with 4 worker processes
checked 8 declarations, 0 failed, in 0.00274816s wall (2.06691e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "perf/irrelevance-before-evaluation"

Expected: 👍 accept · Size: 17.5 KB · Lines: 388 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check is

slowTriv (count #n) = True.intro

proved by Eq.refl, where slowTriv m : True recurses over m, so forcing it to a constructor evaluates the numeral in Θ(n²) reductions.

Checking compares the two proofs as arguments of Eq, whose head is rigid: nothing can be unfolded instead. Proof irrelevance settles the proofs by their type for Θ(1); evaluating the left one to a constructor costs Θ(n²) and yields the answer irrelevance already gave. The test asks whether a checker consults proof irrelevance before it reduces.

N=200 in the Lean source.

Test result: 👍 accepted · exit code 0 · wall time: 22 ms · instructions: 7.5 M · max rss memory: 21.6 MB

stderr:
loaded 7 declarations, 324 exprs (324 unique), 53 names in 0.000587902s
declaration order verified in 5.461e-06s
environment built in 1.3826e-05s; checking with 4 worker processes
checked 7 declarations, 0 failed, in 0.00295081s wall (1.88514e-06 core-hours over 4 workers); 9 reduction steps; peak 19 MB in one worker

Test "perf/let-fold"

Expected: 👍 accept · Size: 316.9 KB · Lines: 6.0 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check is

let d := bits #n 0; (rfl : d + 0 = Nat.add d 0)

where bits #n 0 is a closed Nat whose evaluation makes 2^n recursive calls, and the rfl is wrapped in id so that its type is compared with d + 0 = Nat.add d 0 inside the body of the let.

The two sides differ only in how the addition is written. Unfolding HAdd.hAdd turns the left side into the right, for Θ(1). But both sides are additions of literals to a closed term, so a checker that folds closed Nat arithmetic (Nat.add on literals via GMP) will try to evaluate d first, for Θ(2^n). The official kernel only folds terms without free variables, and it checks the body of a let with d as a free variable (bound to its value in the local context), so it never evaluates bits. A checker that substitutes the value for d before checking the body makes the comparison closed and pays for the evaluation.

Found by con-leche on openai/math (SquareDifference, OAI.SquareDifference.source_ordered_contraction), where the bound value is Fintype.card TupleVertex, whose evaluation enumerates permutations and takes the checker past 6 GB; the official kernel checks that declaration in 16 ms.

N=16 in the Lean source.

Test result: 👍 accepted · exit code 0 · wall time: 29 ms · instructions: 69.8 M · max rss memory: 22.9 MB

stderr:
loaded 156 declarations, 4800 exprs (4800 unique), 1017 names in 0.0012998s
declaration order verified in 1.7914e-05s
environment built in 5.4543e-05s; checking with 4 worker processes
checked 156 declarations, 0 failed, in 0.0118579s wall (1.09675e-05 core-hours over 4 workers); 3520 reduction steps; peak 22 MB in one worker

Test "perf/let-ladder"

Expected: 👍 accept · Size: 457.6 KB · Lines: 10.4 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check has type Nat and value

let x₃ := 0; x₃ + (let x₂ := 0; x₂ + (let x₁ := 0; x₁ + (x₃ + (x₂ + (x₁ + 0)))))

shown at n=3: n let bindings, each separated from the next by an addition, over an innermost sum that names every binding.

Substituting a binding into the body before checking it traverses O(n) nodes at each of the n bindings, for Θ(n²) in time and in allocated nodes. Recording the binding and reading it where the body names it costs O(1) per binding, for Θ(n).

The additions are what keep the bindings apart: a run of adjacent lets could be opened by a single substitution; not so here. Nat.add is the only application head, so no beta reduction is involved.

N=2000 in the Lean source.

Test result: 👍 accepted · exit code 0 · wall time: 578 ms · instructions: 2.2 G · max rss memory: 36.9 MB

stderr:
loaded 14 declarations, 10295 exprs (10295 unique), 85 names in 0.00238785s
declaration order verified in 2.7301e-05s
environment built in 2.8784e-05s; checking with 4 worker processes
checked 14 declarations, 0 failed, in 0.560602s wall (0.000158141 core-hours over 4 workers); 2062 reduction steps; peak 36 MB in one worker

Test "perf/magma-list-deep-n21"

Expected: 👍 accept · Size: 1.1 MB · Lines: 21.8 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Countermodel certificate for an equational-theories implication, closed by decide. A magma on Fin 21 with an inline List operation table satisfies x = (x ◇ x) ◇ (x ◇ (y ◇ y)) but not x = x ◇ (x ◇ x). The search space is only 21^2 tuples, but each equation nests the operation several deep, so every tuple expands into a chain of linear list lookups.

From a corpus of certificates generated for the SAIR math distillation challenge (equational theories track). The small end of the deep-nesting family; magma-list-deep-n36 is the same workload at a larger scale.

Test result: 👍 accepted · exit code 0 · wall time: 223 ms · instructions: 2.3 G · max rss memory: 29.8 MB

stderr:
loaded 514 declarations, 17865 exprs (17865 unique), 3436 names in 0.00525939s
declaration order verified in 6.8288e-05s
environment built in 0.000153317s; checking with 4 worker processes
checked 514 declarations, 0 failed, in 0.200705s wall (6.87878e-05 core-hours over 4 workers); 2803318 reduction steps; peak 29 MB in one worker

Test "perf/magma-list-deep-n36"

Expected: 👍 accept · Size: 1.2 MB · Lines: 23.0 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Countermodel certificate for an equational-theories implication, closed by decide. A magma on Fin 36 with an inline List operation table satisfies x = y ◇ (y ◇ (x ◇ (y ◇ x))) but not x = x ◇ (x ◇ x). The search space is only 36^2 tuples, but each side of the equation nests the operation five deep, so every tuple expands into a long chain of linear list lookups. The heaviest test of the magma family.

From a corpus of certificates generated for the SAIR math distillation challenge (equational theories track). magma-list-deep-n21 is the same workload at a smaller scale.

Test result: 👍 accepted · exit code 0 · wall time: 3.1 s · instructions: 31.3 G · max rss memory: 47.1 MB

stderr:
loaded 514 declarations, 18986 exprs (18986 unique), 3508 names in 0.00585602s
declaration order verified in 0.000102622s
environment built in 0.000192811s; checking with 4 worker processes
checked 514 declarations, 0 failed, in 3.05743s wall (0.00086873 core-hours over 4 workers); 47638593 reduction steps; peak 47 MB in one worker

Test "perf/magma-list-pair-n21"

Expected: 👍 accept · Size: 583.1 KB · Lines: 11.0 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Countermodel certificate for an equational-theories implication, closed by decide. A magma on Fin 21 with an inline List operation table satisfies x ◇ y = z ◇ w but not x = x ◇ x. Checking the certificate evaluates the decidable instance over all 21^4 ≈ 195k four-tuples; every ◇ unfolds to a linear lookup into the list. The widest search space of the magma family.

From a corpus of certificates generated for the SAIR math distillation challenge (equational theories track). magma-list-pair-n7 is the same workload at a smaller scale.

Test result: 👍 accepted · exit code 0 · wall time: 10.7 s · instructions: 38.0 G · max rss memory: 1.3 GB

stderr:
loaded 276 declarations, 8828 exprs (8828 unique), 1898 names in 0.00521258s
declaration order verified in 2.7852e-05s
environment built in 0.000121588s; checking with 4 worker processes
checked 276 declarations, 0 failed, in 10.724s wall (0.00295447 core-hours over 4 workers); 33690557 reduction steps; peak 1365 MB in one worker

Test "perf/magma-list-pair-n7"

Expected: 👍 accept · Size: 583.6 KB · Lines: 11.0 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Countermodel certificate for an equational-theories implication, closed by decide. A magma on Fin 7 with an inline List operation table satisfies x ◇ y = z ◇ (w ◇ u) but not x = x ◇ x. Checking the certificate evaluates the decidable instance over all 7^5 ≈ 17k five-tuples; every ◇ unfolds to a linear lookup into the list.

From a corpus of certificates generated for the SAIR math distillation challenge (equational theories track). The small end of the list-table family; magma-list-pair-n21 is the same workload at a larger scale.

Test result: 👍 accepted · exit code 0 · wall time: 713 ms · instructions: 3.2 G · max rss memory: 128.7 MB

stderr:
loaded 276 declarations, 8838 exprs (8838 unique), 1898 names in 0.00280436s
declaration order verified in 2.9165e-05s
environment built in 0.000164699s; checking with 4 worker processes
checked 276 declarations, 0 failed, in 0.694817s wall (0.000201894 core-hours over 4 workers); 2519725 reduction steps; peak 128 MB in one worker

Test "perf/magma-string-n4"

Expected: 👍 accept · Size: 16.5 MB · Lines: 344.3 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Countermodel certificate for an equational-theories implication, closed by decide. A magma on Fin 4 with the operation table encoded as a String satisfies x ◇ x = y ◇ ((x ◇ (y ◇ z)) ◇ z) but not x ◇ x = x ◇ (((y ◇ x) ◇ y) ◇ z). The smallest magma of the family (4^3 tuples); the cost is dominated by decoding each table entry out of the string on every lookup.

From a corpus of certificates generated for the SAIR math distillation challenge (equational theories track). The small end of the string-table family; magma-string-pair-n9 is the same workload at a larger scale.

Test result: 👍 accepted · exit code 0 · wall time: 570 ms · instructions: 11.0 G · max rss memory: 55.5 MB

stderr:
loaded 3268 declarations, 321312 exprs (321312 unique), 19661 names in 0.0536462s
declaration order verified in 0.00142644s
environment built in 0.000577302s; checking with 4 worker processes
checked 3268 declarations, 0 failed, in 0.500533s wall (0.000532725 core-hours over 4 workers); 3310447 reduction steps; peak 52 MB in one worker

Test "perf/magma-string-pair-n9"

Expected: 👍 accept · Size: 16.6 MB · Lines: 344.3 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Countermodel certificate for an equational-theories implication, closed by decide. A magma on Fin 9 with the operation table encoded as a String satisfies x ◇ y = (((z ◇ w) ◇ y) ◇ x) ◇ y but not x ◇ y = ((z ◇ (z ◇ y)) ◇ x) ◇ y. Checking the certificate evaluates the decidable instance over all 9^4 ≈ 6.5k four-tuples, decoding each table entry out of the string on every lookup. The heaviest of the string-table tests.

From a corpus of certificates generated for the SAIR math distillation challenge (equational theories track). magma-string-n4 is the same workload at a smaller scale.

Test result: 👍 accepted · exit code 0 · wall time: 1.9 s · instructions: 20.6 G · max rss memory: 158.4 MB

stderr:
loaded 3268 declarations, 321333 exprs (321333 unique), 19661 names in 0.0468196s
declaration order verified in 0.00138017s
environment built in 0.000562655s; checking with 4 worker processes
checked 3268 declarations, 0 failed, in 1.802s wall (0.000849607 core-hours over 4 workers); 14189521 reduction steps; peak 158 MB in one worker

Test "perf/proj-cheap-struct"

Expected: 👍 accept · Size: 85.9 KB · Lines: 1.5 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

(S u).re      and      (S ()).re

where u is a definition that unfolds to (), and reducing S _ to a constructor takes Θ(N) steps (it is a foldr over List.range N, with N = 2^17).

.re is a projection function, so both sides unfold to a primitive projection of S u and S (). Official reduces the structure of a projection during definitional equality only with whnf_core (no delta), compares the two stuck projections by their structures, and finds those equal by comparing the arguments of S. That is five unfoldings in all. A checker that fully reduces the structure of the projection to find a constructor evaluates S on both sides: Θ(N) steps, which runs into a step budget smaller than N.

Distilled from a Palomar submission, where the structure is a Finset.sum over Finset.range (2^17) under Complex.re.

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 16.9 M · max rss memory: 22.0 MB

stderr:
loaded 57 declarations, 1164 exprs (1164 unique), 300 names in 0.000721402s
declaration order verified in 6.603e-06s
environment built in 2.5768e-05s; checking with 4 worker processes
checked 57 declarations, 0 failed, in 0.00571922s wall (5.23677e-06 core-hours over 4 workers); 257 reduction steps; peak 21 MB in one worker

Test "perf/proj-lazy-struct"

Expected: 👍 accept · Size: 44.9 KB · Lines: 808 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

(P (slow 100000)).1      and      (Q (slow 100001)).1

where P a and Q a both unfold to (0, a), and slow n takes Θ(n) steps to evaluate.

Official compares two projections of the same structure by lazily unfolding their structs, and projects as soon as neither side unfolds any further: after unfolding P and Q, it compares just the first fields, 0 and 0. That is four unfoldings in all. A checker that instead compares the two structs completely (here (0, slow 100000) and (0, slow 100001)) before projecting also compares the second fields, which differ, and does so by evaluating slow.

This is the counterpart of proj-cheap-struct, where the structs must not be evaluated because they are equal by their arguments.

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 11.7 M · max rss memory: 22.0 MB

stderr:
loaded 31 declarations, 613 exprs (613 unique), 148 names in 0.000722935s
declaration order verified in 3.537e-06s
environment built in 2.3144e-05s; checking with 4 worker processes
checked 31 declarations, 0 failed, in 0.00358944s wall (3.2083e-06 core-hours over 4 workers); 120 reduction steps; peak 21 MB in one worker

Test "perf/proj-stuck-struct"

Expected: 👍 accept · Size: 50.1 KB · Lines: 916 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A definitional equality under a projection whose structure argument is stuck, distilled from a fuel-bridge lemma of con-leche's own proof library, on which con-leche ran out of memory.

step c n x : Nat × Nat recurses structurally on the fuel n; for a variable x each level is stuck on match x, and each branch reads .1 of two recursive calls. stepN checks (step (id c) N x).1 = (step c N x).1 by rfl, the sides differing only in id c vs c.

A checker that leaves a stuck projection's structure argument alone (as the reference kernel's whnf_core does when reduce_proj fails) compares step (id c) N x =?= step c N x, tries the arguments first, and is done at once. A checker that replaces it by its weak head normal form has lost the step head and unrolls the recursion tree on both sides: exponential in N (con-leche before the fix: 0.2 s, 2 s, 17 s and 73 MB, 0.4 GB, 2.6 GB for N = 12, 16, 20; official, nanoda, lean4lean: ~0.02 s at every N).

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 12.4 M · max rss memory: 21.9 MB

stderr:
loaded 34 declarations, 711 exprs (711 unique), 155 names in 0.000683331s
declaration order verified in 7.544e-06s
environment built in 3.0106e-05s; checking with 4 worker processes
checked 34 declarations, 0 failed, in 0.00444393s wall (3.91179e-06 core-hours over 4 workers); 139 reduction steps; peak 21 MB in one worker

Test "perf/refute-cheap-first"

Expected: ✋ reject · Size: 20.7 KB · Lines: 439 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check claims

(false, count #n) = (true, count #(n+1))

and must be rejected. Both sides are constructor applications, so comparing components is the only route, and either component refutes on its own: false against true for Θ(1), the numerals for Θ(n²) (count #k evaluates to #k in Θ(k²) reductions). The test asks in which order a checker visits the components. refute-cheap-last.lean swaps them, and the ratio between the two files is what that order costs.

N=200 in the Lean source. From Courant and Leroy, POPL 2026, §10, where the two orders cost Rocq 4 × 10⁻⁶ s and 0.61 s.

Test result: ✋ rejected · exit code 1 · wall time: 26 ms · instructions: 60.8 M · max rss memory: 25.6 MB

stderr:
loaded 7 declarations, 367 exprs (367 unique), 57 names in 0.000284904s
declaration order verified in 2.705e-06s
environment built in 1.4958e-05s; checking with 4 worker processes
FAIL kernel_refute_cheap_first (line 439): declaration type mismatch for 'kernel_refute_cheap_first'
  inferred: (((Eq.{1} ((Prod.{0, 0} Bool) N)) ((((Prod.mk.{0, 0} Bool) N) Bool.false) (count (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S N.O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) ((((Prod.mk.{0, 0} Bool) N) Bool.false) (count (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S N.O)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
  declared: (((Eq.{1} ((Prod.{0, 0} Bool) N)) ((((Prod.mk.{0, 0} Bool) N) Bool.false) (count (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S N.O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) ((((Prod.mk.{0, 0} Bool) N) Bool.true) (count (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S N.O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
checked 6 declarations, 1 failed, in 0.0129026s wall (4.78401e-06 core-hours over 4 workers); 6 reduction steps; peak 25 MB in one worker

Test "perf/refute-cheap-last"

Expected: ✋ reject · Size: 20.5 KB · Lines: 439 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check claims

(count #n, false) = (count #(n+1), true)

and must be rejected: refute-cheap-first.lean with the components swapped, so the cheap refutation sits behind the expensive one for a checker that visits components left to right.

N=200 in the Lean source. From Courant and Leroy, POPL 2026, §10.

Test result: ✋ rejected · exit code 1 · wall time: 26 ms · instructions: 61.1 M · max rss memory: 25.8 MB

stderr:
loaded 7 declarations, 367 exprs (367 unique), 57 names in 0.000302998s
declaration order verified in 2.425e-06s
environment built in 2.134e-05s; checking with 4 worker processes
FAIL kernel_refute_cheap_last (line 439): declaration type mismatch for 'kernel_refute_cheap_last'
  inferred: (((Eq.{1} ((Prod.{0, 0} N) Bool)) ((((Prod.mk.{0, 0} N) Bool) (count (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S N.O)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) Bool.false)) ((((Prod.mk.{0, 0} N) Bool) (count (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S N.O)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) Bool.false))
  declared: (((Eq.{1} ((Prod.{0, 0} N) Bool)) ((((Prod.mk.{0, 0} N) Bool) (count (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S N.O)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) Bool.false)) ((((Prod.mk.{0, 0} N) Bool) (count (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S (N.S N.O))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) Bool.true))
checked 6 declarations, 1 failed, in 0.0119428s wall (4.3189e-06 core-hours over 4 workers); 6 reduction steps; peak 25 MB in one worker

Test "perf/repeated-subproblem"

Expected: 👍 accept · Size: 11.4 KB · Lines: 214 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

perfect #n leaf      and      perfect #(n-1) (node leaf leaf)

where perfect #k t builds the perfect binary tree of depth k with leaves t, in k steps that each duplicate the tree so far into both arguments of Tr.node.

Both sides reduce to the perfect tree of depth n. Descending them meets Tr.node u u against Tr.node v v at every level, where both argument positions pose the same subproblem, so the recursion reaches 2^n pairs of nodes of which n are distinct. The test asks whether a checker records the pairs it has proved convertible: Θ(n) if it does, Θ(2ⁿ) if not.

N=20 in the Lean source, stepped up by one rather than doubled. From Courant and Leroy, POPL 2026, §10.

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 8.2 M · max rss memory: 21.5 MB

stderr:
loaded 5 declarations, 162 exprs (162 unique), 43 names in 0.000385953s
declaration order verified in 2.405e-06s
environment built in 1.4106e-05s; checking with 4 worker processes
checked 5 declarations, 0 failed, in 0.00375416s wall (2.12323e-06 core-hours over 4 workers); 132 reduction steps; peak 20 MB in one worker

Test "perf/shared-subterm"

Expected: 👍 accept · Size: 50.1 KB · Lines: 1.3 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

ldepth (perfect #n leaf)      and      ldepth2 (perfect #n leaf)

where perfect #n leaf builds the perfect binary tree of depth n in n steps that each duplicate the tree so far, and ldepth and ldepth2 both return the length of the leftmost path.

The head constants differ, so both sides are evaluated, and neither traversal looks beyond the leftmost path: ldepth walks n nodes for Θ(n), ldepth2 folds n additions over growing numerals for Θ(n²). The test asks whether a checker consumes the tree through its representation, for Θ(n²), or expands it into the 2ⁿ nodes of its normal form.

N=1000 in the Lean source. From Courant and Leroy, POPL 2026, §10.

Test result: 👍 accepted · exit code 0 · wall time: 32 ms · instructions: 111.4 M · max rss memory: 28.7 MB

stderr:
loaded 8 declarations, 1175 exprs (1175 unique), 65 names in 0.000376275s
declaration order verified in 5.34e-06s
environment built in 1.3896e-05s; checking with 4 worker processes
checked 8 declarations, 0 failed, in 0.0198497s wall (6.28224e-06 core-hours over 4 workers); 50009 reduction steps; peak 28 MB in one worker

Test "perf/shift-cascade"

Expected: 👍 accept · Size: 256.3 KB · Lines: 5.1 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Stress test for cascading substitution overhead in kernel let processing.

N nested let bindings inside a lambda, where each value references the outer lambda parameter and the previous binding:

fun (a : Nat → Nat) => let f₁ := fun x => a x let f₂ := fun x => a (f₁ x) ... let fₙ := fun x => a (fₙ₋₁ x) fₙ 0

The kernel processes each let by substituting the value into the body. Each value has a free bvar (references a), so substitution under inner binders creates shifted copies. In a de Bruijn kernel with deferred shifts, these Shift(val, offset) wrappers accumulate: step k must traverse through O(k) wrappers from previous steps, giving O(N²) total work.

A locally-nameless kernel substitutes fvars that need no shifting, giving O(N) total.

N=1000 in the Lean source. Increase to stress further.

Test result: 👍 accepted · exit code 0 · wall time: 65 ms · instructions: 528.5 M · max rss memory: 33.3 MB

stderr:
loaded 5 declarations, 4089 exprs (4089 unique), 1032 names in 0.0012834s
declaration order verified in 1.1471e-05s
environment built in 2.0729e-05s; checking with 4 worker processes
checked 5 declarations, 0 failed, in 0.0512253s wall (1.48786e-05 core-hours over 4 workers); 1000 reduction steps; peak 33 MB in one worker

Test "perf/unroll-versus-evaluate"

Expected: 👍 accept · Size: 44.6 KB · Lines: 1.2 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

count #(n+1)      and      N.add (count #n) #1

where #k is the numeral with k successors, and count #k evaluates to #k in Θ(k²) reductions.

The head constants differ. Unrolling count once turns the left side into the right side, leaving a traversal of the shared numeral #n, for Θ(n); evaluating both sides costs Θ(n²). The test asks which of two differing head constants a checker chooses to unfold.

N=1000 in the Lean source. From Courant and Leroy, POPL 2026, §2.

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 8.3 M · max rss memory: 21.8 MB

stderr:
loaded 5 declarations, 1107 exprs (1107 unique), 43 names in 0.000438622s
declaration order verified in 3.427e-06s
environment built in 1.4347e-05s; checking with 4 worker processes
checked 5 declarations, 0 failed, in 0.00279069s wall (2.13275e-06 core-hours over 4 workers); 17 reduction steps; peak 19 MB in one worker

Test "std"

Expected: 👍 accept · Size: 569.0 MB · Lines: 10.8 M · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The complete Std library export from Lean 4.

This test contains the standard library extensions beyond core Lean 4, including:

  • Enhanced data structures (HashMap, RBTree, etc.)
  • Additional mathematical operations
  • Extended list and array operations
  • Utility functions and theorems

This represents a medium-sized test case, larger than core modules but smaller than Mathlib, making it useful for performance testing.

Test result: 👍 accepted · exit code 0 · wall time: 21.2 s · instructions: 369.8 G · max rss memory: 710.3 MB

stderr:
loaded 101286 declarations, 10145829 exprs (10145829 unique), 578589 names in 1.65928s
declaration order verified in 0.0952641s
environment built in 0.0411138s; checking with 4 worker processes
checked 101286 declarations, 0 failed, in 19.5066s wall (0.0216592 core-hours over 4 workers); 77160347 reduction steps; peak 710 MB in one worker

Test "tutorial/001_basicDef"

Expected: 👍 accept · Size: 367 B · Lines: 6 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Basic definition

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 1 names in 8.7454e-05s
declaration order verified in 1.753e-06s
environment built in 1.4828e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00235438s wall (1.33168e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/002_badDef"

Expected: ✋ reject · Size: 365 B · Lines: 6 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Mismatched types

Test result: ✋ rejected · exit code 1 · wall time: 20 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 1 names in 0.000142788s
declaration order verified in 2.214e-06s
environment built in 2.2873e-05s; checking with 4 worker processes
FAIL badDef (line 6): declaration type mismatch for 'badDef'
  inferred: Sort(2)
  declared: Sort(0)
checked 0 declarations, 1 failed, in 0.00250143s wall (1.45049e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/003_arrowType"

Expected: 👍 accept · Size: 622 B · Lines: 12 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Arrow type (function type)

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 6.3 M · max rss memory: 21.5 MB

stderr:
loaded 1 declarations, 3 exprs (3 unique), 6 names in 0.000218049s
declaration order verified in 2.334e-06s
environment built in 2.0779e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00328258s wall (2.02338e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/004_dependentType"

Expected: 👍 accept · Size: 460 B · Lines: 7 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Dependent type (forall)

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 3 exprs (3 unique), 2 names in 0.000117902s
declaration order verified in 1.844e-06s
environment built in 2.2813e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00311821s wall (1.75257e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/005_constType"

Expected: 👍 accept · Size: 897 B · Lines: 17 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Lambda expression

Test result: 👍 accepted · exit code 0 · wall time: 20 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 6 exprs (6 unique), 8 names in 0.000164639s
declaration order verified in 5.07e-06s
environment built in 2.3324e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00238604s wall (1.7429e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/006_betaReduction"

Expected: 👍 accept · Size: 1.3 KB · Lines: 27 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Lambda reduction

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 13 exprs (13 unique), 10 names in 0.000167564s
declaration order verified in 2.083e-06s
environment built in 1.9296e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00237648s wall (1.25331e-06 core-hours over 4 workers); 1 reduction steps; peak 18 MB in one worker

Test "tutorial/007_betaReduction2"

Expected: 👍 accept · Size: 1.4 KB · Lines: 28 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Lambda reduction under binder

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 6.3 M · max rss memory: 21.4 MB

stderr:
loaded 2 declarations, 14 exprs (14 unique), 10 names in 9.4898e-05s
declaration order verified in 2.224e-06s
environment built in 1.1141e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00308669s wall (2.00031e-06 core-hours over 4 workers); 1 reduction steps; peak 18 MB in one worker

Test "tutorial/008_forallSortWhnf"

Expected: 👍 accept · Size: 1.2 KB · Lines: 25 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The binding domain of a forall may need to be reduce before it is a sort

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 13 exprs (13 unique), 6 names in 0.000145743s
declaration order verified in 2.294e-06s
environment built in 2.5658e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00263095s wall (1.9565e-06 core-hours over 4 workers); 8 reduction steps; peak 18 MB in one worker

Test "tutorial/009_forallSortBad"

Expected: ✋ reject · Size: 1.2 KB · Lines: 26 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The binding domain of a forall has to be a sort

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.4 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 14 exprs (14 unique), 6 names in 0.000199383s
declaration order verified in 1.783e-06s
environment built in 1.2463e-05s; checking with 4 worker processes
FAIL forallSortBad (line 26): type expected: $1
checked 1 declarations, 1 failed, in 0.00166704s wall (1.22846e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/010_nonTypeType"

Expected: ✋ reject · Size: 1.1 KB · Lines: 21 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The type of a declaration has to be a type, not some other expression

Test result: ✋ rejected · exit code 1 · wall time: 14 ms · instructions: 6.3 M · max rss memory: 21.5 MB

stderr:
loaded 2 declarations, 8 exprs (8 unique), 9 names in 0.00014385s
declaration order verified in 5.691e-06s
environment built in 1.4076e-05s; checking with 4 worker processes
FAIL nonTypeType (line 21): type expected: constType
checked 1 declarations, 1 failed, in 0.0017984s wall (1.3576e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/011_nonTypeAxiom"

Expected: ✋ reject · Size: 1.0 KB · Lines: 20 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

This applies to axioms as well, which are easy to overlook because they have no value to check the type against. Letting one through is not merely untidy: an axiom whose type is an arbitrary term inhabits whatever that term is later found definitionally equal to, and the eta and proof irrelevance rules are happy to equate a term like this with a great many things.

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 7 exprs (7 unique), 9 names in 0.000125475s
declaration order verified in 1.904e-06s
environment built in 1.4898e-05s; checking with 4 worker processes
FAIL nonTypeAxiom (line 20): type expected: constType
checked 1 declarations, 1 failed, in 0.00176548s wall (1.11011e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/012_nonPropThm"

Expected: ✋ reject · Size: 424 B · Lines: 7 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The type of a theorem has to be a proposition

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 3 exprs (3 unique), 2 names in 0.00014903s
declaration order verified in 1.783e-06s
environment built in 1.1622e-05s; checking with 4 worker processes
FAIL nonPropThm (line 7): theorem type is not a proposition: nonPropThm
checked 0 declarations, 1 failed, in 0.00224273s wall (1.52884e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/013_thmProof"

Expected: 👍 accept · Size: 1.3 KB · Lines: 26 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A theorem can refer to another theorem

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 14 exprs (14 unique), 9 names in 0.000154941s
declaration order verified in 2.615e-06s
environment built in 1.5198e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00207566s wall (1.27605e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/014_selfProof"

Expected: ✋ reject · Size: 459 B · Lines: 8 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A theorem cannot refer to itself

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 4 exprs (4 unique), 2 names in 0.000150793s
declaration order verified in 2.024e-06s
environment built in 1.1542e-05s; checking with 4 worker processes
FAIL selfProof (line 8): unknown constant 'selfProof'
checked 0 declarations, 1 failed, in 0.00222049s wall (1.44342e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/015_levelComp1"

Expected: 👍 accept · Size: 391 B · Lines: 7 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Some level computation

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 1 names in 0.000128711s
declaration order verified in 1.813e-06s
environment built in 1.2564e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00185511s wall (1.17362e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/016_levelComp2"

Expected: 👍 accept · Size: 409 B · Lines: 8 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Some level computation

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.3 M · max rss memory: 21.5 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 1 names in 0.000158878s
declaration order verified in 4.929e-06s
environment built in 1.3606e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00189173s wall (1.37567e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/017_levelComp3"

Expected: 👍 accept · Size: 427 B · Lines: 9 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Some level computation

Test result: 👍 accepted · exit code 0 · wall time: 14 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 1 names in 0.000101821s
declaration order verified in 1.954e-06s
environment built in 1.6261e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00179487s wall (1.02825e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/018_levelParams"

Expected: 👍 accept · Size: 1.4 KB · Lines: 29 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Level parameters

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 13 exprs (13 unique), 11 names in 0.000155721s
declaration order verified in 2.294e-06s
environment built in 2.3013e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00256602s wall (1.73698e-06 core-hours over 4 workers); 1 reduction steps; peak 18 MB in one worker

Test "tutorial/019_tut06_bad01"

Expected: ✋ reject · Size: 427 B · Lines: 8 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Duplicate universe parameters

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 2 names in 0.000155201s
declaration order verified in 3.086e-06s
environment built in 1.7423e-05s; checking with 4 worker processes
FAIL tut06_bad01 (line 8): duplicate universe level parameter 'u'
checked 0 declarations, 1 failed, in 0.0026595s wall (1.40941e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/020_levelComp4"

Expected: 👍 accept · Size: 424 B · Lines: 8 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Some level computation

Test result: 👍 accepted · exit code 0 · wall time: 20 ms · instructions: 6.3 M · max rss memory: 21.8 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 2 names in 8.9789e-05s
declaration order verified in 1.813e-06s
environment built in 1.5178e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00262633s wall (1.13007e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/021_levelComp5"

Expected: 👍 accept · Size: 424 B · Lines: 8 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Some level computation

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 2 names in 8.3928e-05s
declaration order verified in 4.448e-06s
environment built in 1.3716e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00187836s wall (1.24273e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/022_imax1"

Expected: 👍 accept · Size: 809 B · Lines: 16 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type inference for forall using imax

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 6 exprs (6 unique), 7 names in 0.000116358s
declaration order verified in 2.114e-06s
environment built in 1.5739e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00220893s wall (1.40958e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/023_imax2"

Expected: 👍 accept · Size: 828 B · Lines: 17 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type inference for forall using imax

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 6 exprs (6 unique), 7 names in 0.00011728s
declaration order verified in 6.312e-06s
environment built in 2.5217e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00224561s wall (1.4992e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/024_levelMaxComm"

Expected: 👍 accept · Size: 524 B · Lines: 12 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Level equality: max is commutative (max u v ≈ max v u).

Test result: 👍 accepted · exit code 0 · wall time: 39 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 3 names in 0.000106419s
declaration order verified in 1.733e-06s
environment built in 2.5367e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00171172s wall (1.20906e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/025_levelMaxAssoc"

Expected: 👍 accept · Size: 623 B · Lines: 16 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Level equality: max is associative (max (max u v) w ≈ max u (max v w)).

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.5 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 4 names in 9.7122e-05s
declaration order verified in 2.174e-06s
environment built in 1.5409e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00170326s wall (1.20222e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/026_levelMaxIdem"

Expected: 👍 accept · Size: 447 B · Lines: 9 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Level equality: max is idempotent (max u u ≈ u).

Test result: 👍 accepted · exit code 0 · wall time: 14 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 2 names in 9.8975e-05s
declaration order verified in 1.643e-06s
environment built in 1.4867e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00151921s wall (9.18931e-07 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/027_levelMaxAbsorb"

Expected: 👍 accept · Size: 526 B · Lines: 12 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Level equality: max absorption (max u (max u v) ≈ max u v).

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.3 M · max rss memory: 21.5 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 3 names in 0.000127349s
declaration order verified in 2.034e-06s
environment built in 1.9227e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00196111s wall (1.16807e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/028_inferVar"

Expected: 👍 accept · Size: 713 B · Lines: 12 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type inference of local variables

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 7 exprs (7 unique), 3 names in 0.000116589s
declaration order verified in 1.763e-06s
environment built in 1.6992e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00149809s wall (1.03156e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/029_defEqLambda"

Expected: 👍 accept · Size: 1.4 KB · Lines: 26 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Definitional equality between lambdas

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 15 exprs (15 unique), 9 names in 0.000120206s
declaration order verified in 2.855e-06s
environment built in 1.6701e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00226392s wall (1.27353e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/030_peano1"

Expected: 👍 accept · Size: 3.6 KB · Lines: 73 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Peano arithmetic: 2 = 2

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.6 M · max rss memory: 21.5 MB

stderr:
loaded 7 declarations, 41 exprs (41 unique), 20 names in 0.000100218s
declaration order verified in 6.572e-06s
environment built in 1.1892e-05s; checking with 4 worker processes
checked 7 declarations, 0 failed, in 0.00289688s wall (1.34893e-06 core-hours over 4 workers); 5 reduction steps; peak 18 MB in one worker

Test "tutorial/031_peano2"

Expected: 👍 accept · Size: 4.5 KB · Lines: 90 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Peano arithmetic: 1 + 1 = 2

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 6.8 M · max rss memory: 21.8 MB

stderr:
loaded 8 declarations, 55 exprs (55 unique), 22 names in 0.000150492s
declaration order verified in 3.777e-06s
environment built in 1.8525e-05s; checking with 4 worker processes
checked 8 declarations, 0 failed, in 0.00281081s wall (1.98438e-06 core-hours over 4 workers); 23 reduction steps; peak 19 MB in one worker

Test "tutorial/032_peano3"

Expected: 👍 accept · Size: 4.9 KB · Lines: 98 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Peano arithmetic: 2 * 2 = 4

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 6.9 M · max rss memory: 21.6 MB

stderr:
loaded 10 declarations, 59 exprs (59 unique), 24 names in 0.0001602s
declaration order verified in 3.967e-06s
environment built in 1.8345e-05s; checking with 4 worker processes
checked 10 declarations, 0 failed, in 0.00596075s wall (2.60671e-06 core-hours over 4 workers); 37 reduction steps; peak 19 MB in one worker

Test "tutorial/033_letType"

Expected: 👍 accept · Size: 489 B · Lines: 9 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type checking a non-dependent let

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 4 exprs (4 unique), 2 names in 0.000116198s
declaration order verified in 6.392e-06s
environment built in 2.3664e-05s; checking with 4 worker processes
checked 1 declarations, 0 failed, in 0.00291896s wall (1.54866e-06 core-hours over 4 workers); 1 reduction steps; peak 18 MB in one worker

Test "tutorial/034_letTypeDep"

Expected: 👍 accept · Size: 1.2 KB · Lines: 26 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type checking a dependent let

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 3 declarations, 11 exprs (11 unique), 10 names in 0.000157576s
declaration order verified in 1.984e-06s
environment built in 2.2712e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00273071s wall (1.42198e-06 core-hours over 4 workers); 1 reduction steps; peak 18 MB in one worker

Test "tutorial/035_letRed"

Expected: 👍 accept · Size: 627 B · Lines: 12 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Reducing a let

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.3 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 5 exprs (5 unique), 3 names in 8.1974e-05s
declaration order verified in 1.653e-06s
environment built in 1.3706e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00180556s wall (1.09626e-06 core-hours over 4 workers); 4 reduction steps; peak 18 MB in one worker

Test "tutorial/036_empty"

Expected: 👍 accept · Size: 1.2 KB · Lines: 20 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A simple empty inductive type

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 9 exprs (9 unique), 6 names in 0.000132829s
declaration order verified in 2.084e-06s
environment built in 2.4386e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00211136s wall (1.475e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/037_boolType"

Expected: 👍 accept · Size: 2.3 KB · Lines: 37 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A simple enumeration inductive type

Test result: 👍 accepted · exit code 0 · wall time: 14 ms · instructions: 6.4 M · max rss memory: 21.5 MB

stderr:
loaded 2 declarations, 22 exprs (22 unique), 10 names in 0.000139261s
declaration order verified in 2.084e-06s
environment built in 1.2694e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00159517s wall (1.15055e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/038_twoBool"

Expected: 👍 accept · Size: 4.2 KB · Lines: 65 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A simple product type

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.6 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 43 exprs (43 unique), 16 names in 0.000162665s
declaration order verified in 1.1572e-05s
environment built in 2.1571e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00236839s wall (1.42656e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/039_andType"

Expected: 👍 accept · Size: 3.2 KB · Lines: 57 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A parametrized product type (no level parameters)

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.6 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 41 exprs (41 unique), 12 names in 0.000116669s
declaration order verified in 4.358e-06s
environment built in 1.2053e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00229165s wall (1.58311e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/040_prodType"

Expected: 👍 accept · Size: 3.8 KB · Lines: 76 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A parametrized product type (with level parameters)

Test result: 👍 accepted · exit code 0 · wall time: 21 ms · instructions: 6.6 M · max rss memory: 21.9 MB

stderr:
loaded 2 declarations, 47 exprs (47 unique), 19 names in 0.000186399s
declaration order verified in 5.099e-06s
environment built in 1.6822e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00244291s wall (1.84701e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/041_pprodType"

Expected: 👍 accept · Size: 3.8 KB · Lines: 75 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A parametrized product type (with more general level parameters)

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 6.7 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 47 exprs (47 unique), 19 names in 0.000156213s
declaration order verified in 6.592e-06s
environment built in 2.3364e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.0023582s wall (1.60878e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/042_pUnitType"

Expected: 👍 accept · Size: 1.8 KB · Lines: 31 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Level-polymorphic unit type

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.4 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 16 exprs (16 unique), 9 names in 0.000146295s
declaration order verified in 1.963e-06s
environment built in 1.4798e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00180897s wall (1.30472e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/043_eqType"

Expected: 👍 accept · Size: 3.2 KB · Lines: 62 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Equality, as an important indexed non-recursive data type

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.6 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 42 exprs (42 unique), 15 names in 0.000165109s
declaration order verified in 9.688e-06s
environment built in 2.2813e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00231784s wall (1.58496e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/044_natDef"

Expected: 👍 accept · Size: 3.3 KB · Lines: 61 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A recursive inductive data type

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.5 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 36 exprs (36 unique), 20 names in 0.000136496s
declaration order verified in 6.702e-06s
environment built in 1.3335e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00181884s wall (1.34547e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/045_rbTreeDef"

Expected: 👍 accept · Size: 15.7 KB · Lines: 296 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A recursive indexed data type

Test result: 👍 accepted · exit code 0 · wall time: 20 ms · instructions: 8.9 M · max rss memory: 21.8 MB

stderr:
loaded 4 declarations, 248 exprs (248 unique), 39 names in 0.000678382s
declaration order verified in 2.715e-06s
environment built in 1.4147e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.00548872s wall (2.50261e-06 core-hours over 4 workers); 0 reduction steps; peak 21 MB in one worker

Test "tutorial/046_inductBadNonSort"

Expected: ✋ reject · Size: 1.2 KB · Lines: 20 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive type with a non-sort type

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 6.4 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 7 exprs (7 unique), 9 names in 0.000123261s
declaration order verified in 2.274e-06s
environment built in 1.3856e-05s; checking with 4 worker processes
FAIL inductBadNonSort (line 20): type expected: constType
checked 1 declarations, 1 failed, in 0.0030023s wall (1.65404e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/047_inductBadNonSort2"

Expected: ✋ reject · Size: 598 B · Lines: 8 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Another inductive type with a non-sort type

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.3 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 2 exprs (2 unique), 2 names in 0.000125415s
declaration order verified in 2.174e-06s
environment built in 1.7743e-05s; checking with 4 worker processes
FAIL inductBadNonSort2 (line 8): type expected: aType
checked 1 declarations, 1 failed, in 0.0022607s wall (1.52322e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/048_inductLevelParam"

Expected: ✋ reject · Size: 515 B · Lines: 7 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive with duplicate level params

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 1 exprs (1 unique), 2 names in 0.000125706s
declaration order verified in 1.834e-06s
environment built in 2.4106e-05s; checking with 4 worker processes
FAIL inductLevelParam (line 7): duplicate universe level parameter 'u'
checked 0 declarations, 1 failed, in 0.00185063s wall (1.25728e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/049_inductTooFewParams"

Expected: ✋ reject · Size: 548 B · Lines: 6 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive with too few parameters in the type

Test result: ✋ rejected · exit code 1 · wall time: 30 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 2 exprs (2 unique), 2 names in 9.5369e-05s
declaration order verified in 2.034e-06s
environment built in 1.4757e-05s; checking with 4 worker processes
FAIL inductTooFewParams (line 6): invalid inductive datatype declaration, incorrect number of parameters
checked 0 declarations, 1 failed, in 0.00212265s wall (1.27069e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/050_inductWrongCtorParams"

Expected: ✋ reject · Size: 1.2 KB · Lines: 16 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive with a constructor with wrong parameters

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 6.4 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 7 exprs (7 unique), 5 names in 0.000115376s
declaration order verified in 1.813e-06s
environment built in 1.9066e-05s; checking with 4 worker processes
FAIL inductWrongCtorParams (line 16): arg #1 of 'inductWrongCtorParams.mk' does not match inductive datatype parameters
checked 1 declarations, 1 failed, in 0.00220315s wall (1.18153e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/051_inductWrongCtorResParams"

Expected: ✋ reject · Size: 1.3 KB · Lines: 19 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive with a constructor with wrong parameters in result (they are swapped)

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 6.4 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 11 exprs (11 unique), 5 names in 0.000104907s
declaration order verified in 6.162e-06s
environment built in 1.3596e-05s; checking with 4 worker processes
FAIL inductWrongCtorResParams (line 19): invalid return type for 'inductWrongCtorResParams.mk'
checked 0 declarations, 1 failed, in 0.00199047s wall (1.44233e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/052_inductWrongCtorResLevel"

Expected: ✋ reject · Size: 1.4 KB · Lines: 23 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive with a constructor with wrong level parameters in result (they are swapped)

Test result: ✋ rejected · exit code 1 · wall time: 19 ms · instructions: 6.4 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 11 exprs (11 unique), 7 names in 0.000135745s
declaration order verified in 2.374e-06s
environment built in 3.4124e-05s; checking with 4 worker processes
FAIL inductWrongCtorResLevel (line 23): invalid return type for 'inductWrongCtorResLevel.mk'
checked 0 declarations, 1 failed, in 0.00312091s wall (1.71068e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/053_inductInIndex"

Expected: ✋ reject · Size: 1.1 KB · Lines: 14 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A constructor with an unexpected occurrence of the type in index position of a return type.

Test result: ✋ rejected · exit code 1 · wall time: 18 ms · instructions: 6.4 M · max rss memory: 21.9 MB

stderr:
loaded 2 declarations, 6 exprs (6 unique), 5 names in 0.000280586s
declaration order verified in 7.905e-06s
environment built in 2.4015e-05s; checking with 4 worker processes
FAIL inductInIndex (line 14): invalid return type for 'inductInIndex.mk'
checked 1 declarations, 1 failed, in 0.00243762s wall (1.63438e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/054_indNeg"

Expected: ✋ reject · Size: 996 B · Lines: 12 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The classic example of an inductive with negative recursive occurrence

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.4 M · max rss memory: 21.7 MB

stderr:
loaded 1 declarations, 5 exprs (5 unique), 4 names in 0.000130945s
declaration order verified in 5.19e-06s
environment built in 1.6481e-05s; checking with 4 worker processes
FAIL indNeg (line 12): arg #1 of 'indNeg.mk' has a non positive occurrence of the datatypes being declared
checked 0 declarations, 1 failed, in 0.00256009s wall (1.49983e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/055_reduceCtorParam.mk"

Expected: 👍 accept · Size: 4.1 KB · Lines: 80 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

When checking inductives, we expect the kernel to reduce the types of constructor arguments.

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 6.8 M · max rss memory: 21.5 MB

stderr:
loaded 3 declarations, 54 exprs (54 unique), 18 names in 0.000168706s
declaration order verified in 4.759e-06s
environment built in 2.4697e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00251251s wall (2.00965e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/056_reduceCtorType.mk"

Expected: ✋ reject · Size: 1.5 KB · Lines: 26 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

When checking inductives, we expect the kernel to not reduce the type of the constructor itself; that should be all manifest foralls

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 6.5 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 13 exprs (13 unique), 7 names in 0.000142087s
declaration order verified in 2.585e-06s
environment built in 1.6641e-05s; checking with 4 worker processes
FAIL reduceCtorType (line 26): invalid return type for 'reduceCtorType.mk'
checked 1 declarations, 1 failed, in 0.00217717s wall (1.25212e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/057_indNegReducible"

Expected: ✋ reject · Size: 1.9 KB · Lines: 31 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

When checking inductives, we expect the kernel to not reduce the type of the constructor parameters further than head normal form. Recursive occurrences nested inside the head normal form are considered negative occurrences, even if they could be reduced to disappear.

Test result: ✋ rejected · exit code 1 · wall time: 20 ms · instructions: 6.4 M · max rss memory: 21.5 MB

stderr:
loaded 3 declarations, 14 exprs (14 unique), 12 names in 0.000130936s
declaration order verified in 2.495e-06s
environment built in 2.2723e-05s; checking with 4 worker processes
FAIL indNegReducible (line 31): arg #1 of 'indNegReducible.mk' has a non positive occurrence of the datatypes being declared
checked 2 declarations, 1 failed, in 0.00260607s wall (1.34912e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/058_predWithTypeField"

Expected: 👍 accept · Size: 2.0 KB · Lines: 32 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive proposition can have constructors with fields of arbitrary level.

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.4 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 20 exprs (20 unique), 8 names in 0.000113994s
declaration order verified in 1.713e-06s
environment built in 1.2894e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00227471s wall (1.32366e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/059_typeWithTypeField"

Expected: 👍 accept · Size: 2.1 KB · Lines: 36 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive type can have fields of level up to that of the inductive.

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.4 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 21 exprs (21 unique), 9 names in 0.000145162s
declaration order verified in 1.964e-06s
environment built in 1.3486e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00231049s wall (1.29383e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/060_typeWithTypeFieldPoly"

Expected: 👍 accept · Size: 2.1 KB · Lines: 38 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive type can have fields of level up to that of the inductive (polymorphic variant).

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.4 M · max rss memory: 21.5 MB

stderr:
loaded 2 declarations, 21 exprs (21 unique), 10 names in 0.000139151s
declaration order verified in 1.833e-06s
environment built in 1.2744e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00267217s wall (1.52963e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/061_typeWithTooHighTypeField.mk"

Expected: ✋ reject · Size: 943 B · Lines: 11 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive type can have fields of from higher universes.

Test result: ✋ rejected · exit code 1 · wall time: 19 ms · instructions: 6.4 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 4 exprs (4 unique), 4 names in 8.8977e-05s
declaration order verified in 4.559e-06s
environment built in 1.0489e-05s; checking with 4 worker processes
FAIL typeWithTooHighTypeField (line 11): universe level of type_of(arg #1) of 'typeWithTooHighTypeField.mk' is too big for the corresponding inductive datatype
checked 0 declarations, 1 failed, in 0.00284071s wall (1.14467e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/062_emptyRec"

Expected: 👍 accept · Size: 1.2 KB · Lines: 21 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.4 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 10 exprs (10 unique), 6 names in 0.000124433s
declaration order verified in 2.304e-06s
environment built in 2.0529e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00239781s wall (1.27674e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/063_boolRec"

Expected: 👍 accept · Size: 3.0 KB · Lines: 53 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.5 M · max rss memory: 21.5 MB

stderr:
loaded 2 declarations, 32 exprs (32 unique), 16 names in 0.000129873s
declaration order verified in 6.652e-06s
environment built in 1.4547e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00228775s wall (1.34805e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/064_twoBoolRec"

Expected: 👍 accept · Size: 4.8 KB · Lines: 78 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.7 M · max rss memory: 21.7 MB

stderr:
loaded 3 declarations, 50 exprs (50 unique), 22 names in 0.000194013s
declaration order verified in 0.000103764s
environment built in 2.665e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00241463s wall (1.49711e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/065_andRec"

Expected: 👍 accept · Size: 3.2 KB · Lines: 58 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.7 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 42 exprs (42 unique), 12 names in 0.000142106s
declaration order verified in 3.777e-06s
environment built in 1.3425e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00261673s wall (1.88018e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/066_prodRec"

Expected: 👍 accept · Size: 4.0 KB · Lines: 79 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.7 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 49 exprs (49 unique), 20 names in 0.000120376s
declaration order verified in 4.038e-06s
environment built in 2.0839e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00255551s wall (1.98724e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/067_pprodRec"

Expected: 👍 accept · Size: 4.0 KB · Lines: 78 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 14 ms · instructions: 6.7 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 48 exprs (48 unique), 20 names in 0.000129142s
declaration order verified in 4.068e-06s
environment built in 1.9566e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00203678s wall (1.65542e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/068_punitRec"

Expected: 👍 accept · Size: 2.2 KB · Lines: 39 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.4 M · max rss memory: 21.5 MB

stderr:
loaded 2 declarations, 18 exprs (18 unique), 15 names in 0.000103404s
declaration order verified in 1.764e-06s
environment built in 2.2172e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00171418s wall (1.24907e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/069_eqRec"

Expected: 👍 accept · Size: 3.3 KB · Lines: 63 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.7 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 43 exprs (43 unique), 15 names in 0.000146034s
declaration order verified in 6.613e-06s
environment built in 2.3344e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00237494s wall (1.61585e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/070_nRec"

Expected: 👍 accept · Size: 3.3 KB · Lines: 61 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.6 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 36 exprs (36 unique), 20 names in 0.000118943s
declaration order verified in 6.823e-06s
environment built in 1.2694e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00232006s wall (1.37104e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/071_rbTreeRef"

Expected: 👍 accept · Size: 16.2 KB · Lines: 303 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 9.2 M · max rss memory: 21.4 MB

stderr:
loaded 4 declarations, 254 exprs (254 unique), 40 names in 0.000920587s
declaration order verified in 5.059e-06s
environment built in 2.1099e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.00591282s wall (3.34841e-06 core-hours over 4 workers); 0 reduction steps; peak 20 MB in one worker

Test "tutorial/072_boolPropRec"

Expected: 👍 accept · Size: 2.3 KB · Lines: 34 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Inductive predicates eliminate into Prop if they have more than one constructor.

Test result: 👍 accepted · exit code 0 · wall time: 38 ms · instructions: 6.4 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 22 exprs (22 unique), 9 names in 0.000119023s
declaration order verified in 4.278e-06s
environment built in 1.5389e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00205467s wall (1.54827e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/073_BogusRecursor"

Expected: ✋ reject · Size: 1.8 KB · Lines: 27 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A kernel must not blindly trust the recursors it is handed. If we write

inductive BogusRecursor : Type where
  | mk : BogusRecursor

then the recursor BogusRecursor.rec will be correctly derived with type {motive : BogusRecursor → Sort u} → motive .mk → (t : BogusRecursor) → motive t.

This test instead claims that the recursor is a constant of type False, and then uses it to prove bogusRecursorFalse : False. A kernel that validates the recursors it is handed rejects the bogus recursor itself; a kernel that ignores them and derives the recursors anew rejects the proof of False (the derived recursor neither has type False nor zero universe parameters). Either way, this test must be rejected.

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 6.5 M · max rss memory: 21.7 MB

stderr:
loaded 3 declarations, 12 exprs (12 unique), 9 names in 0.000132217s
declaration order verified in 2.064e-06s
environment built in 1.3595e-05s; checking with 4 worker processes
FAIL BogusRecursor (line 24): recursor 'BogusRecursor.rec': parameter/index/motive/minor/K data differs from the derived recursor
checked 1 declarations, 1 failed, in 0.00296412s wall (1.90577e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/074_existsRec"

Expected: 👍 accept · Size: 3.6 KB · Lines: 66 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Inductive predicates eliminate into Prop if they have one constructors and it carries data.

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.8 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 45 exprs (45 unique), 17 names in 0.000168245s
declaration order verified in 3.817e-06s
environment built in 1.7092e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00303733s wall (2.14123e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/075_typeSingletonRecReduction"

Expected: 👍 accept · Size: 7.9 KB · Lines: 138 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Because NewSingleton is a singleton, NewSingleton.rec true x reduces to true even though x is a variable.

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 7.1 M · max rss memory: 21.6 MB

stderr:
loaded 5 declarations, 95 exprs (95 unique), 34 names in 0.000131406s
declaration order verified in 2.064e-06s
environment built in 1.3275e-05s; checking with 4 worker processes
checked 5 declarations, 0 failed, in 0.00288576s wall (2.07002e-06 core-hours over 4 workers); 5 reduction steps; peak 19 MB in one worker

Test "tutorial/076_sortElimPropRec"

Expected: 👍 accept · Size: 5.6 KB · Lines: 97 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Inductive predicates eliminate into Sort if they have one constructors and it carries data, but the data is known from the type, e.g. a parameter or an index

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 7.0 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 69 exprs (69 unique), 22 names in 0.000254577s
declaration order verified in 2.815e-06s
environment built in 2.2322e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00321706s wall (2.58134e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/077_sortElimProp2Rec"

Expected: 👍 accept · Size: 6.6 KB · Lines: 114 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Inductive predicates eliminate into Sort if they have one constructors and it carries data, but the data is known from the type, e.g. a parameter or an index. However, it must occur directly in the result type, with no intervening reduction.

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 7.1 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 83 exprs (83 unique), 24 names in 0.000150352s
declaration order verified in 4.889e-06s
environment built in 2.2433e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.00278914s wall (1.96007e-06 core-hours over 4 workers); 2 reduction steps; peak 19 MB in one worker

Test "tutorial/078_boolRecEqns"

Expected: 👍 accept · Size: 10.8 KB · Lines: 199 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Reduction behavior of Bool.rec

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 7.5 M · max rss memory: 21.5 MB

stderr:
loaded 4 declarations, 133 exprs (133 unique), 58 names in 0.000479379s
declaration order verified in 2.956e-06s
environment built in 1.9897e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.00343281s wall (2.26904e-06 core-hours over 4 workers); 16 reduction steps; peak 19 MB in one worker

Test "tutorial/079_prodRecEqns"

Expected: 👍 accept · Size: 10.1 KB · Lines: 205 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Reduction behavior of Prod.rec

Test result: 👍 accepted · exit code 0 · wall time: 21 ms · instructions: 7.5 M · max rss memory: 21.8 MB

stderr:
loaded 3 declarations, 127 exprs (127 unique), 67 names in 0.000939601s
declaration order verified in 2.465e-06s
environment built in 1.3706e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00678455s wall (2.65875e-06 core-hours over 4 workers); 6 reduction steps; peak 20 MB in one worker

Test "tutorial/080_nRecReduction"

Expected: 👍 accept · Size: 12.7 KB · Lines: 238 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A proof relying on the reduction behavior of N.rec

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 7.7 M · max rss memory: 21.6 MB

stderr:
loaded 6 declarations, 170 exprs (170 unique), 58 names in 0.000387807s
declaration order verified in 3.246e-06s
environment built in 2.112e-05s; checking with 4 worker processes
checked 6 declarations, 0 failed, in 0.00402407s wall (2.3964e-06 core-hours over 4 workers); 43 reduction steps; peak 20 MB in one worker

Test "tutorial/081_listRecReduction"

Expected: 👍 accept · Size: 17.5 KB · Lines: 335 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Reduction behavior of List.rec

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 8.9 M · max rss memory: 21.8 MB

stderr:
loaded 7 declarations, 256 exprs (256 unique), 67 names in 0.000525816s
declaration order verified in 4.479e-06s
environment built in 6.3038e-05s; checking with 4 worker processes
checked 7 declarations, 0 failed, in 0.00532993s wall (3.09673e-06 core-hours over 4 workers); 44 reduction steps; peak 21 MB in one worker

Test "tutorial/082_RBTree.id_spec"

Expected: 👍 accept · Size: 47.9 KB · Lines: 1.0 k · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Reduction behavior of RBTree.rec

Test result: 👍 accepted · exit code 0 · wall time: 21 ms · instructions: 15.5 M · max rss memory: 22.3 MB

stderr:
loaded 7 declarations, 878 exprs (878 unique), 116 names in 0.000542567s
declaration order verified in 5.791e-06s
environment built in 1.7774e-05s; checking with 4 worker processes
checked 7 declarations, 0 failed, in 0.007435s wall (4.94787e-06 core-hours over 4 workers); 46 reduction steps; peak 22 MB in one worker

Test "tutorial/083_And.right"

Expected: 👍 accept · Size: 4.3 KB · Lines: 74 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type-checking simple projection functions

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.7 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 55 exprs (55 unique), 14 names in 0.00015999s
declaration order verified in 3.878e-06s
environment built in 1.6572e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.002278s wall (1.84877e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/084_Prod.snd"

Expected: 👍 accept · Size: 4.5 KB · Lines: 83 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type-checking projection functions with parameters

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.8 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 57 exprs (57 unique), 16 names in 0.000194725s
declaration order verified in 4.258e-06s
environment built in 1.7793e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00302653s wall (1.97879e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/085_PProd.snd"

Expected: 👍 accept · Size: 4.5 KB · Lines: 83 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type-checking projection functions

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.8 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 57 exprs (57 unique), 16 names in 0.000113112s
declaration order verified in 3.456e-06s
environment built in 1.7183e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00227825s wall (1.50842e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/086_PSigma.snd"

Expected: 👍 accept · Size: 5.1 KB · Lines: 96 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type-checking dependent projection functions

Test result: 👍 accepted · exit code 0 · wall time: 21 ms · instructions: 7.0 M · max rss memory: 21.7 MB

stderr:
loaded 3 declarations, 65 exprs (65 unique), 21 names in 0.000151715s
declaration order verified in 3.135e-06s
environment built in 2.3013e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.0040087s wall (2.28143e-06 core-hours over 4 workers); 1 reduction steps; peak 19 MB in one worker

Test "tutorial/087_projOutOfRange"

Expected: ✋ reject · Size: 3.8 KB · Lines: 67 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Out of range projection

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.7 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 48 exprs (48 unique), 15 names in 0.000166432s
declaration order verified in 3.667e-06s
environment built in 2.5808e-05s; checking with 4 worker processes
FAIL projOutOfRange (line 67): invalid projection And.2
checked 1 declarations, 1 failed, in 0.00276974s wall (1.61615e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/088_projNotStruct"

Expected: ✋ reject · Size: 3.5 KB · Lines: 64 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projection out something that is not a structure

Test result: ✋ rejected · exit code 1 · wall time: 20 ms · instructions: 6.6 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 38 exprs (38 unique), 21 names in 0.000308909s
declaration order verified in 7.414e-06s
environment built in 2.4416e-05s; checking with 4 worker processes
FAIL projNotStruct (line 64): invalid projection N.0
checked 1 declarations, 1 failed, in 0.0042374s wall (3.60477e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/089_projProp1"

Expected: 👍 accept · Size: 8.2 KB · Lines: 143 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projecting out of a proposition

The lean kernel allows projections out of propositions if they precede all dependent data fields.

Test result: 👍 accepted · exit code 0 · wall time: 21 ms · instructions: 7.1 M · max rss memory: 21.7 MB

stderr:
loaded 4 declarations, 103 exprs (103 unique), 31 names in 0.000383599s
declaration order verified in 3.396e-06s
environment built in 2.0268e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.0032334s wall (2.10642e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/090_projProp2"

Expected: ✋ reject · Size: 8.2 KB · Lines: 143 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projecting out of a proposition

The lean kernel disallows data projections out of propositional structures.

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 7.2 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 103 exprs (103 unique), 31 names in 0.000302377s
declaration order verified in 2.324e-06s
environment built in 2.2292e-05s; checking with 4 worker processes
FAIL projProp2 (line 143): invalid projection PropStructure.1
checked 3 declarations, 1 failed, in 0.00241871s wall (1.77601e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/091_projProp3"

Expected: 👍 accept · Size: 8.2 KB · Lines: 143 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projecting out of a proposition

The lean kernel allows projections out of propositions if they precede all dependent data fields. Non-dependent data fields are not relevant.

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 7.1 M · max rss memory: 21.7 MB

stderr:
loaded 4 declarations, 103 exprs (103 unique), 31 names in 0.000347662s
declaration order verified in 2.385e-06s
environment built in 1.4026e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.0022923s wall (1.78498e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/092_projProp4"

Expected: ✋ reject · Size: 8.2 KB · Lines: 143 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projecting out of a proposition

The lean kernel disallows data projections out of propositional structures.

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 7.2 M · max rss memory: 21.7 MB

stderr:
loaded 4 declarations, 103 exprs (103 unique), 31 names in 0.00026622s
declaration order verified in 2.285e-06s
environment built in 1.4226e-05s; checking with 4 worker processes
FAIL projProp4 (line 143): invalid projection PropStructure.3
checked 3 declarations, 1 failed, in 0.00201607s wall (1.45956e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/093_projProp5"

Expected: ✋ reject · Size: 8.4 KB · Lines: 148 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projecting out of a proposition

The lean kernel disallows proof projections out of propositional structures that depend on data.

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 7.2 M · max rss memory: 21.7 MB

stderr:
loaded 4 declarations, 108 exprs (108 unique), 31 names in 0.000251351s
declaration order verified in 2.354e-06s
environment built in 1.2172e-05s; checking with 4 worker processes
FAIL projProp5 (line 148): invalid projection PropStructure.3
checked 3 declarations, 1 failed, in 0.00204538s wall (1.39253e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/094_projProp6"

Expected: ✋ reject · Size: 8.2 KB · Lines: 143 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projecting out of a proposition.

The lean kernel rejects any projections out of a proposition that come after a dependent data field, even if that is not used by the present projection.

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 7.2 M · max rss memory: 21.7 MB

stderr:
loaded 4 declarations, 103 exprs (103 unique), 31 names in 0.000348824s
declaration order verified in 2.394e-06s
environment built in 1.8364e-05s; checking with 4 worker processes
FAIL projProp6 (line 143): invalid projection PropStructure.5
checked 3 declarations, 1 failed, in 0.00325344s wall (1.8581e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/095_projDataIndexRec"

Expected: 👍 accept · Size: 6.8 KB · Lines: 111 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The recursor for ProjDataIndex allows elimination into sort.

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.9 M · max rss memory: 21.8 MB

stderr:
loaded 4 declarations, 72 exprs (72 unique), 31 names in 0.000173325s
declaration order verified in 2.114e-06s
environment built in 2.6008e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.00236779s wall (1.60757e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/096_projIndexData"

Expected: ✋ reject · Size: 14.1 KB · Lines: 226 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projecting out data is not allowed, even if this data appears as an index and the recursor would allow it.

Test result: ✋ rejected · exit code 1 · wall time: 18 ms · instructions: 7.8 M · max rss memory: 21.6 MB

stderr:
loaded 7 declarations, 163 exprs (163 unique), 51 names in 0.000366347s
declaration order verified in 2.434e-06s
environment built in 2.2933e-05s; checking with 4 worker processes
FAIL projIndexData (line 226): invalid projection PropStructure.0
checked 6 declarations, 1 failed, in 0.00328808s wall (2.43791e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/097_projIndexData2"

Expected: ✋ reject · Size: 14.1 KB · Lines: 226 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projecting out data is not allowed, even if this data appears as an index and the recursor would allow it.

This also forbids projecting out proofs that follow such fields.

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 7.8 M · max rss memory: 21.6 MB

stderr:
loaded 7 declarations, 163 exprs (163 unique), 51 names in 0.000377027s
declaration order verified in 2.405e-06s
environment built in 1.7663e-05s; checking with 4 worker processes
FAIL projIndexData2 (line 226): invalid projection PropStructure.1
checked 6 declarations, 1 failed, in 0.00268228s wall (2.04677e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/098_projRed"

Expected: 👍 accept · Size: 9.9 KB · Lines: 177 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Projection reductions

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 7.4 M · max rss memory: 21.8 MB

stderr:
loaded 6 declarations, 131 exprs (131 unique), 32 names in 0.00068831s
declaration order verified in 3.616e-06s
environment built in 1.8695e-05s; checking with 4 worker processes
checked 6 declarations, 0 failed, in 0.00267865s wall (2.27351e-06 core-hours over 4 workers); 2 reduction steps; peak 19 MB in one worker

Test "tutorial/099_ruleK"

Expected: 👍 accept · Size: 6.5 KB · Lines: 121 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Rule k for Eq: The recursor reduces even if the major argument is not a constructor, as long replacing the major argument with a constructor is type correct.

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 7.0 M · max rss memory: 21.8 MB

stderr:
loaded 3 declarations, 83 exprs (83 unique), 31 names in 0.000180378s
declaration order verified in 2.104e-06s
environment built in 2.3905e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00324191s wall (2.21334e-06 core-hours over 4 workers); 4 reduction steps; peak 19 MB in one worker

Test "tutorial/100_ruleKbad"

Expected: ✋ reject · Size: 6.5 KB · Lines: 121 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Rule k for Eq should not fire if the types of the major argument do not match that of the constructor.

Test result: ✋ rejected · exit code 1 · wall time: 18 ms · instructions: 7.1 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 83 exprs (83 unique), 31 names in 0.00015958s
declaration order verified in 4.749e-06s
environment built in 2.5428e-05s; checking with 4 worker processes
FAIL ruleKbad (line 121): declaration type mismatch for 'ruleKbad'
  inferred: ((x._@.Tutorial.3161876795._hygCtx._hyg.27 : (((Eq.{1} Bool) Bool.true) Bool.false)) -> ((a : Bool) -> (((Eq.{1} Bool) #0) #0)))
  declared: ((h : (((Eq.{1} Bool) Bool.true) Bool.false)) -> ((a : Bool) -> (((Eq.{1} Bool) ((((((Eq.rec.{1, 1} Bool) Bool.true) (fun (x._@.Tutorial.3161876795._hygCtx._hyg.17 : Bool) => (fun (x._@.Tutorial.3161876795._hygCtx._hyg.19 : (((Eq.{1} Bool) Bool.true) #0)) => Bool))) #0) Bool.false) #1)) #0)))
checked 2 declarations, 1 failed, in 0.00314128s wall (1.89079e-06 core-hours over 4 workers); 0 reduction steps; peak 20 MB in one worker

Test "tutorial/101_ruleKAcc"

Expected: ✋ reject · Size: 12.5 KB · Lines: 229 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Rule k should not fire for Acc.

Test result: ✋ rejected · exit code 1 · wall time: 19 ms · instructions: 8.2 M · max rss memory: 21.5 MB

stderr:
loaded 4 declarations, 180 exprs (180 unique), 41 names in 0.00038914s
declaration order verified in 3.066e-06s
environment built in 1.2684e-05s; checking with 4 worker processes
FAIL ruleKAcc (line 229): declaration type mismatch for 'ruleKAcc'
  inferred: ((α : Sort(u)) -> ((p : ((a._@._internal._hyg.0 : #0) -> ((a._@._internal._hyg.0 : #1) -> Sort(0)))) -> ((x : #1) -> ((h : (((Acc.{u} #2) #1) #0)) -> ((a : Bool) -> (((Eq.{1} Bool) #0) #0))))))
  declared: ((α : Sort(u)) -> ((p : ((a._@._internal._hyg.0 : #0) -> ((a._@._internal._hyg.0 : #1) -> Sort(0)))) -> ((x : #1) -> ((h : (((Acc.{u} #2) #1) #0)) -> ((a : Bool) -> (((Eq.{1} Bool) ((((((Acc.rec.{1, u} #4) #3) (fun (x._@.Tutorial.4255978773._hygCtx._hyg.22 : #4) => (fun (x._@.Tutorial.4255978773._hygCtx._hyg.24 : (((Acc.{u} #5) #4) #0)) => Bool))) (fun (x._@.Tutorial.4255978773._hygCtx._hyg.31 : #4) => (fun (x._@.Tutorial.4255978773._hygCtx._hyg.33 : ((y : #5) -> ((a._@._internal._hyg.0 : ((#5 #0) #1)) -> (((Acc.{u} #7) #6) #1)))) => (fun (x._@.Tutorial.4255978773._hygCtx._hyg.35 : ((y : #6) -> ((a._@._internal._hyg.0 : ((#6 #0) #2)) -> Bool))) => #3)))) #2) #1)) #0))))))
checked 3 declarations, 1 failed, in 0.00481265s wall (2.69291e-06 core-hours over 4 workers); 0 reduction steps; peak 21 MB in one worker

Test "tutorial/102_aNatLit"

Expected: 👍 accept · Size: 3.0 KB · Lines: 54 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Type checking Nat literals

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 6.5 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 37 exprs (37 unique), 12 names in 0.000113813s
declaration order verified in 3.536e-06s
environment built in 1.3125e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00214809s wall (1.35301e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/103_natLitEq"

Expected: 👍 accept · Size: 6.1 KB · Lines: 114 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Reducing Nat literals

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 7.0 M · max rss memory: 21.8 MB

stderr:
loaded 3 declarations, 84 exprs (84 unique), 23 names in 0.000163948s
declaration order verified in 9.107e-06s
environment built in 2.3574e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00252433s wall (2.20729e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/104_proofIrrelevance"

Expected: 👍 accept · Size: 5.0 KB · Lines: 100 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Proof irrelevance: every Prop is a subsingleton, if p : Prop then all elements of p are definitionally equal.

Test result: 👍 accepted · exit code 0 · wall time: 14 ms · instructions: 6.8 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 66 exprs (66 unique), 28 names in 9.8785e-05s
declaration order verified in 1.974e-06s
environment built in 1.7844e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00207827s wall (1.26443e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/105_proofIrrelevanceBad"

Expected: ✋ reject · Size: 4.7 KB · Lines: 93 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Proof irrelevance is limited to Prop: if p : Type, then all elements of p are not definitionally equal.

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.8 M · max rss memory: 21.7 MB

stderr:
loaded 3 declarations, 67 exprs (67 unique), 19 names in 9.8495e-05s
declaration order verified in 5.871e-06s
environment built in 1.4457e-05s; checking with 4 worker processes
FAIL proofIrrelevanceBad (line 93): declaration type mismatch for 'proofIrrelevanceBad'
  inferred: ((p : Sort(1)) -> ((h1 : #0) -> ((h2 : #1) -> (((Eq.{1} #2) #1) #1))))
  declared: ((p : Sort(1)) -> ((h1 : #0) -> ((h2 : #1) -> (((Eq.{1} #2) #1) #0))))
checked 2 declarations, 1 failed, in 0.00315429s wall (2.1062e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/106_proofIrrelevanceWhnf"

Expected: 👍 accept · Size: 5.6 KB · Lines: 112 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Proof irrelevance: if p : A and A is definitionally equal to Prop, then all elements of p are still definitionally equal. Just applying proof irrelevance at Sort 0 isn't sufficient.

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.9 M · max rss memory: 21.7 MB

stderr:
loaded 4 declarations, 74 exprs (74 unique), 29 names in 0.000137468s
declaration order verified in 2.485e-06s
environment built in 1.6781e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.00252246s wall (1.56753e-06 core-hours over 4 workers); 10 reduction steps; peak 19 MB in one worker

Test "tutorial/107_proofIrrelevanceUnderBinder"

Expected: 👍 accept · Size: 1.9 KB · Lines: 39 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Proof irrelevance applies to any two terms of a proposition, not just to variables. Checking this definition needs aPropFamily (h anElem) ≡ aPropFamily (h anotherElem), i.e. h anElem ≡ h anotherElem. Both are proofs of aProp, since h : aType → aProp, so they are definitionally equal even though their arguments are not. A checker that compares the two applications structurally, without first noticing that they are proofs, wrongly rejects this.

Test result: 👍 accepted · exit code 0 · wall time: 14 ms · instructions: 6.4 M · max rss memory: 21.9 MB

stderr:
loaded 7 declarations, 17 exprs (17 unique), 13 names in 0.000135173s
declaration order verified in 5.681e-06s
environment built in 2.1029e-05s; checking with 4 worker processes
checked 7 declarations, 0 failed, in 0.00223086s wall (1.35923e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/108_unitEta1"

Expected: 👍 accept · Size: 6.2 KB · Lines: 116 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Unit eta

Test result: 👍 accepted · exit code 0 · wall time: 13 ms · instructions: 6.9 M · max rss memory: 21.7 MB

stderr:
loaded 5 declarations, 77 exprs (77 unique), 30 names in 0.00014405s
declaration order verified in 2.014e-06s
environment built in 3.9464e-05s; checking with 4 worker processes
checked 5 declarations, 0 failed, in 0.00179044s wall (1.40336e-06 core-hours over 4 workers); 4 reduction steps; peak 19 MB in one worker

Test "tutorial/109_unitEta2"

Expected: 👍 accept · Size: 5.9 KB · Lines: 109 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Unit eta

Test result: 👍 accepted · exit code 0 · wall time: 14 ms · instructions: 6.9 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 73 exprs (73 unique), 29 names in 0.000179747s
declaration order verified in 6.252e-06s
environment built in 1.5709e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.00206854s wall (1.6182e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/110_unitEta3"

Expected: 👍 accept · Size: 6.0 KB · Lines: 111 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Unit eta

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.9 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 75 exprs (75 unique), 29 names in 0.000113784s
declaration order verified in 2.004e-06s
environment built in 1.5699e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.00186466s wall (1.34696e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/111_indexedUnitEta"

Expected: ✋ reject · Size: 7.2 KB · Lines: 121 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The unit-like rule, which makes any two elements of a single-constructor type with no fields definitionally equal, is also restricted to non-recursive structures without indices (is_def_eq_unit_like goes through is_non_rec_structure), so it does not fire for IndexedUnit.

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 7.1 M · max rss memory: 21.7 MB

stderr:
loaded 4 declarations, 86 exprs (86 unique), 27 names in 0.000126226s
declaration order verified in 2.124e-06s
environment built in 1.2944e-05s; checking with 4 worker processes
FAIL indexedUnitEta (line 121): declaration type mismatch for 'indexedUnitEta'
  inferred: ((x : (IndexedUnit Bool.true)) -> ((y : (IndexedUnit Bool.true)) -> (((Eq.{1} (IndexedUnit Bool.true)) #1) #1)))
  declared: ((x : (IndexedUnit Bool.true)) -> ((y : (IndexedUnit Bool.true)) -> (((Eq.{1} (IndexedUnit Bool.true)) #1) #0)))
checked 3 declarations, 1 failed, in 0.0022743s wall (1.67317e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/112_structEta"

Expected: 👍 accept · Size: 12.5 KB · Lines: 230 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Structure eta

Test result: 👍 accepted · exit code 0 · wall time: 19 ms · instructions: 7.9 M · max rss memory: 21.7 MB

stderr:
loaded 7 declarations, 173 exprs (173 unique), 43 names in 0.000369493s
declaration order verified in 2.736e-06s
environment built in 6.1024e-05s; checking with 4 worker processes
checked 7 declarations, 0 failed, in 0.00442025s wall (3.12704e-06 core-hours over 4 workers); 4 reduction steps; peak 19 MB in one worker

Test "tutorial/113_indexedStructEta"

Expected: ✋ reject · Size: 8.5 KB · Lines: 138 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Structure eta applies only to non-recursive structures without indices: the official kernel's is_non_rec_structure requires nindices == 0, so it does not fire for IndexedSingleton even though that has a single constructor.

Every field of IndexedSingleton.mk is a proof, so a kernel that checks only "has a single constructor" and then compares the fields against projections would have proof irrelevance discharge the remaining goals, and would wrongly accept this.

Test result: ✋ rejected · exit code 1 · wall time: 18 ms · instructions: 7.2 M · max rss memory: 21.6 MB

stderr:
loaded 5 declarations, 99 exprs (99 unique), 30 names in 0.000365736s
declaration order verified in 2.816e-06s
environment built in 3.1328e-05s; checking with 4 worker processes
FAIL indexedStructEta (line 138): declaration type mismatch for 'indexedStructEta'
  inferred: ((a : (IndexedSingleton Bool.true)) -> (((Eq.{1} (IndexedSingleton Bool.true)) #0) #0))
  declared: ((x : (IndexedSingleton Bool.true)) -> (((Eq.{1} (IndexedSingleton Bool.true)) (IndexedSingleton.mk True.intro)) #0))
checked 4 declarations, 1 failed, in 0.0030865s wall (2.30698e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/114_funEta"

Expected: 👍 accept · Size: 5.2 KB · Lines: 104 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Function eta for non-dependent functions.

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 6.8 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 71 exprs (71 unique), 26 names in 0.000188233s
declaration order verified in 2.645e-06s
environment built in 1.6201e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00270154s wall (2.20476e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/115_funEtaDep"

Expected: 👍 accept · Size: 5.3 KB · Lines: 106 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Function eta for dependent functions (pi types).

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.9 M · max rss memory: 21.5 MB

stderr:
loaded 3 declarations, 73 exprs (73 unique), 26 names in 0.000201387s
declaration order verified in 8.476e-06s
environment built in 1.6792e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.0026762s wall (2.00873e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/116_funEtaBad"

Expected: ✋ reject · Size: 4.9 KB · Lines: 97 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Eta should not identify functions with different bodies.

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.9 M · max rss memory: 21.5 MB

stderr:
loaded 2 declarations, 64 exprs (64 unique), 27 names in 0.000201408s
declaration order verified in 1.2884e-05s
environment built in 3.7931e-05s; checking with 4 worker processes
FAIL funEtaBad (line 97): declaration type mismatch for 'funEtaBad'
  inferred: ((x._@.Tutorial.4249243883._hygCtx._hyg.28 : Sort(1)) -> ((x._@.Tutorial.4249243883._hygCtx._hyg.30 : Sort(1)) -> ((x._@.Tutorial.4249243883._hygCtx._hyg.32 : ((a._@._internal._hyg.0 : #1) -> #2)) -> ((f : ((a._@._internal._hyg.0 : #2) -> #2)) -> (((Eq.{1} ((x : #3) -> #3)) #0) #0)))))
  declared: ((α : Sort(1)) -> ((β : Sort(1)) -> ((g : ((a._@._internal._hyg.0 : #1) -> #2)) -> ((f : ((a._@._internal._hyg.0 : #2) -> #2)) -> (((Eq.{1} ((x : #3) -> #3)) (fun (x : #3) => (#1 (#2 #0)))) #0)))))
checked 1 declarations, 1 failed, in 0.00317006s wall (2.46737e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/117_reflOccLeft"

Expected: ✋ reject · Size: 3.7 KB · Lines: 61 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Rejection: recursive occurrence on the left of an arrow, behind further arrows inside a constructor argument.

The constructor argument is a function type Nat → (I → Nat).

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 6.7 M · max rss memory: 21.7 MB

stderr:
loaded 2 declarations, 41 exprs (41 unique), 15 names in 0.000129223s
declaration order verified in 6.983e-06s
environment built in 1.2975e-05s; checking with 4 worker processes
FAIL reflOccLeft (line 61): arg #1 of 'reflOccLeft.mk' has a non positive occurrence of the datatypes being declared
checked 1 declarations, 1 failed, in 0.00219266s wall (1.47591e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/118_reflOccInIndex"

Expected: ✋ reject · Size: 3.9 KB · Lines: 66 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Rejection: recursive occurrence in index position, behind a further arrow.

We build an indexed inductive I : Type → Type with a constructor argument Nat → I (I α), so the recursive occurrence appears as an index argument.

Test result: ✋ rejected · exit code 1 · wall time: 38 ms · instructions: 6.7 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 45 exprs (45 unique), 16 names in 0.000150322s
declaration order verified in 1.095e-05s
environment built in 3.2831e-05s; checking with 4 worker processes
FAIL reflOccInIndex (line 66): application type mismatch in (reflOccInIndex $3)
  argument type: Nat
  expected: Sort(1)
checked 1 declarations, 1 failed, in 0.00263095s wall (2.03245e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/119_reduceCtorParamRefl.mk"

Expected: 👍 accept · Size: 4.5 KB · Lines: 88 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

When checking inductives, we expect the kernel to reduce the types of constructor arguments in all positive positions.

Test result: 👍 accepted · exit code 0 · wall time: 18 ms · instructions: 6.8 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 62 exprs (62 unique), 18 names in 0.000119814s
declaration order verified in 9.036e-06s
environment built in 1.7132e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00276009s wall (1.62052e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/120_reduceCtorParamRefl2.mk"

Expected: 👍 accept · Size: 4.5 KB · Lines: 88 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

When checking inductives, we expect the kernel to reduce the types of constructor arguments in all positive positions.

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 6.8 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 62 exprs (62 unique), 18 names in 0.000147957s
declaration order verified in 7.604e-06s
environment built in 1.7303e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00272814s wall (2.00647e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/121_rTreeRec"

Expected: 👍 accept · Size: 5.5 KB · Lines: 91 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of the generated recursor.

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 6.8 M · max rss memory: 21.7 MB

stderr:
loaded 3 declarations, 60 exprs (60 unique), 24 names in 0.000145402s
declaration order verified in 2.805e-06s
environment built in 1.9947e-05s; checking with 4 worker processes
checked 3 declarations, 0 failed, in 0.00226532s wall (1.38685e-06 core-hours over 4 workers); 0 reduction steps; peak 18 MB in one worker

Test "tutorial/122_rtreeRecReduction"

Expected: 👍 accept · Size: 10.7 KB · Lines: 191 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Reduction behavior of RTree.rec on RTree.mk.

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 7.4 M · max rss memory: 21.6 MB

stderr:
loaded 6 declarations, 134 exprs (134 unique), 47 names in 0.000385283s
declaration order verified in 2.805e-06s
environment built in 2.11e-05s; checking with 4 worker processes
checked 6 declarations, 0 failed, in 0.00261937s wall (1.92791e-06 core-hours over 4 workers); 14 reduction steps; peak 19 MB in one worker

Test "tutorial/123_accRecType"

Expected: 👍 accept · Size: 7.5 KB · Lines: 151 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of Acc.rec.

Test result: 👍 accepted · exit code 0 · wall time: 17 ms · instructions: 7.4 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 124 exprs (124 unique), 21 names in 0.000148549s
declaration order verified in 5.621e-06s
environment built in 1.592e-05s; checking with 4 worker processes
checked 2 declarations, 0 failed, in 0.00364886s wall (2.31146e-06 core-hours over 4 workers); 0 reduction steps; peak 20 MB in one worker

Test "tutorial/124_accRecReduction"

Expected: 👍 accept · Size: 13.0 KB · Lines: 243 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Acc.rec reduces on Acc.intro.

Test result: 👍 accepted · exit code 0 · wall time: 25 ms · instructions: 8.5 M · max rss memory: 21.7 MB

stderr:
loaded 4 declarations, 193 exprs (193 unique), 42 names in 0.000470632s
declaration order verified in 3.607e-06s
environment built in 2.09e-05s; checking with 4 worker processes
checked 4 declarations, 0 failed, in 0.0072115s wall (4.44237e-06 core-hours over 4 workers); 9 reduction steps; peak 21 MB in one worker

Test "tutorial/125_accRecNoEta"

Expected: ✋ reject · Size: 12.7 KB · Lines: 235 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Acc.rec does not have structure eta.

Test result: ✋ rejected · exit code 1 · wall time: 21 ms · instructions: 8.2 M · max rss memory: 21.6 MB

stderr:
loaded 4 declarations, 186 exprs (186 unique), 41 names in 0.000346479s
declaration order verified in 3.567e-06s
environment built in 2.6139e-05s; checking with 4 worker processes
FAIL accRecNoEta (line 235): declaration type mismatch for 'accRecNoEta'
  inferred: ((α : Sort(1)) -> ((r : ((a._@._internal._hyg.0 : #0) -> ((a._@._internal._hyg.0 : #1) -> Sort(0)))) -> ((a : #1) -> ((h : (((Acc.{1} #2) #1) #0)) -> ((a : Bool) -> (((Eq.{1} Bool) #0) #0))))))
  declared: ((α : Sort(1)) -> ((r : ((a._@._internal._hyg.0 : #0) -> ((a._@._internal._hyg.0 : #1) -> Sort(0)))) -> ((a : #1) -> ((h : (((Acc.{1} #2) #1) #0)) -> ((p : Bool) -> (((Eq.{1} Bool) ((((((Acc.rec.{1, 1} #4) #3) (fun (x._@.Tutorial.4017164079._hygCtx._hyg.22 : #4) => (fun (x._@.Tutorial.4017164079._hygCtx._hyg.24 : (((Acc.{1} #5) #4) #0)) => Bool))) (fun (x._@.Tutorial.4017164079._hygCtx._hyg.31 : #4) => (fun (x._@.Tutorial.4017164079._hygCtx._hyg.33 : ((y : #5) -> ((a._@._internal._hyg.0 : ((#5 #0) #1)) -> (((Acc.{1} #7) #6) #1)))) => (fun (x._@.Tutorial.4017164079._hygCtx._hyg.35 : ((y : #6) -> ((a._@._internal._hyg.0 : ((#6 #0) #2)) -> Bool))) => #3)))) #2) #1)) #0))))))
checked 3 declarations, 1 failed, in 0.00566812s wall (3.37802e-06 core-hours over 4 workers); 0 reduction steps; peak 21 MB in one worker

Test "tutorial/126_quotMkType"

Expected: 👍 accept · Size: 6.3 KB · Lines: 123 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of Quot.mk.

Test result: 👍 accepted · exit code 0 · wall time: 20 ms · instructions: 6.8 M · max rss memory: 21.5 MB

stderr:
loaded 6 declarations, 87 exprs (87 unique), 26 names in 0.000121879s
declaration order verified in 5.55e-06s
environment built in 1.2754e-05s; checking with 4 worker processes
checked 6 declarations, 0 failed, in 0.00289091s wall (1.568e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/127_quotIndType"

Expected: 👍 accept · Size: 6.3 KB · Lines: 124 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of Quot.ind.

Test result: 👍 accepted · exit code 0 · wall time: 20 ms · instructions: 6.8 M · max rss memory: 21.6 MB

stderr:
loaded 6 declarations, 88 exprs (88 unique), 26 names in 0.000203963s
declaration order verified in 2.976e-06s
environment built in 2.9826e-05s; checking with 4 worker processes
checked 6 declarations, 0 failed, in 0.00342665s wall (2.62925e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/128_quotLiftType"

Expected: 👍 accept · Size: 6.3 KB · Lines: 124 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of Quot.lift.

Test result: 👍 accepted · exit code 0 · wall time: 21 ms · instructions: 6.8 M · max rss memory: 21.6 MB

stderr:
loaded 6 declarations, 88 exprs (88 unique), 26 names in 0.000139662s
declaration order verified in 6.503e-06s
environment built in 1.6281e-05s; checking with 4 worker processes
checked 6 declarations, 0 failed, in 0.00343067s wall (2.09582e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/129_quotSoundType"

Expected: 👍 accept · Size: 7.2 KB · Lines: 141 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Asserting the type of Quot.sound.

Test result: 👍 accepted · exit code 0 · wall time: 21 ms · instructions: 6.9 M · max rss memory: 21.7 MB

stderr:
loaded 7 declarations, 103 exprs (103 unique), 27 names in 0.000219992s
declaration order verified in 3.848e-06s
environment built in 3.192e-05s; checking with 4 worker processes
checked 7 declarations, 0 failed, in 0.0036281s wall (2.60754e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/130_quotLiftReduction"

Expected: 👍 accept · Size: 7.8 KB · Lines: 153 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Reduction behavior of Quot.lift on Quot.mk.

Test result: 👍 accepted · exit code 0 · wall time: 15 ms · instructions: 7.1 M · max rss memory: 21.7 MB

stderr:
loaded 6 declarations, 116 exprs (116 unique), 27 names in 0.000105708s
declaration order verified in 4.799e-06s
environment built in 1.7503e-05s; checking with 4 worker processes
checked 6 declarations, 0 failed, in 0.003254s wall (1.86787e-06 core-hours over 4 workers); 2 reduction steps; peak 20 MB in one worker

Test "tutorial/131_quotIndReduction"

Expected: 👍 accept · Size: 7.6 KB · Lines: 151 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Reduction behavior of Quot.ind on Quot.mk.

Test result: 👍 accepted · exit code 0 · wall time: 16 ms · instructions: 7.1 M · max rss memory: 21.8 MB

stderr:
loaded 6 declarations, 115 exprs (115 unique), 26 names in 0.000123221s
declaration order verified in 2.094e-06s
environment built in 1.3766e-05s; checking with 4 worker processes
checked 6 declarations, 0 failed, in 0.00308289s wall (1.82496e-06 core-hours over 4 workers); 2 reduction steps; peak 20 MB in one worker

Test "tutorial/132_dup_defs"

Expected: ✋ reject · Size: 475 B · Lines: 7 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Two definitions with the same name

Test result: ✋ rejected · exit code 1 · wall time: 12 ms · instructions: 6.3 M · max rss memory: 21.8 MB

stderr:
loaded 2 declarations, 2 exprs (2 unique), 1 names in 9.8334e-05s
declaration order verified in 1.764e-06s
error: constant already declared: dup_defs

Test "tutorial/133_dup_ind_def"

Expected: ✋ reject · Size: 1.7 KB · Lines: 27 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A definition and a constructor with the same name

Test result: ✋ rejected · exit code 1 · wall time: 13 ms · instructions: 6.3 M · max rss memory: 21.9 MB

stderr:
loaded 2 declarations, 15 exprs (15 unique), 7 names in 0.000104015s
declaration order verified in 2.134e-06s
error: constant already declared: dup_ind_def

Test "tutorial/134_dup_ctor_def"

Expected: ✋ reject · Size: 1.7 KB · Lines: 27 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A definition and a constructor with the same name

Test result: ✋ rejected · exit code 1 · wall time: 12 ms · instructions: 6.3 M · max rss memory: 22.2 MB

stderr:
loaded 2 declarations, 15 exprs (15 unique), 7 names in 8.9949e-05s
declaration order verified in 2.415e-06s
error: constant already declared: dup_ctor_def.mk

Test "tutorial/135_dup_rec_def"

Expected: ✋ reject · Size: 1.7 KB · Lines: 27 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A definition and a recursor with the same name

Test result: ✋ rejected · exit code 1 · wall time: 13 ms · instructions: 6.3 M · max rss memory: 21.9 MB

stderr:
loaded 2 declarations, 15 exprs (15 unique), 7 names in 8.6662e-05s
declaration order verified in 4.628e-06s
error: constant already declared: dup_rec_def.rec

Test "tutorial/136_misnamed_rec_user"

Expected: ✋ reject · Size: 2.0 KB · Lines: 33 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

The name of the recursor for misnamed_rec must be misnamed_rec.rec: another name (like misnamed_rec.not_rec) should be rejected. dupRecUser is included so that checkers that recreate the recursor (as misnamed_rec.rec) rather than validating it still fail, because misnamed_rec_user references misnamed_rec.not_rec.

Test result: ✋ rejected · exit code 1 · wall time: 14 ms · instructions: 6.4 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 18 exprs (18 unique), 9 names in 0.000105017s
declaration order verified in 1.994e-06s
environment built in 1.2032e-05s; checking with 4 worker processes
FAIL misnamed_rec (line 25): recursor 'misnamed_rec.rec' missing from the export
checked 0 declarations, 1 failed, in 0.00162225s wall (1.13211e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/137_dup_rec_def2"

Expected: ✋ reject · Size: 1.7 KB · Lines: 28 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Even if a kernel doesn't catch a recursor for dup_rec_def2 that is misnamed as dup_rec_def2.not_rec, it should catch some other constant being given the name dup_rec_def2.rec that is reserved for the recursor.

Test result: ✋ rejected · exit code 1 · wall time: 17 ms · instructions: 6.4 M · max rss memory: 21.6 MB

stderr:
loaded 2 declarations, 15 exprs (15 unique), 8 names in 0.000123622s
declaration order verified in 2.024e-06s
environment built in 1.3446e-05s; checking with 4 worker processes
FAIL dup_rec_def2 (line 28): recursor 'dup_rec_def2.rec' missing from the export
checked 1 declarations, 1 failed, in 0.00221181s wall (1.44053e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/138_dup_ctor_rec"

Expected: ✋ reject · Size: 1.5 KB · Lines: 24 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

A constructor and a recursor with the same name

Test result: ✋ rejected · exit code 1 · wall time: 15 ms · instructions: 6.3 M · max rss memory: 21.9 MB

stderr:
loaded 1 declarations, 14 exprs (14 unique), 6 names in 0.000111018s
declaration order verified in 2.104e-06s
error: constant already declared: dup_ctor_rec.rec

Test "tutorial/139_DupConCon"

Expected: ✋ reject · Size: 2.2 KB · Lines: 34 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

An inductive with two constructors with the same name

Test result: ✋ rejected · exit code 1 · wall time: 13 ms · instructions: 6.3 M · max rss memory: 21.6 MB

stderr:
loaded 1 declarations, 21 exprs (21 unique), 9 names in 0.000271158s
declaration order verified in 4.528e-06s
error: constant already declared: dup_ind_con_con.mk

Test "tutorial/140_falseFromUnsafe"

Expected: ✋ reject · Size: 1.3 KB · Lines: 22 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Unsafe definitions cannot be used in theorems

Test result: ✋ rejected · exit code 1 · wall time: 14 ms · instructions: 6.4 M · max rss memory: 21.6 MB

stderr:
loaded 3 declarations, 10 exprs (10 unique), 7 names in 0.000254527s
declaration order verified in 2.435e-06s
environment built in 2.2492e-05s; checking with 4 worker processes
FAIL falseFromUnsafe (line 22): invalid declaration, it uses unsafe declaration 'unsafeLoop'
checked 2 declarations, 1 failed, in 0.00170396s wall (1.26531e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker

Test "tutorial/141_falseFromPartial"

Expected: ✋ reject · Size: 1.3 KB · Lines: 22 · lean4export: 3.1.0 · Lean: 4.34.1 · 📄 Declaration · 🔗 Source

Partial definitions cannot be used in theorems

Test result: ✋ rejected · exit code 1 · wall time: 16 ms · instructions: 6.4 M · max rss memory: 21.5 MB

stderr:
loaded 3 declarations, 10 exprs (10 unique), 7 names in 0.000292248s
declaration order verified in 4.919e-06s
environment built in 1.593e-05s; checking with 4 worker processes
FAIL partialLoop (line 20): invalid declaration, it uses unsafe declaration 'partialLoop'
checked 1 declarations, 1 failed, in 0.00201253s wall (1.41643e-06 core-hours over 4 workers); 0 reduction steps; peak 19 MB in one worker