Reputation: 11477
I implemented the trait Foo
for &'a str
, but when I call the method test
for std::string::String
, it works. I checked my code and I'm sure that I don't implement the trait for String
, so does the Rust compiler convert String
to str
implicitly?
The code likes this:
pub trait Foo {
fn test(self) -> String;
}
impl<'a> Foo for &'a str {
fn test(self) -> String {
String::from("da")
}
}
fn main() {
let s = String::from("123456789");
println!("{}", s.test());
}
The Rust plugin for the Jetbrains IDE can't find test
method for String
, but it works well.
Why does that code work?
Upvotes: 0
Views: 214
Reputation: 19662
First off, careful. String
!= CString
. And s.test(var)
will not yield anything but an error since your test
method takes no parameter but self
.
Now, on to what is actually happening.
When you define an extension method like you did by defining a trait then implementing it for &_ str
but not on String
, and then try to invoke it, the compiler implicitly does the dereferencing (since String
implements Deref
into &_ str
).
As a result, your main
function can be written for clarity as:
fn main() {
let s = String::from("123456789");
println!("{}", (s.deref()).test());
}
and is entirely analogous to what the compiler does under-the-hood. The compiler essentially saw that you were trying to use this, and did so for you.
I need to warn you, though - your code is extremely weird in multiple ways:
Deref
counterpart, precisely to avoid this level of indirectionA much better, and less indirect way to write it, is as follows:
pub trait Foo {
fn test(&self) -> String;
}
impl Foo for str {
fn test(&self) -> String {
String::from("da")
}
}
fn main() {
let s = String::from("123456789");
println!("{}", s.test());
}
You are not sacrificing anything, the functionality remains identical, but:
deref
callUpvotes: 3