3

I can see the difference between dyn and (static) impl Traits in return position, such as:

fn foo() -> Box<dyn Trait> {}

vs

fn foo() -> impl Trait {}

Where in the dyn version I'm allowed to return different types as long they all implement the Trait, while in the impl version I'm only allowed to return the same type (same applies if I return a reference).

But I can't see the purpose of a dyn Trait in argument position such as:

fn foo(x: &dyn Trait) {}

vs

fn foo(x: &impl Trait) {}  // syntatic sugar of `fn foo<T: Trait>(x: &T){}`

What is the difference between the two? Why would I use one or the other? And what does the dyn version allow me to do that the static one doesn't (that I cannot do for example by relaxing the implicit Sized restriction with ?Sized)?

Nick
  • 10,309
  • 21
  • 97
  • 201
  • 1
    Does this answer your question? [What makes something a "trait object"?](https://stackoverflow.com/questions/27567849/what-makes-something-a-trait-object) – trent May 22 '20 at 18:26

1 Answers1

5

If you're familiar with C++/Java, then dyn corresponds to "interface reference", so it implies dynamic polymorphism (thus requires a bunch of jumps over references, so it's a bit slower).

impl being a syntatic sugar, defines a template for functions, thus every time you use the function with another type, you'll get a separate copy of function compiled specifically for this type. So no extra jumping, but your executable bloats with these copies. Rust's ideology tells to create templates with <T>, impl, unless there're too many versions compiled that the executable is too bloated.

Alexey S. Larionov
  • 6,555
  • 1
  • 18
  • 37
  • Are you saying that it's **only** a compromise between binary size and speed? Where in the `impl` version the size is larger, but since I don't have to go through the vtable, it's going to be faster? And that there are no further restrictions with a version of the other? – Nick May 22 '20 at 17:33
  • @Nick pretty much. it's the same in C++ though, you either make virtual methods in a class, override them and thus you deal with vtable jumps, or you make a function template and forget about vtables – Alexey S. Larionov May 22 '20 at 17:40
  • 5
    @Nick For the immediate caller, yes, it's just a matter of the vtable. But an important distinction is that you can make a `dyn Trait` from an `impl Trait`, but not the other way around (because once you go `dyn`, you don't have the compile time type information anymore). That means that the function body cannot call some function that returns a `Box` and return that as a `impl Trait`. – This company is turning evil. May 22 '20 at 17:43
  • Unless, `Trait` is implemented for `Box`. – Optimistic Peach May 22 '20 at 18:22