How can I call Struct::func when Trait::func exists?

I tried to define fn to_str(&self) -> Option<&str> as a trait method to make a function able to receive &OsStr, OsString, &str or String as a parameter s: impl ToStr.

I defined the following ToStr trait:

use std::ffi::OsString;

trait ToStr {
    fn to_str(&self) -> Option<&str>;
}

impl ToStr for OsString {
    fn to_str(&self) -> Option<&str> {
        // warning: function cannot return without recursing
        // self.to_str()

        // warning: function cannot return without recursing
        // OsString::to_str(self)

        // warning: function cannot return without recursing
        // Self::to_str(self)

        // error[E0404]: expected trait, found struct `OsString`
        // <Self as OsString>::to_str(self)
    }
}

fn f(s: impl ToStr) {
    dbg!(s.to_str());
}

fn main() {
    f(OsString::new());
}

How can I resolve the recursion problem? I want to call the to_str method, which is an associated function of OsString.

To be more precise, you want to call to_str on OsStr, not on OsString. (OsString implements Deref<Target = OsStr>, which is probably why you thought that OsString has a .to_str() method). I don't remember the exact procedure by which a .method() call is resolved, but there is a well-defined order in which things are checked... and I assume that the compiler is correctly telling you that calling the trait method takes precedence over dereferencing self and then calling an inherent method.

How about (**self).to_str()? Or maybe just (*self).to_str() is enough, idk, but I know the first one should work.

Here's a resource that might be helpful: Method call resolution in Rust for type parameters · GitHub

Under that explanation, T = &OsString is added in step 1. Then, OsString is added in step 2/3, then those steps are repeated and OsStr is added. Later, &OsStr is added in step 5.

The end result is that inherent methods whose self type is &OsString have the highest priority, but trait methods whose self type is &OsString still have priority over any sort of method whose self type is &OsStr.

Thanks, I confirmed that (*self).to_str() doesn't work and (**self).to_str() and OsStr::to_str(self) work.

// warning: function cannot return without recursing
// (*self).to_str();

// These calls work!
(**self).to_str();
OsStr::to_str(self);

Qualified paths are another way to disambiguate.