# Pre-RFC: explicit proper tail calls

**URL:** <https://internals.rust-lang.org/t/pre-rfc-explicit-proper-tail-calls/3797>\
**Category:** language design\
**Created:** [August 1, 2016, 10:35pm UTC](https://internals.rust-lang.org/t/pre-rfc-explicit-proper-tail-calls/3797 "2016-08-01T22:35:45Z")\
**Posts on this page:** 1\
**Showing post:** 16

<div class="post-metadata">

**Author:** ![dobenour](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dobenour/32/7241_2.png) [@dobenour](https://internals.rust-lang.org/u/dobenour)\
**Post date:** [November 29, 2016, 11:45pm UTC](https://internals.rust-lang.org/t/pre-rfc-explicit-proper-tail-calls/3797/16 "2016-11-29T23:45:00Z")

</div>

This would be emitted to LLVM `musttail` where possible, or to `tail` otherwise. LLVM does actually emit a tail call for `tail` in most cases; the remaining cases would become bugs that should eventually be fixed.

I do think that allowing a cast (either `as` or `std::mem::transmute` – the latter only in unsafe code, obviously, and only where compilable) of the return value would be valuable, but it can wait.

I think that `become` should be allowed almost anywhere that `return` currently is. `become` on an expression tries to tail-call the last operator in the expression. (While somewhat unusual, this can be useful due to operator overloading.). `become` on an `if` or `match` statement behaves as if propagated into each arm of the statement.

Your example would be written as:

```rust
fn fact_a(n: i32, a: i32) -> i32 {
    if n == 0 { a } else { become fact_a(n - 1, n * a) }
}

```

I am not sure whether this code should be accepted.

```rust
fn fact_a(n: i32, a: i32) -> i32 {
    become if n == 0 { a } else { fact_a(n - 1, n * a) }
}

```

The main problem with accepting it is figuring out where the locals of `fact_a` get dropped.

The reason the drop logic is needed is code like this:

```rust
fn id<a, b>(x: a, y: &mut b) -> a {
    x
}

fn foo<a>(x: Vec<a>, y: bool) -> Vec<a> {
    if y {
        x
    } else {
        let bar = ();
        let baz = Box::new(());
        become id(x, &mut bar)
    }
}

```

Here:

- passing `x` to `id` is fine, since ownership of `x` is transferred to `id`.
- Having `baz` in scope is okay, since it is not used after the tail call is made. But it cannot be dropped after `id` returns, since `foo`'s stack frame got clobbered. So it must be dropped _before_ jumping to `id`.
- Passing `&mut bar` is not okay – it refers to an address in `foo`'s stack frame, which was overwritten by `id`'s.

If the `become` had been omitted, this would have been valid code, since `bar` would last until `foo` returned. But if we declared that all locals were dropped before the `become`, then `x` would have been destroyed before being passed to `id`.

---

_[View the full topic](https://internals.rust-lang.org/t/pre-rfc-explicit-proper-tail-calls/3797)._
