lean4-htt/tests/lean/termination_by.lean
Joachim Breitner fb0c46a011
feat: termination_by structural (#4542)
This implements the `termination_by structural` syntax proposed in
#3909.

I went with `termination_by structural` over, say,
`termination_by (config := {method := .structural})` mainly because it
was
easier to get going (otherwise I’d have to look into how to define
recursive
parsers, as `Parser.config` depends on `term` and `termination_by` is
part of
term. But also because I find it more ergonomic and aesthetic as a user.
But syntax can still change.

The `termination_by?` syntax will no longer force well-founded
recursion,
and instead the inferred `termination_by structurally` annotation will
be shown
if structural termination is possible.

While I was it, this fixes #4546 the easy way (log errors about but
otherwise
ignore incomplete `termination_by` sets for mutual recursion). Maybe we
get
multiple replacements (#4551), but even then this this good behavior.

Involves a bit of shuffling around `TerimationHints` (now validated for
a
clique already by `PreDefinition.main`) and `TerminationArguments` (now
lifted
out of the `WF` namespace, and a bit simplified).

Fixes #3909

---------

Co-authored-by: Richard Kiss <him@richardkiss.com>
2024-07-01 16:51:30 +00:00

166 lines
3.6 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-!
This module tests various mis-uses of termination_by and decreasing_by:
* use in non-recursive functions
* that all or none of a recursive group have termination_by.
* mismatched structural/non-structural
-/
def nonRecursive1 (n : Nat) : Nat := n
termination_by n -- Error
def nonRecursive2 (n : Nat) : Nat := n
decreasing_by sorry -- Error
def nonRecursive3 (n : Nat) : Nat := n
termination_by n -- Error
decreasing_by sorry
partial def partial1 (n : Nat) : Nat := partial1 n
termination_by n -- Error
partial def partial2 (n : Nat) : Nat := partial2 n
decreasing_by sorry -- Error
partial def partial3 (n : Nat) : Nat := partial3 n
termination_by n -- Error
decreasing_by sorry
unsafe def unsafe1 (n : Nat) : Nat := unsafe1 n
termination_by n -- Error
unsafe def unsafe2 (n : Nat) : Nat := unsafe2 n
decreasing_by sorry -- Error
unsafe def unsafe3 (n : Nat) : Nat := unsafe3 n
termination_by x -- Error
decreasing_by sorry
unsafe def withWhere (n : Nat) : Nat := foo n
where foo (n : Nat) := n
termination_by n -- Error
unsafe def withLetRec (n : Nat) : Nat :=
let rec foo (n : Nat) := n
termination_by n -- Error
foo n
mutual
def rec : Nat → Nat
| 0 => 0
| n+1 => rec n + notrec n
termination_by x => x
def notrec (n : Nat) : Nat := n
termination_by n -- Error
end
mutual
def isEven : Nat → Bool
| 0 => true
| n+1 => isOdd n
termination_by x => x -- Error
def isOdd : Nat → Bool
| 0 => false
| n+1 => isEven n
termination_by? -- still works
end
namespace Test
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by n _ _ => n -- Error
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => i n a b
def i : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
end
end Test
namespace Test2
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
termination_by structural n _ _ => n
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by n _ _ => n -- Error
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
termination_by n _ _ => n
end
end Test2
namespace Test3
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
termination_by n _ _ => n
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by structural n _ _ => n -- Error
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
termination_by structural n _ _ => n
end
end Test3
namespace Test4
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
termination_by n _ _ => n
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by n _ _ => n
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
termination_by structural n _ _ => n -- Error
end
end Test4
namespace Test5
mutual
def f : Nat → ααα
| 0, a, b => a
| n+1, a, b => g n a b |>.1
termination_by structural n _ _ => n
def g : Nat → αα → (α × α)
| 0, a, b => (a, b)
| n+1, a, b => (h n a b, a)
termination_by structural n _ _ => n
decreasing_by sorry -- Error
def h : Nat → ααα
| 0, a, b => b
| n+1, a, b => f n a b
termination_by structural n _ _ => n
end
end Test5