Skip to content

Aiur kernel: fix Lean.Syntax.rec (shard 53) + ix name-of#464

Open
arthurpaulino wants to merge 2 commits into
mainfrom
ap/aiur-aux-recursor-parity
Open

Aiur kernel: fix Lean.Syntax.rec (shard 53) + ix name-of#464
arthurpaulino wants to merge 2 commits into
mainfrom
ap/aiur-aux-recursor-parity

Conversation

@arthurpaulino

Copy link
Copy Markdown
Member

IxVM Aiur kernel: fix Lean.Syntax.rec (shard 53) aux-recursor gen

ix check --interp bytecode Lean.Syntax.rec failed with assert_eq mismatch: 0 != 1 on the declared-vs-canonical type equality. Three
interlocking bugs in the Aiur block-flattening / recursor-type builder:

  • Single-pass flat traversal. build_flat_block scanned originals
    once; nested-aux members (Array Syntax, List Syntax) never had
    their own ctors scanned, so flat had 2 motives when Lean's recursor
    declares 3. Replaced with a queue-based fixed point mirroring
    crates/kernel/src/inductive.rs:build_flat_block:531-599.

  • is_rec_field matched on const idx alone. For Lean.Syntax.ident
    the field preresolved : List Preresolved shares the base List
    const idx with the block's List Lean.Syntax aux, so it got a
    spurious motive_2 preresolved IH binder. Match key is now
    (head_idx, spine-arg prefix ≡ member.spec_params) — direct members
    carry spec_params = [] and match on idx alone; auxes require the
    concrete occurrence via new find_flat_member_match +
    spine_prefix_eq + kexpr_struct_eq helpers.

  • build_all_minors shrunk flat in-flight. It iterated flat and
    passed the shrinking suffix into build_minor_doms, so later members'
    ctor-field classification was blind to earlier members. Split into a
    thin wrapper build_all_minors + build_all_minors_walk that pins
    the caller's full flat while iteration state shrinks.

Every recursor gen call site (build_minor_at_depth, build_minor_doms,
build_rule_rhs, populate_rules) now threads the full flat alongside
flat_idxs.

Ships pinned FFT cost for Lean.Syntax.rec in the ixvm test suite and
re-pins every stdlib / primitive / prelude cost that shifted from the
codegen refresh. List.rec, Array.rec, Lean.Syntax.rec_1,
Lean.Syntax.rec_2 verified to still pass.

ix name-of: reverse-lookup a Lean.Name from its content address

ix name-of --ixe <path> <hex>: given a 32-byte hex address, scan the
.ixe env's named map and print the fully-qualified Lean.Name of
the const stored at that address. Exits 1 with an error if no named
const matches (unnamed intermediate const or a blob).

Complements ix addr-of (name → address). Primary use: backtrack from
an assertion-failure address logged mid-kernel-execution to the
offending Lean constant.

Test plan

  • lake test -- --ignored ixvm passes end-to-end with the new pins.
  • ix check --interp bytecode Lean.Syntax.rec exits 0.
  • ix check Lean.Syntax.rec (codegen path, after ix codegen) exits 0.
  • ix check --interp bytecode List.rec Array.rec Lean.Syntax.rec_1 Lean.Syntax.rec_2 all exit 0.
  • ix name-of --ixe <ixe> <hex-of-known-named> prints the expected fully-qualified name; unknown address exits 1.

`ix name-of --ixe <path> <hex>`: given a 32-byte hex address,
scan the `.ixe` env's `named` map and print the fully-qualified
Lean.Name of the const stored under that address. Prints an
error + exits 1 if no named const matches (the address might be
an unnamed intermediate constant or a blob).

Complements `ix addr-of` (name → address). Used to backtrack
from an assertion-failure address logged mid-kernel-execution to
the offending Lean constant.
Three interlocking bugs in the Aiur block-flattening / recursor-type
builder caused `ix check --interp bytecode Lean.Syntax.rec` to fail with
`assert_eq mismatch: 0 != 1` on the declared-vs-canonical type equality:

- `build_flat_block` traversed originals once; nested-aux members
  (`Array Syntax`, `List Syntax`) never had their own ctors scanned, so
  `flat` had 2 motives when Lean's recursor declares 3. Replaced with a
  queue-based fixed point mirroring `crates/kernel/src/inductive.rs:
  build_flat_block:531-599`.

- `is_rec_field` classified any ctor field as recursive when its spine
  head Const-idx matched a flat member's ind idx. For `Lean.Syntax.ident`,
  the field `preresolved : List Preresolved` shares the base List const
  idx with the block's `List Lean.Syntax` aux and got a spurious
  `motive_2 preresolved` IH binder. Match key is now (head_idx,
  spine-arg prefix ≡ member.spec_params) — direct members carry
  `spec_params = []` and match on idx alone, auxes require the concrete
  occurrence.

- `build_all_minors` was iterating `flat` and passing the shrinking
  suffix into `build_minor_doms`, so field classification for later
  members was blind to earlier members. Split into a wrapper +
  `build_all_minors_walk` that pins the caller's full flat while the
  iteration state shrinks.

Pin `Lean.Syntax.rec` in the ixvm test suite; rebump every FFT cost
shifted by the codegen refresh (`ix codegen`).
@arthurpaulino arthurpaulino force-pushed the ap/aiur-aux-recursor-parity branch from ad157a6 to 6197f48 Compare July 3, 2026 01:57
@arthurpaulino arthurpaulino marked this pull request as ready for review July 3, 2026 01:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant