-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Description
Today I hit a segfault caused by stack overflow that wasn't caught by the compiler. This only occurred in debug mode, not release.
Current Behavior
The cause was the following piece of code, which passes the compiler without emitting any warnings:
use std::fmt::{self, Display};
struct Foo;
impl Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self, f)
}
}As would be obvious to most people carefully reviewing this code, there's a clear case of unconditional recursion happening. We pass &self to the same impl over and over.
Expected behavior
A similar case is already caught by the compiler: passing self rather than &self to the same impl. This triggers the "unconditional recursion" warning. I would've expected the &self case to hit the same warning.
use std::fmt::{self, Display};
struct Foo;
impl Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(self, f)
}
}warning: function cannot return without recursing
--> src/lib.rs:6:5
|
6 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
7 | Display::fmt(self, f)
| --------------------- recursive call site
|
= note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purposeIt'd be nice if the &self case would also emit diagnostics when detecting infinite recursion. Seeing a segfault occur in your program can be pretty scary. Added to that it wasn't triggering for us in release mode, and searching for "debug stack overflow rust" yields some pretty poor results (because "stack overflow" is also the name of a popular website, heh).
This seems like a case where we could probably use better diagnostics. Thanks!