Skip to content

loon run: abort on checker errors; fix the checker gaps that blocked it#83

Merged
ecto merged 1 commit into
mainfrom
claude/sad-torvalds-5a6d5f
Jul 7, 2026
Merged

loon run: abort on checker errors; fix the checker gaps that blocked it#83
ecto merged 1 commit into
mainfrom
claude/sad-torvalds-5a6d5f

Conversation

@ecto

@ecto ecto commented Jul 7, 2026

Copy link
Copy Markdown
Owner

What

loon run (and --wasm/--native) now runs the checker before execution and hard-aborts on errors, rendering diagnostics exactly like loon check (codespan, to stderr, exit 1). Warnings (W-codes, E0209) print but don't block. Previously the checker ran inside the run path but its diagnostics were discarded (let _errors = checker.check_program(...)), so broken programs silently printed ().

Why

Priority #1 from the agent-first audit: docs/agent-first.md declares silent wrong behavior the worst failure mode. This converts a whole class of silent () results into teaching diagnostics — e.g. a typo'd builtin now exits non-zero with E0201 unbound symbol instead of printing ().

The catch — and the bulk of the diff

Hard-abort wasn't landable as-is: 14/35 conformance programs and 6/19 samples failed the checker while running correctly. The checker had to learn the language it was rejecting:

  • when / loop / recur / test forms — previously unbound symbols; recur targets tracked through loops, named fns, lambdas, and clauses
  • Multi-arity fn — clauses were unified into one type (and infer_fn_clause returned only the body type, so the fn's name got a non-function type); now per-clause schemes with arity dispatch at call sites, mirroring the VM
  • Order-flexible collection builtins — the VM detects the collection by type for map/filter/each/fold/reduce/join, accepting both [map coll fn] and pipe-style [map fn coll]; the checker now mirrors that
  • Record ~ Map unification — record literals are keyword-keyed maps at runtime, so merge/assoc/update accept them; map keys generalized from hardcoded Keyword to polymorphic k (string-keyed maps type-check)
  • Compiler-generated ifs are unions — the and/or desugar produces [if g g x]; unifying branches wrongly constrained pipe lambda params
  • Variadic println/print, generic index-of, lenient get on records (absent key yields falsy (), per the prior-alignment corpus; dot-access stays strict)
  • Dimensions: sig param types pre-apply to fn bodies so dimensional arithmetic checks inside functions; dim names resolve in sigs; Dim is Copy in the ownership check; persistent-collection builtins count as borrows; codegen skips sig

Where the checker was right, the programs are fixed instead

  • samples/physics.oo had a real physics bug: bending stress computed as M/span² (N/m — not comparable to Pa). Now M/span³ with a sig annotation. The dimension checker was correctly rejecting it.
  • samples/bench-collections.oo reused v1 after moving it — reordered.
  • conformance/effects-handlers.oo performed a 1-arg effect op with 0 args — now [E.op 0], same output.

Verification

  • cargo test --workspace: all 25 suites green (conformance, differential, prior-alignment, record/replay included)
  • Every conformance + prior-alignment program and every sample checks clean (E0209 warnings only) and runs with identical output
  • Repro: [println [reduc ...]] exits 1 with the E0201 diagnostic on stderr

Known pre-existing (not a regression, verified against the pre-change binary): web/src/*.loon fail standalone loon check on cross-module use resolution.

🤖 Generated with Claude Code

The type checker already ran inside `loon run` but its diagnostics were
silently discarded, so broken programs printed () instead of teaching
diagnostics (agent-first P1: silent-wrong is the worst failure mode).
`loon run`, `--wasm`, and `--native` now precheck like `loon check`:
errors render to stderr and exit 1; warnings print but don't block.

Landing that required teaching the checker the language it was
rejecting — 14/35 conformance programs and 6/19 samples failed the
checker while running correctly:

- when/loop/recur/test special forms (recur targets tracked through
  loops, named fns, lambdas, and multi-arity clauses)
- multi-arity fn: per-clause schemes with arity dispatch at call sites
  (clauses were unified into one type; infer_fn_clause returned only
  the body type, so a multi-arity fn's name got a non-function type)
- order-flexible collection builtins (map/filter/each/fold/reduce/join
  detect the collection by type at runtime; the checker now mirrors it)
- Record ~ Map unification (record literals are keyword-keyed maps at
  runtime) and polymorphic map keys for get/assoc/update/merge/remove
- compiler-generated ifs (and/or desugar) are unions: don't unify
  branches, which wrongly constrained pipe lambda params
- variadic println/print, generic index-of (vectors too), lenient get
  on records (absent key is falsy (), per prior-alignment corpus)
- sig dimension types pre-apply to fn params so dimensional arithmetic
  checks inside function bodies; dim names resolve in sigs; Dim is
  Copy in the ownership check; persistent-collection builtins are
  borrows, not moves; codegen skips sig

Where the checker was right, the programs are fixed instead:
- samples/physics.oo computed bending stress as M/span² (N/m, not
  comparable to Pa) — now M/span³ with a sig annotation
- samples/bench-collections.oo reused v1 after moving it
- conformance/effects-handlers.oo performed a 1-arg effect op with 0
  args

cargo test --workspace: all 25 suites green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
loon Ready Ready Preview, Comment Jul 7, 2026 1:51pm

Request Review

@ecto ecto merged commit 0d16dc5 into main Jul 7, 2026
6 checks passed
@chojiai

chojiai Bot commented Jul 7, 2026

Copy link
Copy Markdown

What shipped

Running a program that contained errors no longer silently prints a blank result. Before this change, broken programs would run anyway and output nothing useful; now, when errors are detected, the tool stops immediately and shows the same clear diagnostics you would see from an explicit check command. Warnings are still shown but do not block execution.


Plain-English summary generated by Choji from this pull request.

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