Comment by dminik

8 hours ago

Sort of. Given an instance (can even be a primitive) you can obtain a dyn reference to a trait it implements simply by casting it.

let a: i32 = 12

let b = &a as &dyn std::string::ToString; // i32 implements the ToString trait

let c = a.to_string(); // Static dispatch

let d = b.to_string(); // Dynamic dispatch through dyn reference

Note that there's not really any polymorphic objects in rust. All polymorphism in this case goes through the dyn reference which contains a pointer to a vtable for a specific trait.

Additionally, going from a dyn reference to a type-specific reference is not easy. Also, certain methods and traits are not dyn-compatible, mostly due to generic parameters.

The main use comes in with various libraries. Doing dynamic dispatch on a specific type is not very useful, but your library might expose a trait which you then call some methods on. If you accept a generic parameter (eg. impl Trait) each such invocation will cause monomorphization (the function body is compiled separately for each generic type combination). This can obviously bloat compile times.

Using a dyn reference in your API will result in only a single version being compiled. The downside is the inability to inline or optimize based on the type.

One additional use I found is that you can sometimes get around the divergent expression type in match expressions. Say you need to print out some values of different types:

let value: &dyn Display = match foo { A(numeric_id) => &numeric_id, B(string_name) => &string_name, C => &"static str", };

This would not work without dyn as each value has a different type.