Skip to content
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

fix: simp? suggests generated equations lemma names #3573

Merged
merged 2 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions src/Lean/Meta/Eqns.lean
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ private def shouldGenerateEqnThms (declName : Name) : MetaM Bool := do
return false

structure EqnsExtState where
map : PHashMap Name (Array Name) := {}
map : PHashMap Name (Array Name) := {}
mapInv : PHashMap Name Name := {}
deriving Inhabited

/- We generate the equations on demand, and do not save them on .olean files. -/
Expand All @@ -77,7 +78,22 @@ private def mkSimpleEqThm (declName : Name) : MetaM (Option Name) := do
return none

/--
Return equation theorems for the given declaration.
Returns `some declName` if `thmName` is an equational theorem for `declName`.
-/
def isEqnThm? (thmName : Name) : CoreM (Option Name) := do
return eqnsExt.getState (← getEnv) |>.mapInv.find? thmName

/--
Stores in the `eqnsExt` environment extension that `eqThms` are the equational theorems for `declName`
-/
private def registerEqnThms (declName : Name) (eqThms : Array Name) : CoreM Unit := do
modifyEnv fun env => eqnsExt.modifyState env fun s => { s with
map := s.map.insert declName eqThms
mapInv := eqThms.foldl (init := s.mapInv) fun mapInv eqThm => mapInv.insert eqThm declName
}

/--
Returns equation theorems for the given declaration.
By default, we do not create equation theorems for nonrecursive definitions.
You can use `nonRec := true` to override this behavior, a dummy `rfl` proof is created on the fly.
-/
Expand All @@ -87,12 +103,12 @@ def getEqnsFor? (declName : Name) (nonRec := false) : MetaM (Option (Array Name)
else if (← shouldGenerateEqnThms declName) then
for f in (← getEqnsFnsRef.get) do
if let some r ← f declName then
modifyEnv fun env => eqnsExt.modifyState env fun s => { s with map := s.map.insert declName r }
registerEqnThms declName r
return some r
if nonRec then
let some eqThm ← mkSimpleEqThm declName | return none
let r := #[eqThm]
modifyEnv fun env => eqnsExt.modifyState env fun s => { s with map := s.map.insert declName r }
registerEqnThms declName r
return some r
return none

Expand Down
18 changes: 17 additions & 1 deletion src/Lean/Meta/Tactic/Simp/Types.lean
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Authors: Leonardo de Moura
prelude
import Lean.Meta.AppBuilder
import Lean.Meta.CongrTheorems
import Lean.Meta.Eqns
import Lean.Meta.Tactic.Replace
import Lean.Meta.Tactic.Simp.SimpTheorems
import Lean.Meta.Tactic.Simp.SimpCongrTheorems
Expand Down Expand Up @@ -256,7 +257,22 @@ def getSimpCongrTheorems : SimpM SimpCongrTheorems :=
@[inline] def withDischarger (discharge? : Expr → SimpM (Option Expr)) (x : SimpM α) : SimpM α :=
savingCache <| withReader (fun r => { MethodsRef.toMethods r with discharge? }.toMethodsRef) x

def recordSimpTheorem (thmId : Origin) : SimpM Unit :=
def recordSimpTheorem (thmId : Origin) : SimpM Unit := do
/-
If `thmId` is an equational theorem (e.g., `foo._eq_1`), we should record `foo` instead.
See issue #3547.
-/
let thmId ← match thmId with
| .decl declName post false =>
/-
Remark: if `inv := true`, then the user has manually provided the theorem and wants to
use it in the reverse direction. So, we only performs the substitution when `inv := false`
-/
if let some declName ← isEqnThm? declName then
pure (Origin.decl declName post false)
else
pure thmId
| _ => pure thmId
modify fun s => if s.usedTheorems.contains thmId then s else
let n := s.usedTheorems.size
{ s with usedTheorems := s.usedTheorems.insert thmId n }
Expand Down
11 changes: 11 additions & 0 deletions tests/lean/run/3547.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
def foo : Nat → Nat
| 0 => 0
| n+1 => foo n
decreasing_by decreasing_tactic

/--
info: Try this: simp only [foo]
-/
#guard_msgs in
def foo2 : foo 2 = 0 := by
simp? [foo]
Loading