-
Notifications
You must be signed in to change notification settings - Fork 449
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
feat: decide!
tactic for using kernel reduction
#5665
Conversation
Mathlib CI status (docs):
|
if kernelOnly then | ||
-- Reduce the decidable instance to (hopefully!) `isTrue` by passing `pf` to the kernel. | ||
-- The `mkAuxLemma` function caches the result in two ways: | ||
-- 1. First, the function makes use of a `type`-indexed cache per module. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this will still work with parallelism. Also is it not a bit strange to have a per module cache, and penalize users for splitting modules?
How is the matcher caching auxiliary definitions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure whether cross-decide!
caching will still be supported with parallelism. I just know that mkAuxLemma
is used by simp
when processing simp lemmas.
The matcher uses its own cache, and the key function is Lean.Meta.Match.mkMatcherAuxDefinition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right, you are basically getting this for free by using mkAuxLemma
? So whatever will happen to that feature of simp
will also happen to decide!
. That’s fine.
src/Lean/Parser/Tactic.lean
Outdated
- Since it uses kernel reduction instead of elaboratior reduction, it ignores transparancy and can unfold everything. | ||
- While `decide` needs to reduce the `Decidable` instance twice (once during elaboration to verify whether the tactic succeeds, | ||
and once during kernel type checking), the `decide!` tactic reduces it exactly once. | ||
- When `decide!` is successful, the result is cached for the current module. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe remove that from the docstring. We don’t want people to relying on that behavior if we don't know if and how that will work post-parallelism.
- When `decide!` is successful, the result is cached for the current module. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. How does leaving the caching test sound, so we know when this finally has broken?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely!
The `decide!` tactic is like `decide`, but when it tries reducing the `Decidable` instance it uses kernel reduction rather than the elaborator's reduction. The kernel ignores transparency, so it can unfold all definitions. Furthermore, by using kernel reduction we can cache the result as an auxiliary lemma — this is more efficient than `decide`, which needs to reduce the instance once in the elaborator to check whether the tactic suceeds, and once again in the kernel during final typechecking. This implements a variant of RFC leanprover#5629, which proposes instead to skip checking altogether during elaboration. With this PR's `decide`, we can use `decide!` as more-or-less a drop-in replacement for `decide`.
Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
The
decide!
tactic is likedecide
, but when it tries reducing theDecidable
instance it uses kernel reduction rather than the elaborator's reduction.The kernel ignores transparency, so it can unfold all definitions (for better or for worse). Furthermore, by using kernel reduction we can cache the result as an auxiliary lemma — this is more efficient than
decide
, which needs to reduce the instance twice: once in the elaborator to check whether the tactic succeeds, and once again in the kernel during final typechecking.While RFC #5629 proposes a
decide!
that skips checking altogether during elaboration, with this PR'sdecide!
we can usedecide!
as more-or-less a drop-in replacement fordecide
, since the tactic will fail if kernel reduction fails.This PR also includes two small fixes:
blameDecideReductionFailure
now useswithIncRecDepth
.Lean.Meta.zetaReduce
now instantiates metavariables while zeta reducing.Some profiling: