lean4-htt/tests/lean/guessLexFailures.lean.expected.out
Joachim Breitner f45c19b428
feat: identify more fixed parameters (#7166)
This PR extends the notion of “fixed parameter” of a recursive function
also to parameters that come after varying function. The main benefit is
that we get nicer induction principles.


Before the definition

```lean
def app (as : List α) (bs : List α) : List α :=
  match as with
  | [] => bs
  | a::as => a :: app as bs
```

produced

```lean
app.induct.{u_1} {α : Type u_1} (motive : List α → List α → Prop) (case1 : ∀ (bs : List α), motive [] bs)
  (case2 : ∀ (bs : List α) (a : α) (as : List α), motive as bs → motive (a :: as) bs) (as bs : List α) : motive as bs
```
and now you get
```lean
app.induct.{u_1} {α : Type u_1} (motive : List α → Prop) (case1 : motive [])
  (case2 : ∀ (a : α) (as : List α), motive as → motive (a :: as)) (as : List α) : motive as
```
because `bs` is fixed throughout the recursion (and can completely be
dropped from the principle).

This is a breaking change when such an induction principle is used
explicitly. Using `fun_induction` makes proof tactics robust against
this change.

The rules for when a parameter is fixed are now:

1. A parameter is fixed if it is reducibly defq to the the corresponding
argument in each recursive call, so we have to look at each such call.
2. With mutual recursion, it is not clear a-priori which arguments of
another function correspond to the parameter. This requires an analysis
with some graph algorithms to determine.
3. A parameter can only be fixed if all parameters occurring in its type
are fixed as well.
This dependency graph on parameters can be different for the different
functions in a recursive group, even leading to cycles.
4. For structural recursion, we kinda want to know the fixed parameters
before investigating which argument to actually recurs on. But once we
have that we may find that we fixed an index of the recursive
parameter’s type, and these cannot be fixed. So we have to un-fix them
5. … and all other fixed parameters that have dependencies on them.

Lean tries to identify the largest set of parameters that satisfies
these criteria.

Note that in a definition like
```lean
def app : List α → List α → List α
  | [], bs => bs
  | a::as, bs => a :: app as bs
```
the `bs` is not considered fixes, as it goes through the matcher
machinery.


Fixes #7027
Fixes #2113
2025-03-04 22:26:20 +00:00

159 lines
5.8 KiB
Text

guessLexFailures.lean:9:4-9:18: error: fail to show termination for
nonTerminating
with errors
failed to infer structural recursion:
Cannot use parameter #1:
failed to eliminate recursive application
nonTerminating n.succ m.succ
Cannot use parameter #2:
failed to eliminate recursive application
nonTerminating n.succ m.succ
Could not find a decreasing measure.
The basic measures relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
x1 x2
1) 11:12-46 ? ?
Please use `termination_by` to specify a decreasing measure.
guessLexFailures.lean:15:0-18:31: error: Could not find a decreasing measure.
The basic measures relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
x1 x2
1) 17:12-47 ? ?
Please use `termination_by` to specify a decreasing measure.
guessLexFailures.lean:20:4-20:15: error: fail to show termination for
noArguments
with errors
failed to infer structural recursion:
no parameters suitable for structural recursion
well-founded recursion cannot be used, 'noArguments' does not take any (non-fixed) arguments
guessLexFailures.lean:22:4-22:23: error: fail to show termination for
noNonFixedArguments
with errors
failed to infer structural recursion:
Not considering parameter n of noNonFixedArguments:
it is unchanged in the recursive calls
no parameters suitable for structural recursion
well-founded recursion cannot be used, 'noNonFixedArguments' does not take any (non-fixed) arguments
guessLexFailures.lean:27:0-33:31: error: Could not find a decreasing measure.
The basic measures relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
n m l
1) 29:6-25 = = =
2) 30:6-23 = < _
3) 31:6-23 < _ _
Please use `termination_by` to specify a decreasing measure.
guessLexFailures.lean:37:0-43:31: error: Could not find a decreasing measure.
The basic measures relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
n m x3
1) 39:6-27 = = =
2) 40:6-25 = < _
3) 41:6-25 < _ _
Please use `termination_by` to specify a decreasing measure.
guessLexFailures.lean:48:0-54:31: error: Could not find a decreasing measure.
The basic measures relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
n m l
1) 50:6-25 = = =
2) 51:6-23 = < _
3) 52:6-23 < _ _
Please use `termination_by` to specify a decreasing measure.
guessLexFailures.lean:59:6-59:7: error: fail to show termination for
Mutual.f
Mutual.g
Mutual.h
with errors
failed to infer structural recursion:
Not considering parameter fixed of Mutual.f:
it is unchanged in the recursive calls
Not considering parameter fixed of Mutual.g:
it is unchanged in the recursive calls
Not considering parameter fixed of Mutual.h:
it is unchanged in the recursive calls
Too many possible combinations of parameters of type Nat (or please indicate the recursive argument explicitly using `termination_by structural`).
Skipping arguments of type True, as Mutual.f has no compatible argument.
Could not find a decreasing measure.
The basic measures relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
Call from Mutual.f to Mutual.f at 61:8-33:
n m l
= = =
Call from Mutual.f to Mutual.f at 62:8-31:
n m l
= < <
Call from Mutual.f to Mutual.g at 63:8-39:
n m l
n < ? ?
m ? = ?
l ? ? <
Call from Mutual.g to Mutual.g at 68:8-35:
n m l
? ? =
Call from Mutual.g to Mutual.g at 69:8-33:
n m l
_ _ <
Call from Mutual.g to Mutual.h at 70:8-27:
n m l
n _ _ ?
m _ _ ?
Call from Mutual.h to Mutual.f at 75:8-33:
n m
n _ _
m _ _
l _ _
Call from Mutual.h to Mutual.h at 76:8-27:
n m
_ _
Call from Mutual.h to Mutual.h at 77:8-27:
n m
_ _
Please use `termination_by` to specify a decreasing measure.
guessLexFailures.lean:87:4-87:5: error: fail to show termination for
DuplicatedCall.f
with errors
failed to infer structural recursion:
Cannot use parameter #1:
failed to eliminate recursive application
DuplicatedCall.f (n + 2) (m + 1)
Cannot use parameter #2:
failed to eliminate recursive application
DuplicatedCall.f (n + 2) (m + 1)
Could not find a decreasing measure.
The basic measures relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
n m
1) 89:19-32 ? ?
Please use `termination_by` to specify a decreasing measure.
guessLexFailures.lean:100:0-103:31: error: Could not find a decreasing measure.
The basic measures relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
n m
1) 101:83-105 ? ?
Please use `termination_by` to specify a decreasing measure.
guessLexFailures.lean:113:14-113:31: error: failed to prove termination, possible solutions:
- Use `have`-expressions to prove the remaining goals
- Use `termination_by` to specify a different well-founded relation
- Use `decreasing_by` to specify your own tactic for discharging this kind of goal
n✝ m n : Nat
⊢ n < n✝
guessLexFailures.lean:119:0-123:31: error: Could not find a decreasing measure.
The basic measures relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
n m
1) 121:31-54 ? ?
Please use `termination_by` to specify a decreasing measure.
guessLexFailures.lean:131:14-131:31: error: failed to prove termination, possible solutions:
- Use `have`-expressions to prove the remaining goals
- Use `termination_by` to specify a different well-founded relation
- Use `decreasing_by` to specify your own tactic for discharging this kind of goal
m n✝ n : Nat
⊢ n < n✝ + 1