Conversation

Jarkko Sakkinen

One perhaps not so obvious observations from Rust that at least I've gathered over time is answer to this question:

- There are traits and dynamic traits.
- Which one to pick by defacto?

Dynamic traits are most of the time the best pick in my opinion, and I base it on:

1. Smaller binary size.
2. Shorter compilation times.

#rust #rustlang
1
1
3
Static traits are really "3rd macro language" of Rust, when observing how they translate into ELF binary.
1
0
1

@jarkko First and foremost there are only traits. If they are then used as generic trait bounds or dynamic (vtable) pointer is another thing. There are some semantic differences. Not every trait is dyn-compatible/object safe. dyn is only available behind some kind of (fat-)pointer, be it a reference or some kind of box. While generics will be a single concrete type (at compile time).
For 'dyn' you pay a (often negligible) runtime cost plus sometimes a boxing cost. Generics don't but when you overuse them they bloat the binary and you pay with cache misses. This means the decision is often dictated by usage and intended semantics.

1
0
0
@cehteh I'm not sure I fully cope what point you are trying to make.
2
0
0

@jarkko The conclusion is that the intended usage dictates how you use traits. Often you can not choose arbitrarily if it shall be generic or dyn. But when you do the wrong thing the compiler will nudge you.

0
0
0

@jarkko
As far as I can tell from your English, you're saying there are multiple kinds of traits in Rust, which isn't so. @cehteh was correcting what appears to be your misunderstanding of the trait system's design.

1
0
0

@jarkko @codrusofathens

It is not the trait that is different dynamic/generic, but how you use it:

trait Trait {}

// the T is part of the type you can instantiate this with different T's, but for each different T you get a new type. The T is used directly not over a pointer
// You can access T's methods as well as any trait methods
struct Generic<T: Trait>(t:T);

// here you have only one single dynamic type, you can instantiate it with anything that implements Trait, but only the Trait methods are available. 'dyn' also mandates (as i saied before) a (fat-)pointer, here that is a Box, but references or other things are possible too.
struct Dynamic(Box<dyn Trait>);

Thats just the surface, there are more differences, but it is the usage that differentiates generic vs dyn, not the Trait

1
0
0
@cehteh @codrusofathens i don't think i have any use for these trait tutorials (just saying). i've disassembled enough rust binaries by now what kind of assembly code those construct generate. having a de-facto choice is not same as ultimate choice or a choice that could not change (based on testing that brings to light actual performance regressions not theoretical language spec based).
2
0
0

@jarkko @codrusofathens

You where not wrong saying that using Traits in generic context is similar to macros as it expands the code (you may try optimization/LTO to merge that back again) monomorphizing generics can (and will) bloat and increase compile times. While dyn leads to leaner binaries at a little runtime cost.

I just wanted to point out that there are semantic differences in the language. Using a trait generic vs dynamic is sometimes not a choice so there is no general rule what you should use by default.

0
0
1

@jarkko @codrusofathens

If you like you can look at my univec crate for reference:
https://docs.rs/univec/1.1.0/univec/

which does some mix/translation between generics and dyn (Any)

0
0
0