This PR simplifies the `grind` canonicalizer by removing dead state and unnecessary complexity, and fixes two bugs discovered during the cleanup. ## Changes **Canonicalizer cleanup:** - Remove dead `Canon.State.canon` field — values were inserted but never read. The canonicalizer uses a transient `HashMap` local to each `canonImpl` invocation. - Remove `proofCanon` — it deduplicated `Grind.nestedProof` terms by mapping canonicalized propositions to a single representative, but different proofs may reference different hypotheses, making the result context-dependent and preventing cache sharing across goals. - Remove `isDefEqBounded` — a fallback that retried `isDefEq` at default transparency with a heartbeat budget. The one test that depended on it was actually masking a transparency bug in `propagateCtorHomo`. **Bug fixes:** - Use `withDefault` for `mkAppOptM` in `propagateCtorHomo` (`Ctor.lean`) — the injectivity proof construction needs default transparency to unify implicit arguments of indexed inductive types like `Vector`. - Add `Grind.abstractFn` gadget to protect lambda abstractions created by `abstractGroundMismatches?` from beta reduction during preprocessing. Without this, `Core.betaReduce` in `preprocessLight` collapses `(fun x => body) arg` back to `body[arg/x]`, undoing the abstraction that congruence closure needs. **Eta reduction infrastructure:** - Lower `etaReduceAll` from `MetaM` to `CoreM` — it only performs structural operations, no `MetaM` needed. - Add `etaReduceWithCache` that takes and returns an explicit `HashMap` cache, enabling callers to thread a single cache across multiple expressions. The net effect on `Canon.State` is removing 3 fields (`canon`, `proofCanon`) and the `isDefEqBounded` function, along with the `useIsDefEqBounded` and `parent` parameters from `canonElemCore`. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
124 lines
4.1 KiB
Text
124 lines
4.1 KiB
Text
#grind_lint mute Array.getElem_swap
|
|
|
|
/--
|
|
error: `Array.swap_swap` is not marked with the `@[grind]` attribute for theorem instantiation
|
|
-/
|
|
#guard_msgs in
|
|
#grind_lint mute Array.swap_swap
|
|
|
|
/-- error: `Array.getElem_swap` is already in the `#grind_lint` mute set -/
|
|
#guard_msgs in
|
|
#grind_lint mute Array.getElem_swap
|
|
|
|
#grind_lint skip Array.getElem_swap
|
|
|
|
/--
|
|
error: `Array.swap_swap` is not marked with the `@[grind]` attribute for theorem instantiation
|
|
-/
|
|
#guard_msgs in
|
|
#grind_lint skip Array.swap_swap
|
|
|
|
/-- error: `Array.getElem_swap` is already in the `#grind_lint` skip set -/
|
|
#guard_msgs in
|
|
#grind_lint skip Array.getElem_swap
|
|
|
|
/--
|
|
info: instantiating `Array.range_succ` triggers 19 additional `grind` theorem instantiations
|
|
---
|
|
info: Try this to display the actual theorem instances:
|
|
[apply] set_option trace.grind.ematch.instance true in
|
|
#grind_lint inspect Array.range_succ
|
|
-/
|
|
#guard_msgs in
|
|
#grind_lint inspect Array.range_succ
|
|
|
|
#grind_lint inspect (min := 100) Array.range_succ
|
|
|
|
#grind_lint mute Array.append_assoc -- It is not used during E-matching by `#grind_lint check` and `#grind_lint inspect`
|
|
|
|
/--
|
|
info: instantiating `Array.range_succ` triggers 19 additional `grind` theorem instantiations
|
|
---
|
|
info: Try this to display the actual theorem instances:
|
|
[apply] set_option trace.grind.ematch.instance true in
|
|
#grind_lint inspect Array.range_succ
|
|
-/
|
|
#guard_msgs in
|
|
#grind_lint inspect Array.range_succ
|
|
|
|
/--
|
|
info: instantiating `Array.range_succ` triggers 19 additional `grind` theorem instantiations
|
|
---
|
|
info: instantiating `Array.range'_succ` triggers 14 additional `grind` theorem instantiations
|
|
---
|
|
info: Try this to display the actual theorem instances:
|
|
[apply] set_option trace.grind.ematch.instance true in
|
|
#grind_lint inspect Array.range_succ Array.range'_succ
|
|
-/
|
|
#guard_msgs in
|
|
#grind_lint inspect Array.range_succ Array.range'_succ
|
|
|
|
-- These go slightly over 20, but seem reasonable.
|
|
#grind_lint skip Array.back_singleton
|
|
#grind_lint skip Array.count_singleton
|
|
#grind_lint skip Array.foldl_empty
|
|
#grind_lint skip Array.foldr_empty
|
|
#grind_lint skip Array.getElem_zero_filter
|
|
#grind_lint skip Array.getElem_zero_filterMap
|
|
|
|
#guard_msgs in
|
|
#grind_lint check (min := 20) in Array
|
|
|
|
#guard_msgs in
|
|
#grind_lint inspect Array.filterMap_some
|
|
|
|
#guard_msgs in
|
|
#grind_lint check (min := 20) in module Init.Data.Array
|
|
|
|
/-! Test suffix skipping -/
|
|
|
|
#grind_lint skip suffix succ
|
|
|
|
/-- error: `succ` is already in the `#grind_lint` skip suffix set -/
|
|
#guard_msgs in
|
|
#grind_lint skip suffix succ
|
|
|
|
-- First, let's verify individual theorems ending in succ would normally trigger warnings
|
|
-- This should show that Array.range_succ triggers instantiations
|
|
/--
|
|
info: instantiating `Array.range_succ` triggers 19 additional `grind` theorem instantiations
|
|
---
|
|
info: Try this to display the actual theorem instances:
|
|
[apply] set_option trace.grind.ematch.instance true in
|
|
#grind_lint inspect Array.range_succ
|
|
-/
|
|
#guard_msgs in
|
|
#grind_lint inspect Array.range_succ
|
|
|
|
-- Now verify that theorems ending in `succ` are skipped in check
|
|
-- Note: The suffix skip should apply during check, but inspect bypasses it
|
|
-- Array.range_succ and Array.range'_succ should NOT appear in the output
|
|
/--
|
|
info: instantiating `Array.back?_empty` triggers 17 additional `grind` theorem instantiations
|
|
---
|
|
info: instantiating `Array.count_empty` triggers 19 additional `grind` theorem instantiations
|
|
---
|
|
info: instantiating `Array.findIdx_empty` triggers 20 additional `grind` theorem instantiations
|
|
---
|
|
info: instantiating `Array.findIdx_singleton` triggers 16 additional `grind` theorem instantiations
|
|
---
|
|
info: instantiating `Array.getElem_attachWith` triggers 16 additional `grind` theorem instantiations
|
|
---
|
|
info: instantiating `Array.getElem_eraseIdx` triggers 17 additional `grind` theorem instantiations
|
|
---
|
|
info: Try this:
|
|
[apply] #grind_lint check (min := 15) in Array
|
|
#grind_lint inspect Array.back?_empty
|
|
#grind_lint inspect Array.count_empty
|
|
#grind_lint inspect Array.findIdx_empty
|
|
#grind_lint inspect Array.findIdx_singleton
|
|
#grind_lint inspect Array.getElem_attachWith
|
|
#grind_lint inspect Array.getElem_eraseIdx
|
|
-/
|
|
#guard_msgs in
|
|
#grind_lint check (min := 15) in Array
|