Why can this code not compile? Shouldn’t I be able to pass &str
as parameter here?
struct S<T: AsRef<str>>{
t: T
}
fn bar<T: AsRef<str>>(t: T) -> S<T>{
S{t}
}
fn foo<T: AsRef<str>>(t: T) -> S<T> {
bar("b")
}
fn main() {
foo("a");
}
Error:
error[E0308]: mismatched types
--> src/main.rs:10:9
|
9 | fn foo<T: AsRef<str>>(t: T) -> S<T> {
| - this type parameter
10 | bar("b")
| --- ^^^ expected type parameter `T`, found `&str`
| |
| arguments to this function are incorrect
|
= note: expected type parameter `T`
found reference `&'static str`
help: the return type of this call is `&'static str` due to the type of the argument passed
--> src/main.rs:10:5
|
10 | bar("b")
| ^^^^---^
| |
| this argument influences the return type of `bar`
note: function defined here
--> src/main.rs:5:4
|
5 | fn bar<T: AsRef<str>>(t: T) -> S<T>{
| ^^^ ----
>Solution :
Rust requires that generics typecheck correctly without having concrete types plugged in. (This is unlike C++.)
Look at foo
in detail but rename its template parameter to avoid confusion:
fn foo<U: AsRef<str>>(t: U) -> S<U> {
bar("b")
}
You call bar("b")
and return its result. bar("b")
instantiates to bar<&'static str>("b")
, which returns S<&static str>
, independently of what U
is.
This is not correct, because you have no guarantee that foo
needs to return a S<&static str>
, because you don’t control its template argument.
For example, if I were to call foo("a".to_string())
, I would instantiate foo<String>
, which returns S<String>
– and yet your implementation still tries to return a S<&'static str>
.
That’s why the compiler rejects your code beforehand.
The error message is unfortunately a bit misleading. You see, Rust deduces types both from arguments and also result usage.
Because you return the result of bar
from foo
, the compiler deduces that bar
needs to return S<U>
, and therefore bar
also needs to take a U
as the argument, but you’re passing a &'static str
, which may or may not be the same as U
. And so you get the type mismatch reported on the argument instead of the result.