Stack overflow in fmt::Display impl

217b739
Opened by Brian Martin at 2025-04-01 10:18:14

It's possible to write a impl of fmt::Display which compiles successfully and produces a stack overflow.

A minimal repro is available here: https://play.rust-lang.org/?gist=fb115e1e625e1b8038cdd13c5f9cdbb8&version=stable

The code is here for completeness of the bug report:

use std::fmt;

fn main() {
    println!("Hello, world!");
    let test = Test::Alpha;
    println!("Preparing to stack overflow");
    let test_string = test.to_string();
    println!("test string: {}", test_string);
}

pub enum Test {
  Alpha,
  Bravo,
}

impl fmt::Display for Test {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", self.to_string())
  }
}

I would expect an error at compile time

Instead the error occurs at runtime as a stack overflow.

Meta

rustc 1.21.0 (3b72af97e 2017-10-09)
binary: rustc
commit-hash: 3b72af97e42989b2fe104d8edbaee123cdf7c58f
commit-date: 2017-10-09
host: x86_64-apple-darwin
release: 1.21.0
LLVM version: 4.0
thread 'main' has overflowed its stack
fatal runtime error: stack overflow
Abort trap: 6
  1. Rust does not emit any compiler error for stack overflow, except the very simple ones like fn f() { f(); }. The following will blow the stack without any warnings or errors as well:

    fn f() {
        g();
    }
    fn g() {
        f();
    }
    fn main() {
        f();
    }
    

    kennytm at 2017-11-07 17:50:57

  2. I think the interesting thing about this one is that ToString isn't implemented for the enum, except by having the impl for fmt::Display. Maybe this makes it easier to detect and throw an error?

    Brian Martin at 2017-11-07 18:08:02

  3. Marking as E-hard since this requires not just a fix for https://github.com/rust-lang/rust/issues/57965, but also a complete rewrite of the formatting infrastructure to avoid dynamic dispatch

    Jonas Schievink at 2020-08-10 23:13:18