becomeKeyword
Explanation
become has been reserved since the 2015 edition, but unlike most of its
neighbors in the
Rust Reference's reserved-keyword list,
it has genuine forward momentum: it's earmarked for guaranteed
tail-call elimination. The idea is become f(x) as an explicit,
distinct alternative to return f(x) — one that promises the compiler
will reuse the current stack frame for the call to f rather than
pushing a new one, so a chain of become calls runs in constant stack
space no matter how deep the logical recursion goes. A plain
return f(x) never carries that guarantee today; the compiler may
perform tail-call optimization as an implementation detail, but nothing
in the language lets you require or rely on it.
This is an active area of work: there is an experimental nightly
implementation gated behind #![feature(explicit_tail_calls)] that uses
exactly this become syntax, developed alongside ongoing design
discussion about the guarantees such a construct would need (matching
argument/return types between caller and callee, restrictions inside
unsafe blocks with live destructors, and so on). None of this is stable,
and the shape could still change before (if) it stabilizes — but this
reservation is much closer to "future feature in progress" than the
purely speculative entries like do or final.
Using become as an ordinary identifier is a compile error today. The
raw-identifier form r#become is legal, the same escape hatch every
reserved keyword offers.
Usage examples
Using the raw-identifier escape hatch
let become = 5; // error: expected identifier, found reserved keyword `become`
let r#become = 5; // ok: the raw-identifier form escapes the reservation
Boxing and heap allocation
A recursive function walking a linked structure is exactly the case
become targets: written naturally, each recursive call adds a stack
frame, so a long enough chain risks a stack overflow. Today's real
workaround is to rewrite the recursion as an explicit loop.
struct Node {
value: i64,
next: Option<Box<Node>>,
}
// Today's real alternative: an explicit loop, not recursion.
fn sum(mut node: Option<&Node>) -> i64 {
let mut total = 0;
while let Some(n) = node {
total += n.value;
node = n.next.as_deref();
}
total
}
Without a stable tail-call guarantee, a recursive
version of sum (n.value + sum(n.next.as_deref())) has no promise of
constant stack usage, so idiomatic Rust today reaches for the loop form
instead of trusting the optimizer; become, if stabilized, would let the
recursive form itself carry that guarantee instead of requiring the
manual rewrite.