> However, the extensibility of trait objects comes at the cost of fat
> pointers, which can be a problem if you have a lot of pointers.

This is fixable without introducing virtual functions, by adding a way to 
express "Struct and vtable for impl Trait for Struct" and "thin pointer to 
Struct and vtable for impl Trait for Struct" (or by using an indirect pointer, 
i.e. ~~Trait or Rc<~Trait>).

> It also implies that downcasting isn't really possible, at least not
> cheaply, because there is no notion of the "actual type" of a
> particular object.

I don't understand this.

You can downcast trait pointers to struct pointers just fine, since you can put 
whatever information needed in the trait impl vtable (such as a typeid).

Sure, you can't "downcast" a struct to a struct, but that's the whole point of 
structs.

The idea of a struct is that one is referring to something of EXACTLY that 
type, and so downcasting makes no sense; when one wants a "variable" type one 
uses a trait and then you can (attempt to) downcast to concrete structs.

One can of course introduce "virtual struct"s which are no longer exactly of 
that type but are now virtual, but that just overlaps the role of traits.
> (As an aside, I am personally happier to see virtual structs than to> see 
> traits extending structs or traits extending a `HasPrefix` trait,> as was 
> included in previous designs. Both of those approaches mean> that the trait 
> is no longer "pure interface", and if you write> "generic" code against that 
> trait, you're actually coding at least> partially against a fixed 
> implementation, not an interface.)

I think traits inheriting structs is a better design, because you can have 
multiple traits inheriting the same struct.

For example, let's say you are modelling GUI widgets which need both input 
handling and drawing support.

With traits inheriting structs, you can have several traits, one for input 
handling, 
one for drawing in memory, one for drawing with OpenGL, etc., while with 
virtual functions (and without multiple inheritance) you have to put everything 
together and you have to either implement 
all functionality or add "not supported" error codes.

In other words, a trait inheriting a struct neatly separates the trait part 
where multiple inheritance is natural from the struct part where single 
inheritance is natural.
Also, a trait inheriting a Struct behaves to users of the trait exactly like a 
trait with a get_struct() accessor method, but with better performance.

It's only different for implementors, where it mandates how get_struct() is 
implemented for the sake of performance, at the cost of making it impossible to 
implement it along with traits inheriting from incompatible structs.

In general I think it's better to have multiple options at a low level like 
this, rather than having multiple option at an high-level semantic level like 
virtual struct vs trait, since that exposes the choice less to other modules.   
                                        
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to