diff --git a/src/Lean/Meta/LazyDiscrTree.lean b/src/Lean/Meta/LazyDiscrTree.lean index 2fa9938ae4..d7c2d67b63 100644 --- a/src/Lean/Meta/LazyDiscrTree.lean +++ b/src/Lean/Meta/LazyDiscrTree.lean @@ -802,10 +802,17 @@ structure Cache where def Cache.empty (ngen : NameGenerator) : Cache := { ngen := ngen, core := {}, «meta» := {} } +/-- Check if a private name belongs to the given module -/ +private def isPrivateNameOf (declName : Name) (mainModule : Name) : Bool := + if let some pfx := privatePrefix? declName then + pfx == Name.mkNum (privateHeader ++ mainModule) 0 + else + false + def blacklistInsertion (env : Environment) (declName : Name) : Bool := !allowCompletion env declName || declName == ``sorryAx - || declName.isInternalDetail + || (declName.isInternalDetail && !isPrivateNameOf declName env.header.mainModule) || (declName matches .str _ "inj") || (declName matches .str _ "noConfusionType") diff --git a/tests/lean/run/exact_private.lean b/tests/lean/run/exact_private.lean new file mode 100644 index 0000000000..c597902b37 --- /dev/null +++ b/tests/lean/run/exact_private.lean @@ -0,0 +1,18 @@ +module + +/-! +# Tests for `exact?` with private declarations + +This tests that `exact?` can suggest private theorems defined locally in the same module. +-/ + +-- Test that exact? suggests private declarations +axiom P : Prop +private axiom p : P + +/-- +info: Try this: + [apply] exact p +-/ +#guard_msgs in +example : P := by exact? diff --git a/tests/lean/run/try_parallelism.lean b/tests/lean/run/try_parallelism.lean index 18ddff4e09..3e897e40eb 100644 --- a/tests/lean/run/try_parallelism.lean +++ b/tests/lean/run/try_parallelism.lean @@ -16,9 +16,11 @@ 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 +-- 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 +axiom _parallelTestGoalHolds : ParallelTestGoal -- Magic seed value to signal parallelism meta def magicSeed : Nat := 314159265 @@ -29,14 +31,14 @@ elab "wait_and_check_seed" : tactic => do let gen ← IO.stdGenRef.get let expected := mkStdGen magicSeed if gen.s1 == expected.s1 && gen.s2 == expected.s2 then - evalTactic (← `(tactic| exact parallelTestGoalHolds)) + 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)) + evalTactic (← `(tactic| exact _parallelTestGoalHolds)) -- Register both tactics as user suggestions -- High priority tactic: reset seed first (to ensure clean state), then return waiting tactic @@ -53,9 +55,6 @@ meta def setFlagSolver (_goal : MVarId) (_info : Try.Info) : MetaM (Array (TSynt -- If parallel: both tactics succeed (tactic 1 sees seed change after waiting) -- If sequential: only tactic 2 succeeds (tactic 1 sees unchanged seed) --- --- EXPECTED ON MASTER (sequential): Only one suggestion --- EXPECTED ON try_par (parallel): Two suggestions /-- info: Try these: [apply] wait_and_check_seed diff --git a/tests/lean/run/try_user_suggestions.lean b/tests/lean/run/try_user_suggestions.lean index c2e47bcb52..76b0783327 100644 --- a/tests/lean/run/try_user_suggestions.lean +++ b/tests/lean/run/try_user_suggestions.lean @@ -7,21 +7,23 @@ public meta import Lean.Elab.Tactic.Try open Lean Meta Elab Tactic Try --- Define an opaque predicate that built-in tactics (including solve_by_elim) won't solve +-- Define an opaque predicate 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 user-defined suggestion generators. opaque CustomProp : Prop -axiom customPropHolds : CustomProp +axiom _customPropHolds : CustomProp section BasicTest -- Define a generator that suggests the custom lemma @[local try_suggestion] meta def customPropSolver (_goal : MVarId) (_info : Try.Info) : MetaM (Array (TSyntax `tactic)) := do - return #[← `(tactic| exact customPropHolds)] + return #[← `(tactic| exact _customPropHolds)] -- Test that try? picks up the user-defined suggestion -- Built-in tactics won't solve this, so only user suggestion appears /-- info: Try this: - [apply] exact customPropHolds✝ + [apply] exact _customPropHolds✝ -/ #guard_msgs in example : CustomProp := by @@ -32,11 +34,11 @@ section PriorityTest -- Test priority ordering with multiple generators @[local try_suggestion 2000] meta def highPrioritySolver (_goal : MVarId) (_info : Try.Info) : MetaM (Array (TSyntax `tactic)) := do - return #[← `(tactic| apply customPropHolds)] + return #[← `(tactic| apply _customPropHolds)] @[local try_suggestion 1000] meta def midPrioritySolver (_goal : MVarId) (_info : Try.Info) : MetaM (Array (TSyntax `tactic)) := do - return #[← `(tactic| exact customPropHolds)] + return #[← `(tactic| exact _customPropHolds)] @[local try_suggestion 500] meta def lowPrioritySolver (_goal : MVarId) (_info : Try.Info) : MetaM (Array (TSyntax `tactic)) := do @@ -46,8 +48,8 @@ meta def lowPrioritySolver (_goal : MVarId) (_info : Try.Info) : MetaM (Array (T -- Note: constructor doesn't work on opaque types, so lowPrioritySolver's suggestion is filtered out /-- info: Try these: - [apply] apply customPropHolds✝ - [apply] exact customPropHolds✝ + [apply] apply _customPropHolds✝ + [apply] exact _customPropHolds✝ -/ #guard_msgs in example : CustomProp := by @@ -82,15 +84,15 @@ section DoubleSuggestion -- Use CustomProp which built-ins can't solve @[local try_suggestion] meta def doubleSuggestionSolver (_goal : MVarId) (_info : Try.Info) : MetaM (Array (TSyntax `tactic)) := do - return #[← `(tactic| show_term apply customPropHolds)] + return #[← `(tactic| show_term apply _customPropHolds)] -- Double-suggestion: when show_term produces a "Try this" message, -- both the original tactic and the extracted suggestion should appear -- The message from show_term during extraction is suppressed /-- info: Try these: - [apply] show_term apply customPropHolds✝ - [apply] exact customPropHolds + [apply] show_term apply _customPropHolds✝ + [apply] exact _customPropHolds -/ #guard_msgs in example : CustomProp := by @@ -99,23 +101,23 @@ end DoubleSuggestion section RegisterCommand -- Test the register_try?_tactic convenience command -register_try?_tactic (priority := 500) exact customPropHolds +register_try?_tactic (priority := 500) exact _customPropHolds /-- info: Try this: - [apply] exact customPropHolds + [apply] exact _customPropHolds -/ #guard_msgs in example : CustomProp := by try? -- Test without explicit priority (should default to 1000, so appear before exact at 500) -register_try?_tactic apply customPropHolds +register_try?_tactic apply _customPropHolds /-- info: Try these: - [apply] apply customPropHolds - [apply] exact customPropHolds + [apply] apply _customPropHolds + [apply] exact _customPropHolds -/ #guard_msgs in example : CustomProp := by