chore: rename automatically generated "unfold" theorems (#3767)
Given a definition `foo`, they were previously called `foo._unfold` until 4.7.0. We tried to rename them to `foo.def`, but it created too many issues in the Mathlib repo. We decided to rename it again to `foo.eq_def`. The new name is also consistent with the `eq_<idx>` theorems generated for different "cases". That is, `foo.eq_def` is the equality theorem for the whole definition, and `foo.eq_<idx>` is the equality theorem for case `<idx>`. cc @semorrison
This commit is contained in:
parent
a0dac9f546
commit
22b5c957e9
17 changed files with 70 additions and 47 deletions
|
|
@ -371,7 +371,7 @@ def mkUnfoldEq (declName : Name) (info : EqnInfoCore) : MetaM Name := withLCtx {
|
|||
mkUnfoldProof declName goal.mvarId!
|
||||
let type ← mkForallFVars xs type
|
||||
let value ← mkLambdaFVars xs (← instantiateMVars goal)
|
||||
let name := baseName ++ `def
|
||||
let name := Name.str baseName unfoldThmSuffix
|
||||
addDecl <| Declaration.thmDecl {
|
||||
name, type, value
|
||||
levelParams := info.levelParams
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ def mkEqns (info : EqnInfo) : MetaM (Array Name) :=
|
|||
for i in [: eqnTypes.size] do
|
||||
let type := eqnTypes[i]!
|
||||
trace[Elab.definition.structural.eqns] "{eqnTypes[i]!}"
|
||||
let name := baseName ++ (`eq).appendIndexAfter (i+1)
|
||||
let name := (Name.str baseName eqnThmSuffixBase).appendIndexAfter (i+1)
|
||||
thmNames := thmNames.push name
|
||||
let value ← mkProof info.declName type
|
||||
let (type, value) ← removeUnusedEqnHypotheses type value
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ def mkEqns (declName : Name) (info : EqnInfo) : MetaM (Array Name) :=
|
|||
for i in [: eqnTypes.size] do
|
||||
let type := eqnTypes[i]!
|
||||
trace[Elab.definition.wf.eqns] "{eqnTypes[i]!}"
|
||||
let name := baseName ++ (`eq).appendIndexAfter (i+1)
|
||||
let name := (Name.str baseName eqnThmSuffixBase).appendIndexAfter (i+1)
|
||||
thmNames := thmNames.push name
|
||||
let value ← mkProof declName type
|
||||
let (type, value) ← removeUnusedEqnHypotheses type value
|
||||
|
|
|
|||
|
|
@ -9,25 +9,32 @@ import Lean.Meta.Basic
|
|||
import Lean.Meta.AppBuilder
|
||||
|
||||
namespace Lean.Meta
|
||||
def eqnThmSuffixBase := "eq"
|
||||
def eqnThmSuffixBasePrefix := eqnThmSuffixBase ++ "_"
|
||||
def eqn1ThmSuffix := eqnThmSuffixBasePrefix ++ "1"
|
||||
example : eqn1ThmSuffix = "eq_1" := rfl
|
||||
|
||||
/-- Returns `true` if `s` is of the form `eq_<idx>` -/
|
||||
def isEqnReservedNameSuffix (s : String) : Bool :=
|
||||
"eq_".isPrefixOf s && (s.drop 3).isNat
|
||||
eqnThmSuffixBasePrefix.isPrefixOf s && (s.drop 3).isNat
|
||||
|
||||
/-- Returns `true` if `s == "def"` -/
|
||||
def unfoldThmSuffix := "eq_def"
|
||||
|
||||
/-- Returns `true` if `s == "eq_def"` -/
|
||||
def isUnfoldReservedNameSuffix (s : String) : Bool :=
|
||||
s == "def"
|
||||
s == unfoldThmSuffix
|
||||
|
||||
/--
|
||||
Throw an error if names for equation theorems for `declName` are not available.
|
||||
-/
|
||||
def ensureEqnReservedNamesAvailable (declName : Name) : CoreM Unit := do
|
||||
ensureReservedNameAvailable declName "def"
|
||||
ensureReservedNameAvailable declName "eq_1"
|
||||
ensureReservedNameAvailable declName unfoldThmSuffix
|
||||
ensureReservedNameAvailable declName eqn1ThmSuffix
|
||||
-- TODO: `declName` may need to reserve multiple `eq_<idx>` names, but we check only the first one.
|
||||
-- Possible improvement: try to efficiently compute the number of equation theorems at declaration time, and check all of them.
|
||||
|
||||
/--
|
||||
Ensures that `f.def` and `f.eq_<idx>` are reserved names if `f` is a safe definition.
|
||||
Ensures that `f.eq_def` and `f.eq_<idx>` are reserved names if `f` is a safe definition.
|
||||
-/
|
||||
builtin_initialize registerReservedNamePredicate fun env n =>
|
||||
match n with
|
||||
|
|
@ -87,7 +94,7 @@ builtin_initialize eqnsExt : EnvExtension EqnsExtState ←
|
|||
/--
|
||||
Simple equation theorem for nonrecursive definitions.
|
||||
-/
|
||||
private def mkSimpleEqThm (declName : Name) (suffix := `def) : MetaM (Option Name) := do
|
||||
private def mkSimpleEqThm (declName : Name) (suffix := Name.mkSimple unfoldThmSuffix) : MetaM (Option Name) := do
|
||||
if let some (.defnInfo info) := (← getEnv).find? declName then
|
||||
lambdaTelescope (cleanupAnnotations := true) info.value fun xs body => do
|
||||
let lhs := mkAppN (mkConst info.name <| info.levelParams.map mkLevelParam) xs
|
||||
|
|
@ -122,7 +129,7 @@ Equation theorems are generated on demand, check whether they were generated in
|
|||
-/
|
||||
private partial def alreadyGenerated? (declName : Name) : MetaM (Option (Array Name)) := do
|
||||
let env ← getEnv
|
||||
let eq1 := declName ++ `eq_1
|
||||
let eq1 := Name.str declName eqn1ThmSuffix
|
||||
if env.contains eq1 then
|
||||
let rec loop (idx : Nat) (eqs : Array Name) : MetaM (Array Name) := do
|
||||
let nextEq := declName ++ (`eq).appendIndexAfter idx
|
||||
|
|
@ -152,7 +159,7 @@ def getEqnsFor? (declName : Name) (nonRec := false) : MetaM (Option (Array Name)
|
|||
registerEqnThms declName r
|
||||
return some r
|
||||
if nonRec then
|
||||
let some eqThm ← mkSimpleEqThm declName (suffix := `eq_1) | return none
|
||||
let some eqThm ← mkSimpleEqThm declName (suffix := Name.mkSimple eqn1ThmSuffix) | return none
|
||||
let r := #[eqThm]
|
||||
registerEqnThms declName r
|
||||
return some r
|
||||
|
|
@ -199,7 +206,7 @@ You can use `nonRec := true` to override this behavior.
|
|||
-/
|
||||
def getUnfoldEqnFor? (declName : Name) (nonRec := false) : MetaM (Option Name) := withLCtx {} {} do
|
||||
let env ← getEnv
|
||||
let unfoldName := declName ++ `def
|
||||
let unfoldName := Name.str declName unfoldThmSuffix
|
||||
if env.contains unfoldName then
|
||||
return some unfoldName
|
||||
if (← shouldGenerateEqnThms declName) then
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ theorem ex : foo 0 = 0 := by
|
|||
sorry
|
||||
|
||||
/--
|
||||
info: foo.def (n : Nat) :
|
||||
info: foo.eq_def (n : Nat) :
|
||||
foo n =
|
||||
if n = 0 then 0
|
||||
else
|
||||
|
|
@ -20,4 +20,4 @@ info: foo.def (n : Nat) :
|
|||
foo x
|
||||
-/
|
||||
#guard_msgs in
|
||||
#check foo.def
|
||||
#check foo.eq_def
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ theorem ex2 : g 0 = 0 := by
|
|||
unfold g
|
||||
simp
|
||||
|
||||
#check g.def
|
||||
#check g.eq_def
|
||||
|
||||
|
||||
end Ex2
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
-- `g.def` is not reserved yet
|
||||
theorem g.def : 1 + x = x + 1 := Nat.add_comm ..
|
||||
-- `g.eq_def` is not reserved yet
|
||||
theorem g.eq_def : 1 + x = x + 1 := Nat.add_comm ..
|
||||
|
||||
/--
|
||||
error: failed to declare `g` because `g.def` has already been declared
|
||||
error: failed to declare `g` because `g.eq_def` has already been declared
|
||||
-/
|
||||
#guard_msgs (error) in
|
||||
def g (x : Nat) := x + 1
|
||||
|
|
@ -10,10 +10,10 @@ def g (x : Nat) := x + 1
|
|||
def f (x : Nat) := x + 1
|
||||
|
||||
/--
|
||||
error: 'f.def' is a reserved name
|
||||
error: 'f.eq_def' is a reserved name
|
||||
-/
|
||||
#guard_msgs (error) in
|
||||
theorem f.def : f x = x + 1 := rfl
|
||||
theorem f.eq_def : f x = x + 1 := rfl
|
||||
|
||||
/--
|
||||
error: 'f.eq_1' is a reserved name
|
||||
|
|
@ -31,16 +31,16 @@ def f.eq_2_ := 10 -- Should be ok
|
|||
#guard_msgs (error) in
|
||||
#check f.eq_2
|
||||
|
||||
/-- info: f.def (x : Nat) : f x = x + 1 -/
|
||||
/-- info: f.eq_def (x : Nat) : f x = x + 1 -/
|
||||
#guard_msgs in
|
||||
#check f.def
|
||||
#check f.eq_def
|
||||
|
||||
def fact : Nat → Nat
|
||||
| 0 => 1
|
||||
| n+1 => (n+1) * fact n
|
||||
|
||||
/--
|
||||
info: fact.def :
|
||||
info: fact.eq_def :
|
||||
∀ (x : Nat),
|
||||
fact x =
|
||||
match x with
|
||||
|
|
@ -48,7 +48,7 @@ info: fact.def :
|
|||
| n.succ => (n + 1) * fact n
|
||||
-/
|
||||
#guard_msgs in
|
||||
#check fact.def
|
||||
#check fact.eq_def
|
||||
|
||||
/-- info: fact.eq_1 : fact 0 = 1 -/
|
||||
#guard_msgs in
|
||||
|
|
@ -77,9 +77,9 @@ example : fact' 0 + fact' 1 = 2 := by
|
|||
rw [fact'.eq_1]
|
||||
|
||||
example : fact' 0 + fact' 1 = 2 := by
|
||||
rw [fact'.def, fact'.def]; simp
|
||||
rw [fact'.eq_def, fact'.eq_def]; simp
|
||||
guard_target =ₛ 1 + fact' 0 = 2
|
||||
rw [fact'.def]
|
||||
rw [fact'.eq_def]
|
||||
guard_target =
|
||||
(1 + fact.match_1 (fun _ => Nat) 0 (fun _ => 1) fun n => (n + 1) * fact' n) = 2
|
||||
simp
|
||||
|
|
@ -88,3 +88,19 @@ theorem bla : 0 = 0 := rfl
|
|||
|
||||
def bla.def := 1 -- should work since `bla` is a theorem
|
||||
def bla.eq_1 := 2 -- should work since `bla` is a theorem
|
||||
|
||||
def find (as : Array Int) (i : Nat) (v : Int) : Nat :=
|
||||
if _ : i < as.size then
|
||||
if as[i] = v then
|
||||
i
|
||||
else
|
||||
find as (i+1) v
|
||||
else
|
||||
i
|
||||
|
||||
/--
|
||||
info: find.eq_def (as : Array Int) (i : Nat) (v : Int) :
|
||||
find as i v = if x : i < as.size then if as[i] = v then i else find as (i + 1) v else i
|
||||
-/
|
||||
#guard_msgs in
|
||||
#check find.eq_def
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ theorem len_2 (a b : α) (bs : List α) : len (a::b::bs) = 1 + len (b::bs) := by
|
|||
conv => lhs; unfold len
|
||||
|
||||
-- The `unfold` tactic above generated the following theorem
|
||||
#check @len.def
|
||||
#check @len.eq_def
|
||||
|
||||
theorem len_cons (a : α) (as : List α) : len (a::as) = 1 + len as := by
|
||||
cases as with
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ theorem len_2 (a b : α) (bs : List α) : len (a::b::bs) = 1 + len (b::bs) := by
|
|||
conv => lhs; unfold len
|
||||
|
||||
-- The `unfold` tactic above generated the following theorem
|
||||
#check @len.def
|
||||
#check @len.eq_def
|
||||
|
||||
theorem len_cons (a : α) (as : List α) : len (a::as) = 1 + len as := by
|
||||
cases as with
|
||||
|
|
@ -99,7 +99,7 @@ theorem len_2 (a b : α) (bs : List α) : len (a::b::bs) = 1 + len (b::bs) := by
|
|||
conv => lhs; unfold len
|
||||
|
||||
-- The `unfold` tactic above generated the following theorem
|
||||
#check @len.def
|
||||
#check @len.eq_def
|
||||
|
||||
theorem len_cons (a : α) (as : List α) : len (a::as) = 1 + len as := by
|
||||
cases as with
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ def foo (xs ys zs : List Nat) : List Nat :=
|
|||
#eval tst ``foo
|
||||
|
||||
/--
|
||||
info: foo.def (xs ys zs : List Nat) :
|
||||
info: foo.eq_def (xs ys zs : List Nat) :
|
||||
foo xs ys zs =
|
||||
match (xs, ys) with
|
||||
| (xs', ys') =>
|
||||
|
|
@ -29,7 +29,7 @@ info: foo.def (xs ys zs : List Nat) :
|
|||
| x => [2]
|
||||
-/
|
||||
#guard_msgs in
|
||||
#check foo.def
|
||||
#check foo.eq_def
|
||||
|
||||
|
||||
def bar (xs ys : List Nat) : List Nat :=
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ def tst (declName : Name) : MetaM Unit := do
|
|||
#eval tst ``List.map
|
||||
#check @List.map.eq_1
|
||||
#check @List.map.eq_2
|
||||
#check @List.map.def
|
||||
#check @List.map.eq_def
|
||||
|
||||
def foo (xs ys zs : List Nat) : List Nat :=
|
||||
match (xs, ys) with
|
||||
|
|
@ -23,7 +23,7 @@ def foo (xs ys zs : List Nat) : List Nat :=
|
|||
|
||||
#check foo.eq_1
|
||||
#check foo.eq_2
|
||||
#check foo.def
|
||||
#check foo.eq_def
|
||||
|
||||
#eval tst ``foo
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ def g : List Nat → List Nat → Nat
|
|||
#check g.eq_3
|
||||
#check g.eq_4
|
||||
#check g.eq_5
|
||||
#check g.def
|
||||
#check g.eq_def
|
||||
|
||||
def h (xs : List Nat) (y : Nat) : Nat :=
|
||||
match xs with
|
||||
|
|
@ -53,7 +53,7 @@ def h (xs : List Nat) (y : Nat) : Nat :=
|
|||
#eval tst ``h
|
||||
#check h.eq_1
|
||||
#check h.eq_2
|
||||
#check h.def
|
||||
#check h.eq_def
|
||||
|
||||
def r (i j : Nat) : Nat :=
|
||||
i +
|
||||
|
|
@ -68,7 +68,7 @@ def r (i j : Nat) : Nat :=
|
|||
#check r.eq_1
|
||||
#check r.eq_2
|
||||
#check r.eq_3
|
||||
#check r.def
|
||||
#check r.eq_def
|
||||
|
||||
def bla (f g : α → α → α) (a : α) (i : α) (j : Nat) : α :=
|
||||
f i <|
|
||||
|
|
@ -83,4 +83,4 @@ def bla (f g : α → α → α) (a : α) (i : α) (j : Nat) : α :=
|
|||
#check @bla.eq_1
|
||||
#check @bla.eq_2
|
||||
#check @bla.eq_3
|
||||
#check @bla.def
|
||||
#check @bla.eq_def
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ def g (i j : Nat) : Nat :=
|
|||
#eval tst ``g
|
||||
#check g.eq_1
|
||||
#check g.eq_2
|
||||
#check g.def
|
||||
#check g.eq_def
|
||||
|
||||
def h (i j : Nat) : Nat :=
|
||||
let z :=
|
||||
|
|
@ -26,4 +26,4 @@ def h (i j : Nat) : Nat :=
|
|||
#eval tst ``h
|
||||
#check h.eq_1
|
||||
#check h.eq_2
|
||||
#check h.def
|
||||
#check h.eq_def
|
||||
|
|
|
|||
|
|
@ -17,4 +17,4 @@ def wk_comp : Wk n m → Wk m l → Wk n l
|
|||
|
||||
#check @wk_comp.eq_1
|
||||
#check @wk_comp.eq_2
|
||||
#check @wk_comp.def
|
||||
#check @wk_comp.eq_def
|
||||
|
|
|
|||
|
|
@ -24,4 +24,4 @@ end
|
|||
#eval tst ``isEven
|
||||
#check @isEven.eq_1
|
||||
#check @isEven.eq_2
|
||||
#check @isEven.def
|
||||
#check @isEven.eq_def
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ end
|
|||
#eval tst ``g
|
||||
#check g.eq_1
|
||||
#check g.eq_2
|
||||
#check g.def
|
||||
#check g.eq_def
|
||||
#eval tst ``h
|
||||
#check h.eq_1
|
||||
#check h.eq_2
|
||||
#check h.def
|
||||
#check h.eq_def
|
||||
|
|
|
|||
|
|
@ -16,4 +16,4 @@ decreasing_by
|
|||
|
||||
#eval tst ``f
|
||||
#check f.eq_1
|
||||
#check f.def
|
||||
#check f.eq_def
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ end
|
|||
#eval tst ``f
|
||||
#check @f.eq_1
|
||||
#check @f.eq_2
|
||||
#check @f.def
|
||||
#check @f.eq_def
|
||||
|
||||
|
||||
#eval tst ``h
|
||||
#check @h.eq_1
|
||||
#check @h.eq_2
|
||||
#check @h.def
|
||||
#check @h.eq_def
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue