Replace the ATF result cache with evaluation from instance equations#12
Open
nanavati wants to merge 3 commits into
Open
Replace the ATF result cache with evaluation from instance equations#12nanavati wants to merge 3 commits into
nanavati wants to merge 3 commits into
Conversation
Replace the elaboration-side consumers of the ATF result cache with ATFRules, a pure ground evaluator over the instance declarations already in the symbol table. A fully applied ATF application at ground arguments is reduced by committing to the unique most-specific instance whose head matches (for a coherent class, exactly the instance that reducePred's most-specific-first candidate walk commits to) and running the instance context's fundeps at ground types to bind the variables the result mentions. Applications over type variables stay dormant, as before: their reduction is scope-dependent and is the typechecker's judgment, consumed before ISyntax exists. fullTypeNormalizer loses its cache-hit path and its typechecker fallback in one move: the old miss path was iConvT -> expandSynN, a full runTI per query -- the constraint solver invoked from the middle of elaboration -- and the cache existed to keep that rare. Reduction is now a pure function of the symbol table, so iExpand builds the rules from the symtab it already has, the IATFCache parameter threading disappears from iExpand/genModule/runG, the cache growth during elaboration (cExprToIExpr's mergeATFCache) is deleted, and a ground application that does not reduce is an internal error naming the application, never an occasion to consult the solver. ISyntaxCheck's tCheck builds rules from its symtab the same way. This is behavior-preserving: the cache was consulted only under canNorm (ground keys), so the polymorphic captures recorded by the typechecker were never readable by the normalizer, and normTFun internal-errored on anything the symtab could not reduce -- the same contract the evaluator now enforces directly. The cache is still produced and serialized; a follow-up removes the production pipeline. -trace-atf-cache[-miss] is replaced by -trace-atf-rules, and the cache's pin tests become rules pin tests: ATFCacheHit / ATFPolyCacheMiss collapse into ATFElabReduce (with the cache gone the recorded/unrecorded distinction no longer exists), and ATFCacheHitDef/Use become ATFElabImportDef/Use, pinning that elaboration reduces a family defined entirely in an imported package. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A6uLp1FBmGTXMVRjWc9byU
With the evaluator reducing ground ATF applications directly from the instance equations, the cache pipeline no longer has a consumer. Remove it end to end: * recordATFResult / sat's recordATFs -- the typechecker no longer captures the ATF projections of coherent discharges. The captured results were point observations of the instance equations, keyed by whatever the argument types were at discharge time; open-keyed entries (polymorphic and rigid-variable discharges) were never readable by the ground-keyed consumers, and ground entries are now re-derivable on demand. The record-or-not distinction for incoherent matches goes with it: nothing is recorded at all. * CATFCache / tiATFCache -- typecheck and context reduction return only their results; cTypeCheck and cCtxReduceIO shrink. * IATFCache / ipkg_atf_cache -- the IPackage field, its conversion in iConvPackage, its serialization in GenBin, and the "own entries only" bookkeeping in fixupDefs are gone. A .bo carries declarations and code, never memoized inferences: its instance declarations are the rules, and any consumer can re-derive every reduction from them. Existing .bo files are invalidated by the version hash, as with any format change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A6uLp1FBmGTXMVRjWc9byU
iConvT ran expandSynN -- a full typechecker instantiation -- on every converted type, whether or not any type function appeared in it. Conversion is now pure: expandSyn for synonyms and primitive type functions, then atfReduceInType for ATF applications, which reduces the ground ones from the instance equations and leaves everything else (including partially applied ATF constructors) untouched. The typechecker round trip survives on one path only: a type that still carries a fully applied ATF application over type variables, where expandSynN's scope-relative reduction (bound type variables as rigid atoms) may apply. Types reaching conversion have already been normalized by typechecking, so this fallback is believed unreachable; it is kept until that is enforced with an assertion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A6uLp1FBmGTXMVRjWc9byU
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.
Staged here for the upstream PR to B-Lang-org/bsc (the integration cannot open PRs there; open it from B-Lang-org/bsc@main...nanavati:bsc:claude/itype-rnf-type-var-cache-sddtz9).
Summary
This PR replaces the ATF result cache with direct evaluation from the instance declarations — the rewrite rules the cache was memoizing all along. The cache captured point observations of instance equations at whatever types the typechecker happened to discharge them, serialized them into
.bofiles, and unioned them across the import closure at elaboration; a miss fell back toexpandSynN, a fullrunTI(the constraint solver) invoked from the middle of elaboration. After this PR, a fully applied ATF application at ground arguments is reduced by a pure evaluator (ATFRules) over the instance equations in the symbol table, and nothing is captured, merged, or serialized.The deeper invariant this enforces: permanent construction (IConv / ISimplify / IExpand) never consults the typechecker. Reduction at ground types is evaluation — matching is decisive, instance contexts resolve recursively at ground types, no judgment is involved — so the constraint solver's machinery (fresh variables, unification, improvement, deferral, incoherence decisions) is not needed and not reachable from the evaluator. Applications over type variables stay dormant in ISyntax exactly as before: whether and how they reduce is scope-dependent (rigid variables act as atoms) and remains the typechecker's business, settled before ISyntax exists.
Commits
Evaluate type functions from instance equations, not the ATF cache — adds
src/comp/ATFRules.hsand rewires the consumers.fullTypeNormalizerreduces armed (ground) applications via the evaluator; a ground application that does not reduce is an internal error naming the application, never a solver call. TheIATFCacheparameter threading disappears fromiExpand/genModule/runG(rules are a pure view of the symtab each phase already holds), and elaboration-time cache growth (cExprToIExpr'smergeATFCache) is deleted. The cache's pin tests become rules pin tests (ATFElabReduce,ATFElabImportDef/Use).Retire the ATF cache — removes the production pipeline end to end:
recordATFResult/sat'srecordATFs,CATFCache/tiATFCache, theipkg_atf_cachefield, its conversion iniConvPackage, and its serialization inGenBin. A.bonow carries declarations and code, never memoized inferences; every consumer can re-derive every reduction from the instance declarations it already reads.IConv: reduce ground ATFs from instance equations, not via
runTI—iConvTranexpandSynN(a typechecker instantiation) on every converted type. Conversion is now pure (expandSyn+atfReduceInType); the typechecker round trip survives only for a type still carrying a variable-dependent ATF application, which normalized typechecker output should never produce (kept until enforced by an assertion).Why the evaluator commits to the same instances the typechecker does
reducePredwalks candidates most-specific-first and commits at the first match. On ground arguments, matching is plain structural pattern matching — no substitution into the argument can change which equations match — so "first match in most-specific-first order" is exactly "the unique most-specific matching instance", which is what the evaluator computes directly (with a pairwise generalization test). For a coherent class the overlap check has already guaranteed that any two instances matching the same ground type are comparable; if the evaluator ever finds an ambiguous ground match, that is an unsealed / incoherent family leaking into permanent construction, and it fails loudly rather than guessing.Instance contexts are consulted only to bind variables the result mentions, by running their fundeps recursively at ground types (e.g.
TupleSize'-style helper classes, or aBits a sacontext whosesaappears in the result). Dictionary satisfiability was the typechecker's obligation at the original use site and is not re-verified — the same stance the old cache-hit path took.Behavior preservation
canNorm(ground keys), so the polymorphic/open-keyed entries recorded by the typechecker were never readable by any consumer — deleting the capture loses nothing that was reachable.normTFunalreadyinternalErrored on any ground application the symbol table could not reduce; the evaluator enforces the same contract directly, with a better message.sat) becomes moot: nothing is recorded at all.-trace-atf-rulesand a check that no ATF application survives into the expanded module) and reduction of a family defined entirely in an imported package.bsc.lib/Prelude(79 tests, includingTupleSize) andbsc.binarypass..boformat; existing.bofiles are invalidated by the version hash as with any format change.Performance notes
runTIper converted type (every type in every package went throughexpandSynN).runTIper cache miss; an armed reduction costs a walk of the family's (small) instance equations..bofiles shrink by their cache section.Known restrictions / follow-ups
PrimTypeOf'siToCT/iConvTround trip in IExpand (for synonym-expansion-implemented operators likeSizeOf) is orthogonal to the ATF cache and unchanged.iConvT'sexpandSynNfallback for dormant applications is believed unreachable and should become an assertion in a follow-up.🤖 Generated with Claude Code
https://claude.ai/code/session_01A6uLp1FBmGTXMVRjWc9byU
Generated by Claude Code