Skip to content

Commit 5390cdb

Browse files
authored
fix: correctly handle explicit monotonicity proofs in mutual definitions (#8763)
This PR corrects the handling of explicit `monotonicity` proofs for mutual `partial_fixpoint` definitions.
1 parent e713232 commit 5390cdb

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

src/Lean/Elab/PreDefinition/PartialFixpoint/Main.lean

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,19 @@ private def unReplaceRecApps {α} (preDefs : Array PreDefinition) (fixedParamPer
6060
pure e
6161
k e
6262

63-
def mkMonoPProd (hmono₁ hmono₂ : Expr) : MetaM Expr := do
63+
/--
64+
Given two type-proof pairs for `monotone f` and `monotone g`, constructs a type-proof pair for `monotone fun x => ⟨f x, g x⟩`.
65+
-/
66+
private def mkMonoPProd : (hmono₁ hmono₂ : Expr × Expr) → MetaM (Expr × Expr)
67+
| (hmono1Type, hmono1Proof), (hmono2Type, hmono2Proof) => do
6468
-- mkAppM does not support the equivalent of (cfg := { synthAssignedInstances := false}),
6569
-- so this is a bit more pedestrian
66-
let_expr monotone _ inst _ inst₁ _ := (← inferType hmono₁)
67-
| throwError "mkMonoPProd: unexpected type of{indentExpr hmono₁}"
68-
let_expr monotone _ _ _ inst₂ _ := (← inferType hmono₂)
69-
| throwError "mkMonoPProd: unexpected type of{indentExpr hmono₂}"
70-
mkAppOptM ``PProd.monotone_mk #[none, none, none, inst₁, inst₂, inst, none, none, hmono₁, hmono₂]
70+
let_expr monotone _ inst _ inst₁ _ := hmono1Type
71+
| throwError "mkMonoPProd: unexpected type of{indentExpr hmono1Proof}"
72+
let_expr monotone _ _ _ inst₂ _ := hmono2Type
73+
| throwError "mkMonoPProd: unexpected type of{indentExpr hmono2Proof}"
74+
let hmonoProof ← mkAppOptM ``PProd.monotone_mk #[none, none, none, inst₁, inst₂, inst, none, none, hmono1Proof, hmono2Proof]
75+
return (← inferType hmonoProof, hmonoProof)
7176

7277
def partialFixpoint (preDefs : Array PreDefinition) : TermElabM Unit := do
7378
-- We expect all functions in the clique to have `partial_fixpoint` or `greatest_fixpoint` syntax
@@ -168,17 +173,17 @@ def partialFixpoint (preDefs : Array PreDefinition) : TermElabM Unit := do
168173
let hmono ← instantiateMVars hmono
169174
let mvars ← getMVars hmono
170175
if mvars.isEmpty then
171-
pure hmono
176+
pure (goal, hmono)
172177
else
173178
discard <| Term.logUnassignedUsingErrorInfos mvars
174-
mkSorry goal (synthetic := true)
179+
pure (goal, ← mkSorry goal (synthetic := true))
175180
else
176181
let hmono ← mkFreshExprSyntheticOpaqueMVar goal
177182
prependError m!"Could not prove '{preDef.declName}' to be monotone in its recursive calls:" do
178183
solveMono failK hmono.mvarId!
179184
trace[Elab.definition.partialFixpoint] "monotonicity proof for {preDef.declName}: {hmono}"
180-
instantiateMVars hmono
181-
let hmono ← PProdN.genMk mkMonoPProd hmonos
185+
pure (goal, ← instantiateMVars hmono)
186+
let (_, hmono) ← PProdN.genMk mkMonoPProd hmonos
182187

183188
let packedValue ← mkFixOfMonFun packedType packedInst hmono
184189

tests/lean/run/partial_fixpoint_explicit.lean

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,15 @@ partial_fixpoint monotonicity by
6262
intro y
6363
apply Lean.Order.monotone_apply
6464
apply Lean.Order.monotone_id
65+
66+
-- Mutual
67+
68+
mutual
69+
70+
def mutual1 (x : Nat) : Option Unit := mutual2 (x + 1)
71+
partial_fixpoint monotonicity fun _ _ a x => a.2 (x + 1)
72+
73+
def mutual2 (x : Nat) : Option Unit := mutual1 (x + 1)
74+
partial_fixpoint monotonicity fun _ _ a x => a.1 (x + 1)
75+
76+
end

0 commit comments

Comments
 (0)