I was looking at the Borrow<Borrowed>
trait in Rust, and I understand the idea that we want a generic function to allow an argument K
or its borrowed form Q
such that K: Borrow<Q>
. If I look at the String
implementation, I see that it implements Borrow<str>
, which explains why passing a &String
works in the following snippet. What I'm wondering is how can passing a &str
work: does that imply that str
implements ... Borrow<str>
? If not, how can a str
satisfy the traits of the given P
generic?
use std::borrow::Borrow;
use std::fmt::Display;
fn main() {
let foo = String::from("I'm a String");
print(&foo);
print("I'm a str");
}
fn print<P>(arg: &P)
where
P: Borrow<str> + ?Sized + Display
{
println!("{}", arg)
}
Yes, you can easily look up in the doc
impl<T> Borrow<T> for T where T: ?Sized,
This means for any type T
, Borrow<T>
is implemented for T
. where T: ?Sized
means that T
may be dynamically sized. If trait "bound" (more of a relaxation here) where T: ?Sized
were not added, then T
will not include dynamically sized types like str
or other slice types.