Skip to content
Tech News
← Back to articles

Tail-Call Interpreters in Rust – Jimmy Ostler

read original more articles
Why This Matters

This article explores the implementation of tail-call interpreters in Rust, highlighting how tail-call optimization can reduce stack usage during recursion, which is especially beneficial for functional programming languages. By benchmarking different VM dispatch styles, it demonstrates Rust's capabilities in efficiently handling interpreters and virtual machines, offering insights valuable for both language developers and performance-focused applications.

Key Takeaways

Tail-Call Interpreters in Rust - Jimmy Ostler

Tail-Call Interpreters in Rust

01 Aug 2026 Jimmy Ostler Word Count: 1636 Reading Time: 9 Min

Recently, I came across this post about different styles of VM dispatch as I was searching for ways to improve my ternary project. I had heard of tail-call interpretation, though my original source of inspiration took some time for me to re-find. This post, however, gave an excellent breakdown about several different styles of VM dispatch in Scala. I decided to implement these in Rust (including several variations more relevant to my project) as a fun experiment, and benchmark them to measure how they differ. I'll go over 2 versions - one, meant to emulate Noel's Scala, the other, meant to utilize Rust's strengths with a more complicated and traditional register machine.

Tail-Calls

Tail-call interpretation refers to the technique where some recursion can be turned into a jump during compilation, removing the need to allocate a new stack frame. It's extremely useful for functional languages to keep stack sizes down, such as Scala, but most compilers tend to use it. If you want to learn more, I highly recommend checking out Noel's excellent article above. When compiling with high optimization, Rust also performs this, and the unstable feature explicit_tail_calls lets us directly tell the compiler to perform the optimization or error.

Stack Machine (Noel's Machine)

The simplest machine we can easily work with here is a stack machine with 5 instructions, represented in Rust as so:

enum ByteCode { Lit ( f64 ), Add , Sub , Mul , Div }

Essentially identical to Noel's Scala. Since this is a stack machine, the Lit (literal) instruction pushes a value on the stack; arithmetic instructions pop their operands, and push the resulting value back onto the stack.

... continue reading