Skip to content

Commit 5ee5050

Browse files
committed
fix(Tactic/NormNum): do not re-enter simp from the very outside (#36841)
This fixes a recursion error in ```lean4 import Mathlib.SetTheory.Cardinal.Basic import Mathlib.Tactic.NormNum.Core theorem foos.{u} (α β : Type u) : Cardinal.mk α = Cardinal.mk β → α = β := by norm_num [Cardinal.mk_eq_aleph0] ``` which is quite willing to be promoted to a stack overflow with a moderate recursion depth limit. It's not entirely clear to me if `dischargeGround` is the right discharger to use here, but no tests fail because of that choice. Note this change breaks the following proof: ```lean4 import Mathlib.Tactic.NormNum theorem foo (x y : ℚ) (h₀ : x > 0 ∧ y > 0) (h₁ : x < 1 ∧ y < 1) : 0 ≤ x / (1 - x) + y / (1 - y) := by norm_num [*, div_pos, add_pos, le_of_lt] ``` The reason is that previously `norm_num` was `simp` plus _two_ things: * Numeral normalization. * Hackily overriding `maxDischargeDepth` to exceed maxRecDepth
1 parent 2da3b35 commit 5ee5050

File tree

2 files changed

+20
-22
lines changed

2 files changed

+20
-22
lines changed

Mathlib/Tactic/NormNum/Core.lean

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -215,27 +215,25 @@ def tryNormNum (post := false) (e : Expr) : SimpM Simp.Step := do
215215
catch _ =>
216216
return .continue
217217

218-
variable (ctx : Simp.Context) (useSimp := true) in
219-
mutual
220-
/-- A discharger which calls `norm_num`. -/
221-
partial def discharge (e : Expr) : SimpM (Option Expr) := do (← deriveSimp e).ofTrue
222-
223-
/-- A `Methods` implementation which calls `norm_num`. -/
224-
partial def methods : Simp.Methods :=
225-
if useSimp then {
226-
pre := Simp.preDefault #[] >> tryNormNum
227-
post := Simp.postDefault #[] >> tryNormNum (post := true)
228-
discharge? := discharge
229-
} else {
230-
pre := tryNormNum
231-
post := tryNormNum (post := true)
232-
discharge? := discharge
233-
}
234-
235-
/-- Traverses the given expression using simp and normalises any numbers it finds. -/
236-
partial def deriveSimp (e : Expr) : MetaM Simp.Result :=
237-
(·.1) <$> Simp.main e ctx (methods := methods)
238-
end
218+
/-- A `Methods` implementation which calls `norm_num`. -/
219+
def methods (useSimp := true) : Simp.Methods :=
220+
if useSimp then {
221+
pre := Simp.preDefault #[] >> tryNormNum
222+
post := Simp.postDefault #[] >> tryNormNum (post := true)
223+
discharge? := Simp.dischargeGround
224+
} else {
225+
pre := tryNormNum
226+
post := tryNormNum (post := true)
227+
discharge? := Simp.dischargeGround
228+
}
229+
230+
/-- Traverses the given expression using simp and normalises any numbers it finds. -/
231+
def deriveSimp (ctx : Simp.Context) (useSimp := true) (e : Expr) : MetaM Simp.Result :=
232+
(·.1) <$> Simp.main e ctx (methods := methods useSimp)
233+
234+
/-- A discharger which calls `norm_num`, for use in downstream tactics populating `Simp.Methods`. -/
235+
def discharge (useSimp := true) (e : Expr) : SimpM (Option Expr) := do
236+
(← deriveSimp (← readThe Simp.Context) useSimp e).ofTrue
239237

240238
open Tactic in
241239
/-- Constructs a simp context from the simp argument syntax. -/

Mathlib/Tactic/ReduceModChar.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ partial def derive (expensive := false) (e : Expr) : MetaM Simp.Result := do
256256
| none => throwError "internal error: reduce_mod_char not registered as simp extension"
257257
let ctx ← Simp.mkContext config (congrTheorems := congrTheorems)
258258
(simpTheorems := #[← ext.getTheorems])
259-
let discharge := Mathlib.Meta.NormNum.discharge ctx
259+
let discharge := Mathlib.Meta.NormNum.discharge
260260
let r : Simp.Result := {expr := e}
261261
let pre := Simp.preDefault #[] >> fun e =>
262262
try return (Simp.Step.done (← matchAndNorm (expensive := expensive) e))

0 commit comments

Comments
 (0)