rust-lang / rust-lang/rust

Unwarned Trait recursion causes stack overflow

Open
#132,588 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-lints C-enhancement L-false-negative L-unconditional_recursion T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
pub trait Dog: Animal {}

pub trait Animal {
    fn speak(&self) {
        println!("Hey.");
    }
}

impl<D> Animal for D where D: Dog {
    fn speak(&self) {
        self.speak()
    }
}

pub struct Labrador;
impl Dog for Labrador {}

fn main() {
    Labrador.speak();
}
Current output
Errors
Exited with signal 6 (SIGABRT): abort program
Standard Error
   Compiling playground v0.0.1 (/playground)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.57s
     Running `target/debug/playground`

thread 'main' has overflowed its stack
fatal runtime error: stack overflow
Standard Output
Desired output
warning: function cannot return without recursing
 --> src/main.rs:4:5
  |
4 |     fn speak(&self) {
  |     ^^^^^^^^^^^^^^^ cannot return without recursing
5 |         self.speak();
  |         ------------ recursive call site
  |
Rationale and extra context

This class of error is properly caught and warned against in the simplest case: calling a trait method from within that same trait method. You can see this in the above code by replacing the blanket implementation with:

impl Animal for Labrador {
    fn speak(&self) {
        self.speak()
    }
}

Which results in the warning listed above in the "desired output".

What appears to be happening is that, because Dog is required to be Animal, calling self.speak() from within the blanket implementation is calling the Animal method on Dog - which takes precedence over calling the trait method we are currently in.

This code snippet is already seemingly tautological, and it isn't clear how the compiler is reasoning about this. A type implementing Dog must be an Animal, yet Labrador cannot have the Animal trait unless it is also a Dog!

Other cases

No response

Rust Version

I've been using rust playground for this: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e62693e73ead0c65f1b471f8eca6a43a

Using rust 1.82.0

Anything else?

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the reproducer in src/main.rs using Rust 1.82.0, and compare the blanket implementation with the direct Labrador implementation described in the issue. The fix should make the blanket-implementation recursion emit the cannot-return-without-recursing warning instead of overflowing the stack.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.