-
Notifications
You must be signed in to change notification settings - Fork 731
fix: more robust match equation generation #11512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This PR adds a realizable `.else_eq` theorems for sparse casesOn constructions, for rewriting the else case. This code was complicated by having to work around the kernel reduction issues in #11181 around `Nat.xor` etc.
…chim/issue11342
This PR makes `Match.MatchEqs` a leaf module, to be less restricted in which features we can use there.
…chim/match-eqs-leaf
…lean4 into joachim/issue11342
…achim/issue11342
|
Just a note to future myself: The next issue is that during This requires a bit of refactoring, and in particular |
This PR makes `simpH`, used in the match equation generator, produce a proof term. This is in preparation for a bigger refactoring.
…achim/issue11342
…achim/simpH-proof
|
!radar |
|
Benchmark results for 6c0bbc8 against 95a7c76 are in! @nomeata Major changes (3)
Minor changes (1)
|
This PR performs a large refactoring to how match equations are generated, to fix issues like #11342 (which would arise more frequently once we have #11105).
When proving a matcher equation, we previously could encounter
casesOnthat do not reduce right away (it is not applied to a constructor), and that we thus want to split. But splitting can be blocked when the scrutinee is not a free variable, which can be the case when this target is also the index of a later target, see #11342.A more robust approach is to first prove the “congruence equation” from #8284, where the arguments to the matcher are free variables, and the information that these arguments are actually equal to the current pattern is put into hypotheses. In this form, we should be able to reliably split the match into all its branches, avoiding the issue above. At each branch there are three possibilities:
We are in the right branch. We may need to substitute some variable and apply injection to the assumed assumption to unify the goal, and then are done. This can be handled by a (restrictively configured) call to
grind, now thatgrindhandles heterogeneous equality between constructors better (feat: heterogeneous contructor injectivity ingrind#11491).We are in a wrong branch and the patterns do not unify. Then we should have a (possibly heterogeneous) equality between different constructors somewhere in the context, and
grindcan handle it.We are in a wrong branch and it’s overlapping the one we care about. Then there should be a no-overlap assumption in the context, and we need to use that. The code for that exists in
contradiction { genDiseq := true }.This could be made more surgical if instead of using
contradictionwe use some bookkeeping or makers for the overlap assumptions to know which one to belongs to which arm, and use it directly.This is a more expensive approach than the current one, which can avoid many case splits. However it only affects equations that are not by
rflanyways, so the common case is unaffected. Therefore I decided the performance hit in the rarer overlapping is worth the uniformity and the robustness in the code (as opposed to, say, keeping the old code around).It should be possible to (later, when needed) regain some of the performance loss by, before splitting, search the context for equalities between the scrutinee and a constructor, and use the per-constructor elimination form to avoid the unreachable branches directly.
To avoid bootstrapping problems, when compiling core
grindis not used, but instead a naive eager injectivity-applying tactic similar tosolveOverlapis used. This is neither fast nor complete, but good enough for Core (where there are no larger matches and no tricky dependencies). The flagbootstrap.grindInMatchEqnscan be used to trigger this.The flag
debug.Meta.Match.MatchEqs.unrestrictedGrindswitchesgrindto the default configuration. This can be used to test if the restricted configuration is the reason for a failing match compliation.Fixes #11342.