Skip to content

Define typing relation for commands and prove soundness of typechecker#1335

Draft
joscoh wants to merge 33 commits into
main2from
josh/cmd-type-spec
Draft

Define typing relation for commands and prove soundness of typechecker#1335
joscoh wants to merge 33 commits into
main2from
josh/cmd-type-spec

Conversation

@joscoh

@joscoh joscoh commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Gives a type specification for commands (CmdHasType'), generalized over the LExpr typing relation, and instantiates it with LExpr.hasType (CmdHasType) and LExpr.hasTypeA (CmdHasTypeA). Proves that:

  1. If the command typechecker Cmd.typeCheck succeeds, then the original command was well-typed according to CmdHasType (theorem Cmd.typeCheck_sound).
  2. If Cmd.typeCheck succeeds, then the output command is well-annotated according to CmdHasTypeA (theorem Cmd.typeCheck_annotated_sound).

Core command typing (new files under Strata/Languages/Core/)

  • CmdTypeSpec.lean — the inductive CmdHasType', parameterized over an
    ExprTypingSpec typeclass with two instances: CmdHasType (polymorphic
    HasType, over LTy) and CmdHasTypeA (annotated HasTypeA, over
    LMonoTy).
  • CmdTypeSpecProps.lean — the two top-level soundness theorems,
    Cmd.typeCheck_sound and Cmd.typeCheck_annotated_sound, showing
    Cmd.typeCheck produces commands satisfying the spec.
  • CmdTypeProps.lean — supporting lemmas about preprocess / inferType
    / unifyTypes and context updates that feed the soundness proofs.
  • CmdType.inferType — no longer auto-registers undeclared free variables
    via addInOldestContext. Expressions in init/set/assert/assume/cover
    that reference variables not already in scope are now rejected by freeVarCheck.
    Previously, undeclared variables were silently added, which is not longer needed
    with nondeterministic init.

Rigid type variables (fixes #1345)

  • CmdType.checkAnnotCompat — new checker pass that rejects any unification
    result refining a rigid (skolemized) type variable.
  • ProcedureType.leansetupInputEnv now generates fresh rigid vars for
    type parameters and records them in C.rigidTypeVars; body typechecking
    enforces identity on these vars via checkAnnotCompat.
  • CmdTypeSpec.lean — the init_det/init_nondet constructors use
    RigidAnnotCompat (AnnotCompat restricted to be identity on rigid vars).
  • CmdTypeSpecProps.leanCmd.typeCheck_preserves_rigid_inv proves the
    invariant is preserved; typeCheck_sound uses it.
  • RigidTypeVarsTests.lean — test cases for polymorphic procedures with
    rigid type parameters, including expected-failure cases.

Lambda layer

  • LExprResolveProps.lean (renamed from LExprResolveAnnotated.lean) adds theorem resolve_eqModuloAnnotations (resolution preserves
    expression structure, changing only metadata and annotations).
  • LExprTypeSpec.lean — adds freshness / TEnvWF / well-scoped supporting
    lemmas used by the resolve and command proofs. The HasType relation itself
    is unchanged.
  • LExprTypeEnv.lean — adds TContext.subst and TEnv lemmas
    (substitution lookup, addInNewestContext, free-variable scoping) used by the
    command proofs.
  • Smaller supporting changes in LExprWF.lean and LTyUnify.lean.

Tooling

  • Strata/Util/Tactics.lean — now contains the elim_err / elim_errs tactics for
    discharging error branches when unfolding Except-valued checker code, used
    throughout the soundness proofs.

@github-actions github-actions Bot added the Core label Jun 5, 2026
Base automatically changed from josh/resolve-ind to main2 June 5, 2026 22:24
Josh Cohen added 5 commits June 8, 2026 10:28
Unification too permissive: now split into rigid type variables
that cannot be unified, and free type variables which can
Involves changes to typechecker, spec, and proofs
Added test cases for various edge cases
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant