Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
9fde4c6
feat: certify recursive normalization candidates
johnchandlerburnham Jul 31, 2026
b283912
feat: certify annotated normalization binders
johnchandlerburnham Jul 31, 2026
a84aa19
feat: certify singleton normalization candidates
johnchandlerburnham Jul 31, 2026
c2b1c4f
feat: assemble candidate generation certificates
johnchandlerburnham Jul 31, 2026
a1d8943
feat: replay annotated recursive Pi induction
johnchandlerburnham Aug 1, 2026
6a77882
feat: certify non-identity inductive transactions
johnchandlerburnham Aug 1, 2026
bc37d43
feat: certify executable inductive candidates
johnchandlerburnham Aug 1, 2026
5e5bb76
feat: advance annotated Pi validation
johnchandlerburnham Aug 1, 2026
33b99f4
feat: certify annotated Pi constructors
johnchandlerburnham Aug 1, 2026
a3ff992
feat: certify annotated Pi producer
johnchandlerburnham Aug 1, 2026
9a865ea
feat: generalize candidate family validation
johnchandlerburnham Aug 1, 2026
8cfbbb4
state the front-end theorem; update stale notes
digama0 Jul 31, 2026
3dc52e0
Prove Expr cached flag correctness (#19)
kim-em Aug 1, 2026
54a532a
Bump Lean toolchain to v4.30.0 (#20)
kim-em Aug 2, 2026
9fc9c83
fix: SIGSEGV in replayFromImports from freeing regions still in use
digama0 Aug 2, 2026
f3e7094
add GitHub Actions CI
digama0 Aug 2, 2026
d7e70a5
fix: soundness bug from leanprover/lean4#14577
digama0 Jul 29, 2026
7842f38
fix: move the Std.Basic prelude into the Lean4Lean namespace
digama0 Aug 2, 2026
a627362
feat: certify indexed family candidates
johnchandlerburnham Aug 2, 2026
c341302
docs: correct theorem delta-reduction comments (#21)
kim-em Aug 2, 2026
f0d80f8
perf: short-circuit syntactic definitional equality
johnchandlerburnham Aug 2, 2026
6732659
proof: verify IndexedVec nil constructor candidate
johnchandlerburnham Aug 2, 2026
29d9243
use the standard library level operations (#22)
kim-em Aug 2, 2026
66172a2
fix: prove the mkAppRangeAux equation instead of assuming it (#26)
kim-em Aug 2, 2026
c40a471
proof: verify IndexedVec cons constructor candidate
johnchandlerburnham Aug 2, 2026
c739d41
fix: stabilize inductive candidate context provenance
johnchandlerburnham Aug 2, 2026
82f4a54
feat: certify IndexedVec outer candidate production
johnchandlerburnham Aug 2, 2026
d553930
feat: support exact identity candidate replay
johnchandlerburnham Aug 2, 2026
cf3d5a4
feat: certify IndexedVec semantic generation
johnchandlerburnham Aug 2, 2026
997e298
fix: recognize sorts as `Prop` up to universe normalization
digama0 Aug 2, 2026
d35a2f6
docs: record IndexedVec semantic checkpoint
johnchandlerburnham Aug 2, 2026
c9e4ae2
feat: generalize candidate list production
johnchandlerburnham Aug 2, 2026
9ff6be1
docs: record source-indexed list checkpoint
johnchandlerburnham Aug 2, 2026
a7d101b
feat: generalize produced candidate packaging
johnchandlerburnham Aug 2, 2026
80f9dce
docs: record produced-package checkpoint
johnchandlerburnham Aug 2, 2026
5b1385a
fix: replay `Eq` before adding `Quot`
nomeata Feb 23, 2026
f0caf16
feat: retain candidate semantic hierarchy
johnchandlerburnham Aug 2, 2026
ea14f31
docs: record semantic-hierarchy checkpoint
johnchandlerburnham Aug 2, 2026
6ff1690
refactor: move replay into `Lean4Lean.Replay`
digama0 Aug 2, 2026
e3cf22d
feat: assemble produced semantic hierarchy
johnchandlerburnham Aug 2, 2026
7e5f4f7
feat: harden semantic hierarchy ownership
johnchandlerburnham Aug 2, 2026
1093311
docs: record semantic ownership checkpoint
johnchandlerburnham Aug 2, 2026
2b1d802
feat: derive structural generation evidence
johnchandlerburnham Aug 2, 2026
0270843
docs: record structural generation evidence checkpoint
johnchandlerburnham Aug 2, 2026
a64fe98
feat: derive generation analyzer provenance
johnchandlerburnham Aug 2, 2026
4b66e50
docs: record generation analyzer provenance checkpoint
johnchandlerburnham Aug 2, 2026
095c0a9
chore: bump Lean toolchain to v4.31.0 (#29)
kim-em Aug 3, 2026
ef849df
fix: repair `Lean4Lean.Experimental` and cover it in CI
digama0 Aug 3, 2026
5aa9ab6
feat: derive generation shape alignment
johnchandlerburnham Aug 3, 2026
fda0016
docs: record generation shape alignment checkpoint
johnchandlerburnham Aug 3, 2026
bbb45e0
feat: consolidate generation readiness
johnchandlerburnham Aug 3, 2026
c4fd62b
docs: record generation readiness checkpoint
johnchandlerburnham Aug 3, 2026
f82ee77
docs: refactor roadmap into discrete checkpoints
johnchandlerburnham Aug 3, 2026
7c79220
feat: consolidate staged semantic inputs
johnchandlerburnham Aug 3, 2026
21b7a72
docs: record L4L-01A checkpoint
johnchandlerburnham Aug 3, 2026
da45b53
feat: derive family validation staging
johnchandlerburnham Aug 3, 2026
ac41ba9
docs: record L4L-01B checkpoint
johnchandlerburnham Aug 3, 2026
4ef21e0
docs: add upstream reconciliation checkpoint
johnchandlerburnham Aug 3, 2026
7f864b4
merge: reconcile upstream v4.31
johnchandlerburnham Aug 3, 2026
57af1c2
docs: record L4L-01U completion
johnchandlerburnham Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/scripts/check_sorry_frontier.pl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
"Lean4Lean/Verify/Typing/Lemmas.lean\0TrProj.instL" => 1,
# Tier V - checker verification, blocked on Tiers S/P
"Lean4Lean/Verify/Level.lean\0NormLevel.subsumption_eval" => 1,
"Lean4Lean/Verify/Level.lean\0isEquiv_wf" => 1,
"Lean4Lean/Verify/Environment.lean\0addDecl.WF" => 1,
"Lean4Lean/Verify/TypeChecker/InferType.lean\0inferProj.WF" => 1,
"Lean4Lean/Verify/TypeChecker/WHNF.lean\0reduceRecursor.WF" => 1,
"Lean4Lean/Verify/TypeChecker/WHNF.lean\0reduceProj.WF" => 1,
Expand Down
58 changes: 58 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: CI

on:
push:
branches: [master]
pull_request:
workflow_dispatch:

# A newer push to the same branch supersedes an in-flight run; master runs are
# never cancelled, since those are the ones that populate the build cache.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}

jobs:
build:
name: Build and self-check
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v7

# Installs the toolchain pinned in `lean-toolchain` and runs `lake build`,
# i.e. the `defaultTargets`: the `Lean4Lean` library, the `lean4lean` exe,
# `Lean4Lean.Theory`, `Lean4Lean.Verify` and `Lean4Lean.Tests`. The proofs
# in `Verify` deliberately contain `sorry`s, so warnings must not fail the
# build. `Lean4Lean.Experimental` is WIP and is not a default target.
- name: Build
uses: leanprover/lean-action@v1
with:
use-mathlib-cache: false

# `Lean4Lean.Experimental` is WIP and deliberately not a default target, but it still has to
# compile. `sorry`s here are expected, as in `Verify`.
- name: Build Lean4Lean.Experimental
run: lake build Lean4Lean.Experimental

# `lake build` only establishes that lean4lean compiles; these check that it still
# *works*. The two modes exercise different code paths, so both are worth running.

# Module-at-a-time replay, against an environment built from the module's imports.
# This is the path that goes through `replayFromImports`, including the compacted
# region handling that regressed into a SIGSEGV, so keep it as a regression test.
#
# One small module on purpose: `main` spawns an unbounded `IO.asTask` per module and
# each replay imports the world, so peak RSS scales with the fan-out and a large
# prefix (e.g. `Lean4Lean`) is OOM-killed. Widen once replay uses a bounded task
# pool, as lean4checker does.
- name: Replay Init.Core through lean4lean
run: lake exe lean4lean Init.Core

# `--fresh` instead rechecks the module *and all its imports* into an empty
# environment -- ~43k declarations, the closest thing to an end-to-end kernel test.
# Single-threaded and `withImportModules`-bracketed, so it stays cheap on memory.
# Core only: modules importing `Lean` currently fail with "type checker does not
# support loose bound variables" (digama0/lean4lean#17).
- name: Recheck Init.System.IO and its imports from scratch
run: lake exe lean4lean --fresh Init.System.IO

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +17 to +58
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/.lake
/result
/.direnv
/plans
# Keep scratch plans local while versioning the authoritative execution ladder.
/plans/*
!/plans/roadmap.md
15 changes: 15 additions & 0 deletions Lean4Lean/Declaration.lean
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ import Lean.Declaration


namespace Lean

/--
The value of a constant for the purpose of delta reduction: definitions and theorems have one,
opaques do not. This mirrors the C++ `constant_info::has_value()`/`get_value()` pair.

This is deliberately *not* `ConstantInfo.value?`, whose meaning changed in lean4#12973: it now
excludes theorems, but `constant_info::has_value()` was left untouched by that PR, so the kernel
still delta-unfolds theorems: `type_checker::is_delta` uses this predicate to select candidates,
and `instantiate_value_lparams` uses it before reading their values.
-/
def ConstantInfo.deltaValue? : ConstantInfo → Option Expr
| .defnInfo {value, ..} => some value
| .thmInfo {value, ..} => some value
| _ => none

namespace ReducibilityHints

def lt' : ReducibilityHints → ReducibilityHints → Bool -- lean4#2750
Expand Down
2 changes: 1 addition & 1 deletion Lean4Lean/Environment.lean
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ def addTheorem (env : Environment) (v : TheoremVal) (check := true) (fuel : Fuel
if check then
-- TODO(Leo): we must add support for handling tasks here
M.run env (safety := .safe) (lctx := {}) (lparams := v.levelParams) (fuel := fuel) do
checkConstantVal env v.toConstantVal
if !(← isProp v.type) then
throw <| .thmTypeIsNotProp env v.name v.type
checkConstantVal env v.toConstantVal
let valType ← TypeChecker.checkType v.value
if !(← isDefEq valType v.type) then
throw <| .declTypeMismatch env (.thmDecl v) valType
Expand Down
5 changes: 3 additions & 2 deletions Lean4Lean/Environment/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ def primitives : NameSet := .ofList [
/--
Returns true iff `constName` is a non-recursive inductive datatype that has only one constructor and no indices.

Such types have special kernel support. This must be in sync with `is_structure_like`.
Such types have special kernel support (e.g. the eta rule).
This must be in sync with `is_non_rec_structure()`.
-/
def isStructureLike (env : Environment) (constName : Name) : Bool :=
def isNonRecStructure (env : Environment) (constName : Name) : Bool :=
match env.find? constName with
| some (.inductInfo { isRec := false, ctors := [_], numIndices := 0, .. }) => true
| _ => false
Expand Down
2 changes: 1 addition & 1 deletion Lean4Lean/Experimental/NormalEq.lean
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Lean4Lean.Theory.Typing.Pattern

namespace Lean4Lean

open VExpr
open Lean4Lean VExpr

variable (IsDefEqU : List VExpr → VExpr → VExpr → Prop) (Γ₀ : List VExpr) in
inductive IsDefEqCtx : List VExpr → List VExpr → Prop
Expand Down
1 change: 1 addition & 0 deletions Lean4Lean/Experimental/SExpr.lean
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Lean4Lean.Theory.Typing.Lemmas
import Lean4Lean.Theory.Typing.Pattern

namespace Lean4Lean
open Lean4Lean

inductive Classification where
| ctor (arity : Nat)
Expand Down
18 changes: 9 additions & 9 deletions Lean4Lean/Experimental/ShapeLogRel.lean
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Lean4Lean.Experimental.SExpr

namespace Lean4Lean
open Lean4Lean

namespace SExpr
variable [Params]
Expand Down Expand Up @@ -2156,9 +2157,7 @@ theorem WShape.ctor'_join {l l' : List (WShape n)} {c : Name}
exact ih (fun z hz => h2' z (.tail _ hz))
· rw [dif_pos (key.mpr (.inr h2))]; simp [ctor, bot, Shape.bot_join]
have h1' : ∀ x ∈ l, x.1 ≤ Shape.bot := by
have ⟨hIs, hNZ⟩ : IsStruct c = true ∧ ¬ListNonZero l := by
refine ⟨?_, fun hNZ => h1 fun _ => hNZ⟩
by_contra hIs; exact h1 fun h => (hIs h).elim
have ⟨_, hNZ⟩ := Decidable.not_imp_iff_and_not.1 h1
simp [ListNonZero] at hNZ; exact hNZ
congr 1; clear h1 h2 key
induction h with | nil => rfl | @cons x y L L' hh _ ih
Expand Down Expand Up @@ -2531,7 +2530,7 @@ theorem Shape.HasType.unfold_iff {m a : Shape n} : HasType m a ↔ HasTypeU m a
| indTy => rfl
| forallE => simpa [HasType, hasType] using h
| sort => cases n <;> rfl
| forallE H => simpa [HasType, hasType, hasType.core.iff] using H
| forallE H => simpa [HasType, hasType, hasType.core.iff, HasTypePi] using H
| lam H => simp [HasType, hasType, hasType.core.iff]; exact H
| ctor | indTy => rfl

Expand Down Expand Up @@ -3440,7 +3439,7 @@ theorem LE_Interp.Matches.head_wf (H : Matches p c rargs m) (wf : p.WF cl top k)
theorem LE_Interp.Matches.head_wf_eq (H : Matches p c rargs m) (wf : p.WF cl top k) :
cl c = some (if top then .symb (k + rargs.length) else .ctor (k + rargs.length)) := by
induction H generalizing k with
| const => simpa using wf
| const => simpa [Pattern.WF] using wf
| var _ ih =>
have := ih (k := k + 1) wf
rw [List.length_cons]; rw [Nat.add_succ, ← Nat.succ_add]; exact this
Expand Down Expand Up @@ -3615,8 +3614,8 @@ theorem pat_arity (hP : Params.Pat p r) (h : Arity (.const c) n p) :
clear r hP h; intro cl n k h1 h2
induction h2 generalizing k with
| refl => simpa only [Nat.zero_add]
| var _ ih => simpa [Nat.succ_add] using ih _ h1
| app _ ih => simpa [Nat.succ_add] using ih _ h1.1
| var _ ih => simpa [Nat.succ_add, ← Nat.add_assoc] using ih _ h1
| app _ ih => simpa [Nat.succ_add, ← Nat.add_assoc] using ih _ h1.1

theorem LE_Interp.Matches.lift (le : n ≤ n') (H : Matches (n := n) p c rargs m) :
∃ m', Matches p c (rargs.map (.lift n')) m' ∧ ∀ p, m p ≤ m' p ∧ m' p ≤ m p := by
Expand Down Expand Up @@ -4627,7 +4626,7 @@ structure StrongSoundEq (Γ : List SExpr) (M N A : SExpr) : Prop where
left : StrongSound Γ M A
right : StrongSound Γ N A

theorem SoundEq.rfl : SoundEq Γ M M := fun _ _ _ _ => .rfl
protected theorem SoundEq.rfl : SoundEq Γ M M := fun _ _ _ _ => .rfl
theorem SoundEq.symm : SoundEq Γ M N → SoundEq Γ N M := fun H _ _ W _ => (H W).symm
theorem StrongSoundEq.hasType : StrongSoundEq Γ M N A → StrongSound Γ M A ∧ StrongSound Γ N A
| ⟨_, _, h1, h2⟩ => ⟨h1, h2⟩
Expand Down Expand Up @@ -4713,7 +4712,8 @@ theorem SoundEq.forallE_inv (H : SoundEq Γ (.forallE A B) (.forallE A' B'))
· refine fun _ => ⟨_, WShape.bot_le, .bot' (.bot' .sort), ?_⟩
simpa [WShapeFun.single_app] using .rfl
· intro x h'; cases h'.bot_r
simpa [WShapeFun.single_app] using h.mono_l fun _ => TShape.bot_le'
simpa [WShapeFun.single_app, show m.2.T = m from rfl] using
h.mono_l fun _ => TShape.bot_le'
| @cons Γ ρ A a x b1 b2 b3 b4 =>
let k := max (max x.1 m.1) a.1
have hk := Nat.max_le.1 (Nat.le_refl k); simp [Nat.max_le] at hk
Expand Down
2 changes: 1 addition & 1 deletion Lean4Lean/Experimental/Stratified.lean
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Lean4Lean.Theory.Typing.Strong
namespace Lean4Lean
namespace VEnv

open VExpr
open Lean4Lean VExpr

def DefInv (env : VEnv) (U : Nat) (Γ : List VExpr) : VExpr → VExpr → Prop
| .forallE A B, .forallE A' B' =>
Expand Down
2 changes: 1 addition & 1 deletion Lean4Lean/Experimental/StratifiedUntyped.lean
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Lean4Lean.Theory.Typing.Strong
namespace Lean4Lean
namespace VEnv

open VExpr
open Lean4Lean VExpr

section
set_option hygiene false
Expand Down
8 changes: 5 additions & 3 deletions Lean4Lean/Experimental/Stronger.lean
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Lean4Lean.Theory.Typing.Lemmas

namespace Lean4Lean

open VExpr
open Lean4Lean VExpr

structure VEnv'.VConstant extends Lean4Lean.VConstant where
level : VLevel
Expand Down Expand Up @@ -339,10 +339,12 @@ theorem IsDefEqStrong.instL (H : env.IsDefEqStrong U Γ e1 e2 A u) :
| defeqL _ _ h3 _ ih => exact .defeqL (.inst hls) (.inst hls) (VLevel.inst_congr_l h3) ih
| beta _ _ _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 ih6 =>
simpa using .beta (.inst hls) (.inst hls) ih1 ih2 ih3 ih4
(by simpa using ih5) (by simpa using ih6)
(by simpa [VExpr.instL, VLevel.inst] using ih5)
(by simpa [VExpr.instL, VLevel.inst] using ih6)
| eta _ _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 =>
simpa [VExpr.instL] using .eta (.inst hls) (.inst hls) ih1 ih2
(by simpa [VCtx.instL] using ih3) ih4 (by simpa [VExpr.instL] using ih5)
(by simpa [VCtx.instL, VExpr.instL, VLevel.inst] using ih3) ih4
(by simpa [VCtx.instL, VExpr.instL, VLevel.inst] using ih5)
| proofIrrel _ _ _ ih1 ih2 ih3 =>
exact .proofIrrel ih1 ih2 ih3
| extra h1 h2 h3 h4 _ _ _ _ _ _ ih1 ih2 ih3 ih4 ih5 =>
Expand Down
Loading
Loading