Tail Calls in Rust

The main transformation to enable tail calls is to replace the function call f with a goto, calling destructors on local variables, then replacing the original arguments of the current function with the arguments of f. The normal borrow semantics for the return should therefore apply.

A tail call is only valid if there is nothing to be done in the caller after the call. This implementation checks this by first creating a node for become in HIR, then later, in MIR, checks that the “basic block being branched into” either “has length zero” or “terminates with a return.” I assume that this “basic block being branched into” contains whatever follows the become statement, and branches to another basic block if there’s anything more to do after the become; otherwise falling into the cases mentioned.

Also notes the main reason tail calls haven’t been implemented yet: portability. They’re not supported in several targets, like WebAssembly, which is something that the Rust developers apparently won’t tolerate.