Skip to content

Unwarned Trait recursion causes stack overflow #132588

Open
@aevyrie

Description

@aevyrie

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.C-enhancementCategory: An issue proposing an enhancement or a PR with one.L-false-negativeLint: False negative (should have fired but didn't).L-unconditional_recursionLint: unconditional_recursionT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions