Skip to content

Infinite recursion is not catched by the compiler. #70727

Open
@wdanilo

Description

@wdanilo

Hi, consider this code:

#![deny(unconditional_recursion)]

struct Object {
    
}

impl Object {
    // RENAME HERE:
    fn foo(&self) -> f32 {
        7.0
    }
}

impl ToObject for Object {
    fn to_object(&self) -> &Object {
        self
    }
}

trait ToObject {
    fn to_object(&self) -> &Object;
}


trait ObjectOps : ToObject {
    fn foo(&self) -> f32 {
        self.to_object().foo()
    }
}

impl<T:ToObject> ObjectOps for T {}

fn main() {
    let x = Object{};
    println!("{}",x.foo());
}

It works fine. Let's rename foo to foo2 next to the comment "RENAME HERE". What happens is that this code has infinite recursion now and rustc doesn't report any error nor warning despite the usage of #![deny(unconditional_recursion)].

This is a serious problem, as a simple refactoring can cause something like that and it is very, very hard to debug, especially on WASM platform, where infinite recursion can just return a random number (it is UB). This problem could be solvable if I was able to write somehow MAGIC::Object::foo(self.to_object()) instead of self.to_object().foo() but in such a way, that the methods from ObjectOps would not be visible in MAGIC::Object. Currently, when refactoring such code we can get infinite recursion and spend hours debugging it :(

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.T-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