fix: prune universe params in functional induction (#3754)

fixes #3752
This commit is contained in:
Joachim Breitner 2024-03-24 11:15:50 +01:00 committed by GitHub
parent 655ec964f5
commit 80d2455b64
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 62 additions and 1 deletions

View file

@ -603,8 +603,12 @@ def deriveUnaryInduction (name : Name) : MetaM Name := do
logError m!"failed to derive induction priciple:{indentExpr e'}"
check e'
let params := (collectLevelParams {} eTyp).params
-- Prune unused level parameters, preserving the original order
let us := info.levelParams.filter (params.contains ·)
addDecl <| Declaration.thmDecl
{ name := inductName, levelParams := info.levelParams, type := eTyp, value := e' }
{ name := inductName, levelParams := us, type := eTyp, value := e' }
return inductName
/--

View file

@ -0,0 +1,57 @@
/-!
This test checks if the functional induction principle has fewer universe parameters
if the original function has a parameter that disappears.
-/
namespace WellFounded
def foo.{u,v} {α : Type v} : List α → PUnit.{u}
| [] => .unit
| _ :: xs => foo xs
termination_by xs => xs
derive_functional_induction foo
/--
info: WellFounded.foo.induct.{v} {α : Type v} (motive : List α → Prop) (case1 : motive [])
(case2 : ∀ (head : α) (xs : List α), motive xs → motive (head :: xs)) (x : List α) : motive x
-/
#guard_msgs in
#check foo.induct
example : foo xs = .unit := by
induction xs using foo.induct with
| case1 => unfold foo; rfl
| case2 _ xs ih => unfold foo; exact ih
end WellFounded
namespace Mutual
mutual
def foo.{u} : Nat → PUnit.{u}
| 0 => .unit
| n+1 => bar n
termination_by n => n
def bar.{u} : Nat → PUnit.{u}
| 0 => .unit
| n+1 => foo n
termination_by n => n
end
derive_functional_induction foo
/--
info: Mutual.foo.induct (motive1 motive2 : Nat → Prop) (case1 : motive1 0) (case2 : motive2 0)
(case3 : ∀ (n : Nat), motive2 n → motive1 n.succ) (case4 : ∀ (n : Nat), motive1 n → motive2 n.succ) :
∀ (a : Nat), motive1 a
-/
#guard_msgs in
#check foo.induct
example : foo n = .unit := by
induction n using foo.induct (motive2 := fun n => bar n = .unit) with
| case1 => unfold foo; rfl
| case2 => unfold bar; rfl
| case3 n ih => unfold foo; exact ih
| case4 n ih => unfold bar; exact ih
end Mutual