This is related to the use of &dyn Trait implementation.

A dynamically-dispatched type:

  • undergoes type erasure so that the compiler only knows that it has a certain interface, and not its type
  • is a wide pointer, in that there are actually two pointers under the hood. The first points to the data, whereas the other points to a vtable of functions

The author pointed out a cool and subtle feature with the Rust compiler, called constant promotion.

Unlike C++, Rust’s implementation of dynamic dispatch allows for the data and function pointers behind the wide pointer to be decoupled, which may improve CPU execution speed if you only need one instead of the other.

More concretely, another more apparent benefit of the Rust approach is that the the cost of dynamic dispatch (i.e. having a wide pointer) is only paid by the instances of a class that needs dynamic dispatch. In C++, introducing dynamic dispatch is intrusive in that it changes the definition of the class, making all instances of the class paying for the increased memory footprint.

The author also mentioned that the wide pointers’ downside is in having two pointers instead of one like in the C++ approach. This can sometimes bloat up the program, particularly for the Error type in Result<(), Box<dyn Error>> which isn’t on the happy path. This is where the [[anyhow]] crate uses the intrusive C++ approach under the hood to minimize the number of pointers used.