leanprover / leanprover/lean4

Recursive theorems with `cases` vs `match`

Open
#5,690 3 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug P-medium
Dominant language
Lean
Stars
9.2k
Forks
990
Avg merge
1d 17h
Merged PRs (30d)
175

Description

Prerequisites

Please put an X between the brackets as you perform the following steps:

Description

Consider:

inductive C : Nat → Type where
| C0  : C 0
| C1  : C n → C (1 + n)
| C2  : C n → C n → C n

open C

def id_C (c : C n) : C n :=
  match c with
  | C0       => C0
  | C1 c     => C1 (id_C c)
  | C2 c₁ c₂ => C2 (id_C c₁) (id_C c₂)

We can prove the following theorem with match or induction:

theorem id_c_is_identity (c : C n) : id_C c = c := by
  match c with
  | C0 => simp [id_C]
  | C1 inner => simp [id_C, id_c_is_identity inner]
  | C2 lhs rhs => simp [id_C, id_c_is_identity lhs, id_c_is_identity rhs]

this will use the structural termination metric on c as expected.
However the following:

theorem id_c_is_identity (c : C n) : id_C c = c := by
  cases c with
  | C0 => simp [id_C]
  | C1 inner => simp [id_C, id_c_is_identity inner]
  | C2 lhs rhs => simp [id_C, id_c_is_identity lhs, id_c_is_identity rhs]

Fails to prove termination, if we force a use of the structural metric:

theorem id_c_is_identity (c : C n) : id_C c = c := by
  cases c with
  | C0 => simp [id_C]
  | C1 inner => simp [id_C, id_c_is_identity inner]
  | C2 lhs rhs => simp [id_C, id_c_is_identity lhs, id_c_is_identity rhs]
termination_by structural c

We get

failed to infer structural recursion:
Cannot use parameter c:
  failed to eliminate recursive application
    id_c_is_identity lhs
Steps to Reproduce

Expected behavior: Given that it works with match it should either also work with cases or there should be a better error message explaining why that is not the case (haha).

Actual behavior: match works, cases doesn't.

Versions

"4.12.0-nightly-2024-10-13"

Impact

Add 👍 to issues you consider important. If others are impacted by this issue, please ask them to add 👍 to it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the self-contained inductive type and theorem examples in the issue, comparing the match and cases versions in Lean nightly via live.lean-lang.org. Investigate the structural termination check around termination_by structural c; done means the cases form works like match or reports a clearer explanation of the limitation.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.