Idris2
Idris2 copied to clipboard
[ regression ] Totality checker no longer accepts certain total functions
Looks like this is a regression (?) introduced by #2953 . The following proof from idris2-algebra is no longer accepted by the totality checker. Using @-patterns seems not to work here either, and I'm currently uncertain how to proceed with this.
This is the function in question but I'll try to come up with a self-contained example later today. Note that this is currently blocking (amongst some other libraries probably failing for similar reasons) the generation of nightly pack collections.
-- Adding two sums via `add` preserves the evaluation result.
export
0 padd : (x, y : Sum a as) -> esum x + esum y === esum (add x y)
padd [] xs = r.plus.leftNeutral
padd (x :: xs) [] = r.plus.rightNeutral
padd (T f x :: xs) (T g y :: ys) with (compProd x y) proof eq
_ | LT = Calc $
|~ (f * epr x + esum xs) + (g * epr y + esum ys)
~~ (f * epr x) + (esum xs + (g * epr y + esum ys))
..< r.plus.associative
~~ f * epr x + esum (add xs (T g y :: ys))
... cong (f * epr x +) (padd xs (T g y :: ys))
_ | GT = Calc $
|~ (f * epr x + esum xs) + (g * epr y + esum ys)
~~ g * epr y + ((f * epr x + esum xs) + esum ys)
..< lemma213 r.plus.csgrp
~~ g * epr y + esum (add (T f x :: xs) ys)
... cong (g * epr y +) (padd (T f x :: xs) ys)
_ | EQ = case pcompProd x y eq of
Refl => Calc $
|~ (f * epr x + esum xs) + (g * epr x + esum ys)
~~ (f * epr x + g * epr x) + (esum xs + esum ys)
... lemma1324 r.plus.csgrp
~~ (f + g) * epr x + (esum xs + esum ys)
..< cong ( + (esum xs + esum ys)) r.rightDistributive
~~ (f + g) * epr x + esum (add xs ys)
... cong ((f + g) * epr x +) (padd xs ys)
I am fairly certain this is due to #2954. Prior to PR #2953, the termination checker was accepting some functions for the wrong reason, masking issue #2954.
I am currently preparing a refinement to the termination checker that represents size-graphs as matrices. It's still work-in-progress but idris2-algebra does seem to build. I'd be curious which other libraries no longer pass the termination checker.
I am fairly certain this is due to #2954. Prior to PR #2953, the termination checker was accepting some functions for the wrong reason, masking issue #2954.
I am currently preparing a refinement to the termination checker that represents size-graphs as matrices. It's still work-in-progress but idris2-algebra does seem to build. I'd be curious which other libraries no longer pass the termination checker.
Thanks for working on this. In that case I think I'll temporarily use assert_smaller in idris-algebra until your fix lands. I'll see what else in the pack collection fails. I'll report back here if anything interesting shows up.
I have now merged my changes to the termination checker. Unfortunately, they do not address this particular termination issue. The problem here is caused by the with-abstraction, see #403.
The program first deconstructs the Sum (T f x :: xs), for example, and then reconstructs it in the recursive call padd (T f x :: xs) ys. The recursive call appears under a with-abstraction so gets lifted to an auxiliary top-level function, which gets passed only the constituent parts of the Sum. As far as the termination checker is concerned, this generated function therefore increases the sizes of arguments f, x, xs by calling padd on (T f x :: xs).
There are two potential solutions to this: either we inline with-abstractions during size-graph generation, which is already done for lifted case-functions
https://github.com/idris-lang/Idris2/blob/a26766e57ac5466947903a626082e950ae84192e/src/Core/Termination/CallGraph.idr#L316-L321
or we start counting the number of constructors we strip off/add as part of the size graph. The latter is what Agda does according to @gallais but I suspect this approach will still struggle with deep pattern matches like the one above.
In the meantime, you could write the with-abstraction by hand but pass around the "full" Sum, not just its parts.