Skip to content

Commit

Permalink
fix: don't try to generate below for nested predicates. (leanprover…
Browse files Browse the repository at this point in the history
…#2390)

* fix: don't try to generate `below` for nested predicates.

* doc : document test leanprover#2389

* doc : document `mkBelow`

* test: extend `2389.lean`

* style: fix comments in `IndPredBelow.lean` and `2389.lean`
  • Loading branch information
arthur-adjedj authored Sep 21, 2023
1 parent e79370a commit 325fab1
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/Lean/Meta/IndPredBelow.lean
Original file line number Diff line number Diff line change
Expand Up @@ -571,10 +571,13 @@ def findBelowIdx (xs : Array Expr) (motive : Expr) : MetaM $ Option (Expr × Nat
else pure none
| _, _ => pure none

/-- Generates the auxiliary lemmas `below` and `brecOn` for a recursive inductive predicate.
The current generator doesn't support nested predicates, but pattern-matching on them still works
thanks to well-founded recursion. -/
def mkBelow (declName : Name) : MetaM Unit := do
if (← isInductivePredicate declName) then
let x ← getConstInfoInduct declName
if x.isRec then
if x.isRec && !x.isNested then
let ctx ← IndPredBelow.mkContext declName
let decl ← IndPredBelow.mkBelowDecl ctx
addDecl decl
Expand All @@ -585,7 +588,7 @@ def mkBelow (declName : Name) : MetaM Unit := do
let decl ← IndPredBelow.mkBrecOnDecl ctx i
addDecl decl
catch e => trace[Meta.IndPredBelow] "failed to prove brecOn for {ctx.belowNames[i]!}\n{e.toMessageData}"
else trace[Meta.IndPredBelow] "Not recursive"
else trace[Meta.IndPredBelow] "Nested or not recursive"
else trace[Meta.IndPredBelow] "Not inductive predicate"

builtin_initialize
Expand Down
35 changes: 35 additions & 0 deletions tests/lean/run/2389.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/-!
# Verify that nested predicates don't trigger the generation of `below` lemmas
Since the case of nested predicates is not currently handled by `mkBelow` (in `src/Lean/Meta/IndPredBelow.lean`),
trying to generate `OnlyZeros.below` triggers an error upon defining the inductive type.
-/

inductive Forall (P : α → Prop) : List α → Prop
| nil : Forall P []
| cons : {x : α} → P x → Forall P l → Forall P (x::l)

inductive Tree : Type :=
| leaf : Nat → Tree
| node : List Tree → Tree

set_option trace.Meta.IndPredBelow true in

/-- Despite not having `.below` and `.brecOn`,
the type is still usable thanks to well-founded recursion. -/
inductive OnlyZeros : Tree → Prop :=
| leaf : OnlyZeros (.leaf 0)
| node (l : List Tree): Forall OnlyZeros l → OnlyZeros (.node l)

/-- Equivalent definition of `OnlyZeros`, defined by a function instead of an inductive type. -/
def onlyZeros : Tree → Prop
| .leaf n => n = 0
| .node [] => True
| .node (x::s) => onlyZeros x ∧ onlyZeros (.node s)

/-- Pattern-matching on `OnlyZeros` works despite `below` and `brecOn` not being generated. -/
def toFixPoint : OnlyZeros t → onlyZeros t
| .leaf => rfl
| .node [] _ => True.intro
| .node (x::s) (.cons h p) => by
rw [onlyZeros] -- necessary because `onlyZeros` isn't structurally recursive
exact And.intro (toFixPoint h) (toFixPoint (.node s p))
1 change: 1 addition & 0 deletions tests/lean/run/2389.lean.expected.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Meta.IndPredBelow] Nested or not recursive

0 comments on commit 325fab1

Please sign in to comment.