61 lines
1.6 KiB
Text
61 lines
1.6 KiB
Text
/-!
|
|
Terms are often duplicated in lean. One example is default arguments
|
|
referring to earlier ones; observed in the wild with `Array.foldl` and friends.
|
|
|
|
Ideally, compiling a recursive definition will still only consider such a recursive call once.
|
|
-/
|
|
|
|
def dup (a : Nat) (b : Nat := a) := a + b
|
|
|
|
namespace TestingFix
|
|
|
|
def rec : Nat → Nat
|
|
| 0 => 1
|
|
| n+1 => dup (dup (dup (rec n)))
|
|
decreasing_by trace "Tactic is run (ideally only once)"; decreasing_tactic
|
|
|
|
end TestingFix
|
|
|
|
namespace TestingGuessLex
|
|
|
|
-- GuessLex should run the tactic an extra time, that is expected
|
|
def rec : Nat → Nat → Nat
|
|
| 0, _m => 1
|
|
| n+1, m => dup (dup (dup (rec n (m + 1))))
|
|
decreasing_by trace "Tactic is run (ideally only twice)"; decreasing_tactic
|
|
|
|
end TestingGuessLex
|
|
|
|
|
|
namespace Subcontext
|
|
|
|
set_option linter.unusedVariables false
|
|
|
|
-- Now with a duplication into another context
|
|
-- We thread through `x` so that we can make the context mention something
|
|
-- that appears in the goal, else `mvarId.cleanup` will remove it
|
|
def dup2 (x : Nat) (a : Nat) (b : x ≠ x → Nat := fun h => a) := a
|
|
|
|
namespace TestingFix
|
|
def rec : Nat → Nat
|
|
| 0 => 1
|
|
| n+1 => dup2 n (rec n)
|
|
decreasing_by
|
|
trace "Tactic is run (ideally only once, in most general context)"
|
|
trace_state
|
|
decreasing_tactic
|
|
|
|
end TestingFix
|
|
|
|
namespace TestingGuessLex
|
|
|
|
-- GuessLex should run the tactic an extra time, that is expected
|
|
def rec : Nat → Nat → Nat
|
|
| 0, _m => 1
|
|
| n+1, m => dup2 n (rec n (m + 1))
|
|
decreasing_by
|
|
trace "Tactic is run (ideally only twice, in most general context)"
|
|
trace_state
|
|
decreasing_tactic
|
|
|
|
end TestingGuessLex
|