In Rust, one often sees functions that take &str
as a parameter.
fn foo(bar: &str) {
println!("{}", bar);
}
When calling functions like this, it is perfectly fine to pass in a String
as an argument by referencing it.
let bar = String::from("bar");
foo(&bar);
Strictly speaking, the argument being passed is an &String
and the function is expecting an &str
, but Rust (as one would hope) just figures it out and everything works fine. However, this is not the case with match statements. If I try and use the same bar
variable as before in a match statement, the naive usage will not compile:
match &bar {
"foo" => println!("foo"),
"bar" => println!("bar"),
_ => println!("Something else")
};
Rustc complains that it was expecting an &str
but received an &String
. The problem and solution are both very obvious: just borrow bar
more explicitly with .as_str()
. But this brings me to the real question: why is this the case?
If Rust can figure out that an &String
trivially converts to an &str
in the case of function arguments, why can't it do the same thing with match statements? Is this the result of a limitation of the type system, or is there hidden unsafety in fancier borrowing with match statements? Or is this simply a case of a quality of life improvement getting integrated into some places but not others? I'm sure someone knowledgeable about type systems has an answer, but there seems to be very little information about this little quirk of behavior on the internet.