Should complain?


#1

Why doesn’t rust complain about this?

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

#2

It looks like format_args!() has a special case for being used with just one argument.


#3

It caused a stack overflow because I reckoned it would use the debug version for MyType


#4

Ahh, I see. to_string() is implemented using Display, so this is infinite recursion. I guess the compiler should warn about that.


#5

Hi,
What I didn’t see in your code, is what “MyType” is. Then what is rustc complaining about. In other words, the error message you are getting.

The code below show an example:

use std::fmt;

struct Person {
    age: u32,
    name: &'static str,
}

impl fmt::Display for Person {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.age, self.name.to_lowercase().to_String()) // check this
    }
}

fn main() {
    
    let p = Person{age: 34, name: "tomi"};
    println!("{}", p);  // prints 34 tomi
}

#6

If you look at my example I am not calling to_string on a field but on the type itself


#7

Unfortunately, this is untrue. self is a parameter and Self is a type. self.to_string would be declared with a self parameter like so:

impl MyType {
    fn to_string(self) -> String {/**/}
}

while Self::to_string would be declared like this:

impl MyType {
    fn to_string() -> String {/**/} 
}

So, you probably meant that you were calling it on an instance of Self


#8

However, I was talking about self.to_string() because that is what I wrote in my example.

And that is the problem, without Display there would be no to_string() method (not associated function) so this is a infinite recursion.


#9

Ah, sorry I must’ve misunderstood the context, your implementation of std::string::ToString is dependent on Display and therefore causes a stack overflow.


#10

Yes, maybe the fix could be that which implementating a trait the provided functions are not available. But I don’t know if that is enough?

Sebastian Malton


#11

Apart from that, another thing am also pointing out in your code example is how you are using write!(...)


#12

Oh, you mean not using "{}"? Fair


#13

But people sometimes want to employ finite recursion. Also, why should trat impls be treated differently than normal impls? The user can make infinite recursions on both alike. And trying to know if a recursion is finite is impossible in general.


#14

Because the rust compiler already complains of direct infinite recursion.

Sebastian Malton


#15

Yep, Rust does not see infinite recursion when traits and generics are involved.


#16

The infinite recursion lint is limited to cases where a function directly calls itself. Also see https://github.com/rust-lang/rust/issues/57965