This PR fixes an issue where `exact?` would not suggest private declarations defined in the current module. ## Problem When using `exact?` in a file with private declarations, those private declarations were not being suggested even though they are valid and accessible: ```lean module axiom P : Prop private axiom p : P example : P := by exact? -- error: could not find lemma ``` The problem was that `blacklistInsertion` in `LazyDiscrTree` was filtering out all declarations whose names matched `isInternalDetail`, which includes private names due to their `_private.Module.0.name` structure. ## Solution The fix adds a helper function `isPrivateNameOf` that checks if a private declaration belongs to a specific module. The `blacklistInsertion` function now allows private declarations belonging to the current module (`env.header.mainModule`) to pass through the filter. Private declarations from imported modules are still filtered out, as they may reference internal declarations that aren't accessible (which would cause processing errors). Zulip discussion: https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/.60exact.3F.60.20and.20private.20declarations/near/564586152 🤖 Prepared with Claude Code --------- Co-authored-by: Claude <noreply@anthropic.com>
65 lines
2.6 KiB
Text
65 lines
2.6 KiB
Text
/-
|
|
Test that try? runs user suggestion tactics in parallel via attempt_all_par.
|
|
|
|
This test uses IO.stdGenRef (a builtin_initialize ref) to demonstrate parallelism:
|
|
- Tactic 1 (high prio): waits 1000ms, then checks if the random seed was changed
|
|
- Tactic 2 (low prio): immediately sets the seed to a magic value, then succeeds
|
|
|
|
If sequential: Tactic 1 executes first, waits, seed unchanged, fails.
|
|
Then tactic 2 executes, sets seed, succeeds. Only one suggestion.
|
|
If parallel: Both tactics start together. Tactic 2 sets seed immediately.
|
|
Tactic 1 waits 1000ms, sees changed seed, succeeds. Two suggestions.
|
|
-/
|
|
module
|
|
public import Lean
|
|
public meta import Lean.Elab.Tactic.Try
|
|
|
|
open Lean Meta Elab Tactic Try
|
|
|
|
-- An opaque goal that built-in tactics (including solve_by_elim) won't solve.
|
|
-- The axiom name starts with `_` so that `exact?` treats it as an implementation detail and
|
|
-- won't suggest it directly, allowing us to test parallelism of user-defined suggestion generators.
|
|
opaque ParallelTestGoal : Prop
|
|
axiom _parallelTestGoalHolds : ParallelTestGoal
|
|
|
|
-- Magic seed value to signal parallelism
|
|
meta def magicSeed : Nat := 314159265
|
|
|
|
-- Tactic that waits, then checks if seed was changed
|
|
elab "wait_and_check_seed" : tactic => do
|
|
IO.sleep 1000
|
|
let gen ← IO.stdGenRef.get
|
|
let expected := mkStdGen magicSeed
|
|
if gen.s1 == expected.s1 && gen.s2 == expected.s2 then
|
|
evalTactic (← `(tactic| exact _parallelTestGoalHolds))
|
|
else
|
|
throwError "seed not changed (sequential execution detected)"
|
|
|
|
-- Tactic that immediately sets seed and succeeds
|
|
elab "set_seed_and_succeed" : tactic => do
|
|
IO.setRandSeed magicSeed
|
|
evalTactic (← `(tactic| exact _parallelTestGoalHolds))
|
|
|
|
-- Register both tactics as user suggestions
|
|
-- High priority tactic: reset seed first (to ensure clean state), then return waiting tactic
|
|
@[local try_suggestion 900]
|
|
meta def waitAndCheckSolver (_goal : MVarId) (_info : Try.Info) : MetaM (Array (TSyntax `tactic)) := do
|
|
-- Reset to a different seed to ensure we're testing actual communication
|
|
IO.setRandSeed 0
|
|
return #[← `(tactic| wait_and_check_seed)]
|
|
|
|
-- Low priority tactic returns the seed-setting tactic
|
|
@[local try_suggestion 800]
|
|
meta def setFlagSolver (_goal : MVarId) (_info : Try.Info) : MetaM (Array (TSyntax `tactic)) := do
|
|
return #[← `(tactic| set_seed_and_succeed)]
|
|
|
|
-- If parallel: both tactics succeed (tactic 1 sees seed change after waiting)
|
|
-- If sequential: only tactic 2 succeeds (tactic 1 sees unchanged seed)
|
|
/--
|
|
info: Try these:
|
|
[apply] wait_and_check_seed
|
|
[apply] set_seed_and_succeed
|
|
-/
|
|
#guard_msgs in
|
|
example : ParallelTestGoal := by
|
|
try?
|