Answer: 11 Difficulty: 1 # Hint `Base::method` and `Derived::method` happen to have the same name but are otherwise unrelated methods. One does not override the other. # Explanation The two traits `Base` and `Derived` each define a trait method called `method`. These methods happen to have the same name but are otherwise unrelated methods as explained below. Both traits provide a default implementation of their trait method. Default implementations are conceptually copied into each trait impl that does not explicitly define the same method. In this case for example `impl Base for BothTraits` does not provide its own implementation of `Base::method`, which means the implementation of `Base` for `BothTraits` will use the default behavior defined by the trait i.e. `print!("1")`. Additionally, `Derived` has `Base` as a _supertrait_ which means that every type that implements `Derived` is also required to implement `Base`. The two trait methods are unrelated despite having the same name -- thus any type that implements `Derived` will have an implementation of `Derived::method` as well as an implementation of `Base::method` and the two are free to have different behavior. Supertraits are not inheritance! Supertraits are a constraint that if some trait is implemented, some other trait must also be implemented. Let's consider what happens in each of the two methods called from `main`. - `dynamic_dispatch(&BothTraits)` The argument `x` is a reference to the trait object type `dyn Base`. A _trait object_ is a little shim generated by the compiler that implements the trait with the same name by forwarding all trait method calls to trait methods of whatever type the trait object was created from. The forwarding is done by reading from a table of function pointers contained within the trait object. ```rust // Generated by the compiler. // // This is an implementation of the trait `Base` for the // trait object type `dyn Base`, which you can think of as // a struct containing function pointers. impl Base for (dyn Base) { fn method(&self) { /* Some automatically generated implementation detail that ends up calling the right type's impl of the trait method Base::method. */ } } ``` In the quiz code, `x.method()` is a call to this automatically generated method whose fully qualified name is `::method`. Since `x` was obtained by converting a `BothTraits` to `dyn Base`, the automatically generated implementation detail will wind up forwarding to `::method` which prints `1`. Hopefully it's clear from all of this that nothing here has anything to do with the unrelated trait method `Derived::method` defined by `BothTraits`. Especially notice that `x.method()` cannot be a call to `Derived::method` because `x` is of type `dyn Base` and there is no implementation of `Derived` for `dyn Base`. - `static_dispatch(BothTraits)` At compile time we know that `x.method()` is a call to `::method`. Type inference within generic functions in Rust happens independently of any concrete instantiation of the generic function i.e. before we know what `T` may be, other than the fact that it implements `Base`. Thus no inherent method on the concrete type `T` or any other trait method may affect what method `x.method()` is calling. By the time that `T` is decided, it has already been determined that `x.method()` is calling `::method`. The generic function is instantiated with `T` equal to `BothTraits` so this is going to call `::method` which prints `1`. If you are familiar with C++, the behavior of this code in Rust is _different_ from the behavior of superficially analogous C++ code. In C++ the output would be `22` as seen in the following implementation. This highlights the difference between Rust's traits and supertraits vs C++'s inheritance. ```cpp #include struct Base { virtual void method() const { std::cout << "1"; } }; struct Derived: Base { void method() const { std::cout << "2"; } }; void dynamic_dispatch(const Base &x) { x.method(); } template void static_dispatch(const T x) { x.method(); } int main() { dynamic_dispatch(Derived{}); static_dispatch(Derived{}); } ```