opt: fvar reuse optimization #5
Open
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.
This PR adds an optimization to the typechecker implementation to make better use of the
EquivManagerdefinitional equality cache by reusing free variables where possible.As a motivating example, suppose we have defeq terms
TandScontaining free variablex, and we callisDefEqonfun (a : A) (b : B) => T[x := a]andfun (a : A) (b : B) => S[x := a]. This will cache the equality betweenT[x := f1]andS[x := f2], wheref1andf2are new free variables generated upon entering the lambda binders foraandb.However, if we later call
isDefEqonfun (b : B) (a : A) => T[x := a]andfun (b : B) (a : A) => S[x := a], we will check the cache forT[x := f3]andS[x := f4], using the newly generated fvarsf3andf4, resulting in a miss. Ideally, we would want to have reusedf1andf2here so that we could take advantage of the cached knowledge thatT[x := f1]andS[x := f2]are defeq.When entering into a forall or lambda binder of domain type
D, it should be sound to reuse an fvar that was previously generated forDin a different context (as long asDhas not already been bound in the current context). Any fvars appearing inDwould also have to be reused fvars that were generated for previously seen domain types, and so on for the fvars in their types.I've implemented this by replacing the
NameGeneratorin the typechecker state with a simple counter, and using a hashmap from domain type expressions to previously generated fvar names that is checked whenever a new fvar name needs to be generated upon entering a lambda or forall binder. With this optimization, Mathlib typechecks about 20% faster when Lean4Lean is run sequentially.