[metatheory] Proof of soundness of defunctionalization and FO-to-SMT semantic preservation - #1
Open
AD1024 wants to merge 32 commits into
Open
[metatheory] Proof of soundness of defunctionalization and FO-to-SMT semantic preservation#1AD1024 wants to merge 32 commits into
AD1024 wants to merge 32 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds a mechanized soundness argument for the supported part of Crush's
lowering pipeline and connects that argument to the SMT commands retained by the
translator.
The formalized path is:
The central proof is by countermodel construction. Given a model of the
higher-order source theory, the development constructs:
introduced by defunctionalization;
guarded source-type representations; and
The final theorem,
VCG.CommandEquiv.unsat_source_script, therefore establishes:Equivalently, the supported lowering path preserves satisfiability.
Main proof components
Intrinsically typed higher-order and first-order languages
The source language contains Booleans, opaque base types, nondependent function
types, lambda expressions, application, equality, Boolean connectives, and
quantifiers. Its terms are indexed by their context and result type.
The first-order target also uses intrinsically typed terms. Function-like
symbols carry a complete argument telescope and are always fully applied.
Ill-typed terms cannot be constructed in either language.
Custom datatypes appear as named base types at these two layers. Their
constructors, selectors, testers, and model laws are recorded separately.
Higher-order functions may consume or return datatype values. Datatype fields
in the supported declaration fragment contain first-order data; function-valued
fields such as
Tree (α -> α)are outside that fragment.Defunctionalization
The lowering from higher-order to first-order terms:
The principal results are:
Flattened.translate_denote: a translated term has the same denotation asits higher-order source term in the constructed model;
Flattened.generatedFormulas_valid: all generated closure and extensionalityformulas hold in that model; and
Flattened.model_extension_theory: one constructed first-order modelsatisfies the translation of the complete finite source theory.
The aggregate theorem uses one shared signature and one model for every source
fact, including all generated formulas.
Monomorphic custom datatypes
The datatype development covers finite groups of mutually recursive,
monomorphic datatype declarations. A block must be structurally well formed and
productive, so every datatype has a finite constructor value.
For admitted datatype declarations, the SMT semantics requires:
The development constructs a canonical datatype model and proves that it
satisfies these laws. This construction establishes that the datatype command
semantics is inhabited for every supported productive declaration block.
At the source boundary,
Datatype.Env.IsFreeDatatypeModelstates that customdatatypes have their constructor-generated tree interpretation. This is the
source-model assumption used by the final theorem. Declaration well-formedness
checks syntax and productivity; the free-datatype property constrains a
particular source model.
SMT terms, commands, and interpreted theories
The SMT syntax used by the translator is untyped, so the metatheory gives it a
relational semantics and pairs it with a declaration-aware type checker.
The semantic fragment covers:
not, implication, conjunction, and disjunction;let, universal quantification, and existential quantification;>=;declare-fun;define-fun;define-funs-rec;declare-datatypes;define-funanddefine-funs-rechave explicit graph-equation semantics throughFunDef.Holds. A declared sort is interpreted by the model's nonempty carrierfor every SMT sort. Unsupported theory operators and higher-order SMT terms are
rejected by
modeledScriptWellTyped.Static and semantic conditions are kept separate:
CommandsInFragmentrecords semantic side conditions, including datatypeproductivity;
CommandsWellTypedrecords successful declaration-aware checking; andModel.SatisfiesCommandsstates the mathematical obligations imposed by thecommands.
This separation prevents malformed or unsupported syntax from establishing
unsatisfiability through an empty satisfaction clause.
The external semantic premise is
CommandsUnsat. It quantifies over modelswhose Boolean carrier has exactly two values, whose application graph is
functional, and whose integers have their standard interpretation whenever the
command array uses integer syntax. Boolean-only scripts therefore require no
unrelated integer carrier.
standardModel_existssupplies a concrete globalstandard model, ruling out an empty model class.
RawCommandsUnsatremains available for component theorems that quantify overall relational models. The final translator theorem uses
CommandsUnsat.FO-to-SMT representation
SMT.Encodingassigns concrete SMT sorts and identifiers to typed first-ordersorts and symbols. It records injectivity and freshness of those assignments.
Built-in sorts such as
Intare used directly and are never redeclared withdeclare-sort.SMT.TheoryReprandSMT.GuardedTheoryReprstate that a concrete command arraycontains exactly the commands generated from a typed first-order theory. The
semantic comparison ignores order and repeated occurrences because command
satisfaction is membership-based. The order-sensitive checker separately
enforces declaration-before-use and scope.
SMT.representation_soundconstructs one raw SMT model satisfying ordinarysort declarations, symbol declarations, datatype declarations, and assertions.
The model-extension infrastructure proves that fresh interpreted or generated
symbols preserve the denotation of previously encoded terms.
Guarded representations
A source type may be represented by an existing target type together with a
predicate selecting valid encodings. The code calls this a
SubsetRepr.The main example represents
NatbyIntwith the predicate0 <= x.Quantifiers are restricted to values satisfying the corresponding predicate.
For custom datatypes, generated recursive
wf_Tdefinitions combine:wf_Tcalls for datatype-valued fields.The development proves that these tester-and-selector formulas characterize
the intended source values and that the emitted recursive definitions have the
required graph semantics.
SMT.guarded_liftthen combines datatype commands,guard definitions, ordinary declarations, and guarded assertions in one model.
GuardDefInterpsupplies one uniform interpretation for every source modelsatisfying the free-datatype condition. Keeping this interpretation outside the
quantified source-model predicate prevents the final theorem from discarding a
source model merely because target-model construction evidence was unavailable.
Connection to the commands emitted by Crush
When datatype certification is enabled, the translator retains:
reason.
FactTranslationis finalized after all facts have been processed, so itslocations refer to the complete emitted command array.
CommandEquiv.build?compares that array with the proof-side encoding of everyreified source fact under the same signature. It performs one semantic
normalization: removal of top-level
:namedassertion attributes. It then:A successful comparison returns
CommandEquivCert. The leadingset-logiccommand returned by
buildScriptis handled by a separate semantic equivalencetheorem, yielding
CommandEquiv.unsat_source_script.Review-driven fixes included in the current branch
The soundness and vacuity reviews led to the following changes:
definitions.
satisfaction.
raw and standard unsatisfiability predicates.
Int, numeric literals, or the modeled integer operator.list-based proof-facing environment and structural command traversal.
native_decide.encoding proofs, a quantified source theory, exact generated commands,
successful
CommandEquiv.build?, a satisfying standard target model, and anapplication of the final reflection theorem.
shared by the checker and semantic predicate.
datatype semantics.
declare-sortcommands.
PL-theoretical names and shortened common concepts under clear namespaces:
Repr,ModelExt,DatatypeRepr,CommandEquiv,CommandEquivCert,FactTranslation,GuardDefEncoding, andGuardDefInterp.Implementation-facing changes
crush.datatype.certify, defaulting tofalse, for the path thatretains proof-facing datatype and command information.
cannot silently drift from the names used to construct it.
have been emitted.
@[crush_certified_def]unfolds the annotated Lean definition;@[crush_certified_lower]selects a fixed primitive mapping with a semanticcertificate.
@[crush_translate_head]dispatches on an application head;@[crush_translate_family]dispatches on the result-type family.Scope and assumptions
semantic correctness theorem for conversion from arbitrary
Lean.Exprvaluesinto the HO language remains a separate boundary.
CommandsUnsatis a semantic no-model premise. Solver execution, proofreplay, and UNSAT-core-guided reconstruction establish trust in a concrete
solver result through separate mechanisms.
numerals, and integer
>=. Arithmetic such as addition and multiplication,bit-vectors, strings, and arrays require corresponding semantic modules before
entering this theorem.
first-order. Dependent or indexed families, proof-valued fields,
function-valued fields, unsafe cross-block recursion, quotient primitives,
and unsupported recursors remain outside the reified datatype fragment.
applies after the required representations, uniform guard interpretation,
reified theory, and
CommandEquivCerthave been constructed.TranslateState.statusreports whether a run used a marked trusted path. Thefinal soundness theorem consumes the dependent proof objects listed above.
The translator retains collision-free allocation evidence used to construct
and audit that encoding.
Reviewer guide
1. Start from the final theorem
Read:
Crush/Metatheory/VCG/CommandEquiv.leanCrush/Metatheory/VCG/Datatype.leanFocus on:
CommandEquivCert;CommandEquiv.build?;CommandEquiv.unsat_source;CommandEquiv.unsat_source_script;FactTranslation.DatatypeRepr.sound; andFactTranslation.DatatypeRepr.theory_unsat.Check that every bridge from a reified theory to the complete emitted command
array appears as an explicit premise or checked certificate.
2. Review defunctionalization
Suggested order:
Defunctionalization/Collect.leanDefunctionalization/Flattened/Spine.leanDefunctionalization/Flattened/Lambda.leanDefunctionalization/Flattened/Translate.leanDefunctionalization/Flattened/Denotation.leanDefunctionalization/Flattened/Theory.leanCheck captured-variable order, complete application spines, closure equations,
function extensionality, and inclusion of every generated formula in the
aggregate target theory.
3. Review datatype semantics and non-vacuity
Suggested order:
Datatype/Core.leanDatatype/Semantics.leanDatatype/Model.leanDatatype/Flattened.leanSMT/Datatype.leanSMT/DatatypeCanonical.leanSMT/DatatypeTransport.leanSMT/DatatypeRepr.leanCheck that the semantic datatype laws match SMT-LIB, that productivity is
required, and that the canonical construction supplies a model for every
admitted declaration block.
4. Review raw SMT semantics and checking
Read:
Crush/SMT/Check.leanCrush/Metatheory/SMT/Semantics.leanCrush/Metatheory/SMT/Repr.leanCrush/Metatheory/SMT/Model.leanCrush/Metatheory/SMT/ModelExt.leanCrush/Metatheory/SMT/Soundness.leanCrush/Metatheory/SMT/Int.leanCheck:
stated semantics;
CommandsInFragmentandCommandsWellTypedprevent vacuous use of commandsatisfaction;
StandardForrequests integer laws exactly when the commands use integers;and
validity.
5. Review guarded representations
Read:
FO/Guarded.leanDatatype/Guarded.leanGuarded/Encoding.leanSMT/Guarded.leanSMT/GuardedSoundness.leanSMT/DatatypeGuard.leanSMT/DatatypeGuarded.leanCheck universal and existential guard placement, recursive datatype guard
definitions, and the uniformity of
GuardDefInterpover source models.6. Review the implementation connection
Read:
Reification/Witness.leanVCG/Generate.leanVCG/Datatype.leanVCG/CommandEquiv.leanTranslation/Monad.leanTranslation/Translate.leanFrontend/Tactic.leanCheck that command locations refer to the final array, allocated names remain
linked to their commands, assertion-name normalization is the only erased
syntax, and both the emitted and annotation-normalized arrays pass the modeled
checker.
7. Review executable regressions
Read:
Test/Metatheory.leanTest/MetatheoryDatatype.leanTest/SMTCheck.leanTest/Smoke.leanThe two-constant regression near the end of
Test/Metatheory.leanexercisesthe complete command-equivalence and target-model construction path with real
ordinary symbols.
Validation
The following commands pass on the current branch:
The metatheory and its regression tests contain no use of
native_decide.