error[E0277]: the trait bound `Box<dyn AsRef<str>>: AsRef<str>` is not satisfied
--> src/main.rs:6:22
|
6 | let iterator = hello(o);
| ----- ^ the trait `AsRef<str>` is not implemented for `Box<dyn AsRef<str>>`
| |
| required by a bound introduced by this call
|
= help: the trait `AsRef<T>` is implemented for `Box<T, A>`
note: required by a bound in `hello`
--> src/main.rs:1:18
|
1 | fn hello(t: impl AsRef<str>) -> impl Iterator<Item=u8> {
| ^^^^^^^^^^ required by this bound in `hello`
Unless you meant to change the signature of hello?
impl Trait in argument position is equivalent to a generic type parameter.
impl Trait in return position is nothing but a concrete type hidden behind a black box that only lets you use methods from the specified trait (a so-called "existential type").
Neither of these involves dynamic dispatch in itself. dyn Trait is another implementation of the idea of an existential type, but this doesn't mean that it would be the same as return-position impl Trait.
Does it mean that at the callsite, if the caller passes values of concrete types as arguments to the hello function, Rust will do static dispatch, i.e. monomorphization, over all the concrete types passed into hello?
And a related question is, if a trait object is passed as an argument to hello, will Rust do dispatch dispatch over it at runtime?
Yes, fn hello(t: impl AsRef<str>) is the same as fn hello<T: AsRef<str>>(t: T) except that you aren't allowed to turbofish the type (but that's merely a syntactic difference).
I can't really interpret that question. A trait object does always involve dynamic dispatch. (At least conceptually, ignoring optimizations.)
If you pass a trait object to hello, then hello will be monomorphized with the (hidden) type parameter equal to the type of the trait object, e.g. &dyn AsRef<str>, which is itself a concrete type. The trait object will then forward to the underlying concrete type using dynamic dispatch, as always.
There's nothing special happening here. There is no distinguished interaction between generics and trait objects. It's just a composition of how the individual features work separately.
I get it now @H2CO3, you're saying function dispatching over generic type parameters has nothing (at least conceptually) to do with using impl Trait in both the type specifications of function parameter and return type.
On the contrary. impl Trait in argument position is almost exactly the same as a generic type parameter except for the the aforementioned minor syntactic caveat.
What I was saying is that trait objects have nothing to do with that.
Trait objects are dyn Trait types. impl Trait is not a trait object.