With the currently stable Rust is it possible to construct a vector of items with statically unknown type of the Item?
Using trait objects we can coerce Box of object-safe type to be dynamically dispatched Box<dyn Any> object. Informally speaking I would like to construct something like "Vec<dyn Any>" where the container would represent a memory slice of uniform items, but the type of all items will be unknown at compile time.
I want to emphasize that Vec<Box<dyn Any> where each item resides in random memory and have individual type per Item is not my goal. The container should represent a slice of contiguous memory of items of uniform type.
The first thing that comes into my mind is to manually re-implement or partially utilize the existing Vec data structure enreaching it with underlying item type Layout.
The main issue arising with this solution is that in currently stable Std manual memory allocation and deallocation is not possible. Maybe there are some workarounds?
It is assumed that the target container would be created with concrete type. Similarly to Box<T> as Box<dyn Any>. So at the creation point whatever way we created the container we statically known the Item type, and it's Layout as well.
This is not true. What makes you think this is the case? There are several, lower-level and higher-level abstractions in std that you can use to manually manage memory. For example, there is alloc::System with a GlobalAlloc impl. Shouldn't that suffice for most needs?
I feel you have misunderstanding on what OP wants. OP wants something operates like Vec<Box<dyn Any>> but without the Box. OP want to support any_vec![1, 2, "abc", String::from("haha")]-like operation.
Thank you for your reply, and for the detailed example. After reading of your example and the list-any crate mentioned by Violet Leonard above, I realized that I underestimate the expressiveness of the Rust type system, and that my initial thoughts about low-level Vec re-implementation was in wrong direction anyway. What I wanted to achieve in the beginning could be expressed much easier in many ways.
As of alloc::System, as far as I understand all of it's allocation/deallocation functions are under the Allocator API nightly feature. That's why I considered it as unstable.
I like your solution too, it is based on completely safe Rust and very elegant, and basically achieve the desired goal in general. One issue I see here comparing to Violet Leonard's solution is that you create indirection by wrapping Vec<T> into Box. This is additional allocation (which is maybe will not always be a big issue in many cases), and because of this it also slightly harms memory locality too.
yes, to be clear you can make this very concisely with just Box<Vec<T>>, and upcast the it to Box<dyn Any> where the Vec itself is the trait object. The purpose of my crate was solely to remove that extra indirection.
This is not the case; as I mentioned, impl GlobalAlloc for Systemis already stable today (they both have been, since 1.28). This compiles under the stable toolchain.
It's probably not a big deal. You will already have dynamic dispatch for every single call you make to the ErasedVec anyway. Traversing a single pointer is probably at most comparable to that.
Note though that the two traits, DynVec and AnyVec<T> are implemented for all Vec<U> concrete types directly. Therefore, if you are OK with having such a concrete type own the elements, and only drop down to &(mut) dyn DynVec or &(mut) dyn AnyVec<T> when you actually need to access the elements in some other methods, then you can just accept such borrowed trait objects in any function that needs them, and otherwise keep the concretely-typed Vec around. This avoids boxing the vector itself.