Search code examples
f#tail-recursiontail-call-optimization

What reasoning lead to `Sequence expression containing recursive definition is compiled incorrectly`


The question Stack overflow despite tail call position but only in 64-bit lead to uncovering a bug in the F# compiler.

After reading the answer I am curious as to the reasoning that lead to finding the bug as I would like to better improve my skills at resolving problems and understanding TCO.


Solution

  • My reasoning was something like this:

    Talking about "tail calls" when looking at a computation expression can be misleading - in general there really isn't such a thing (see e.g. this other answer for one related discussion, though not related to sequence expressions).

    So calling gauss will not itself ever overflow the stack, only the code iterating through it could make it overflow. But once I saw that the calling code was just something like Seq.nth, that meant that there was almost certainly a compiler bug, because the pattern of "tail yield!ing" in a sequence expression is supposed to get optimized (not sure if this is part of the spec, but I think it's fairly well known). So then it was just a case of seeing what parts of the initial repro were necessary.

    Replacing loop in the original code with a non-recursive definition made the repro stop failing, as did removing the pattern match. I didn't find looking at the IL helpful (there's so much compiler-generated machinery involved in the compilation of sequence expressions), I just tried minimizing the repro at the source level and empirically testing the behavior.