I've just learnt that structs can have their last field as unsized, I've made one as following just for playing around with the concept.
use std::fmt::Display;
struct Show {
a: usize,
b: dyn Display,
}
But no matter how I go about it, I just cannot initialize it. E.g.:
let x = Box::new(Show { a: 1, b: String::new() as dyn Display });
It throws error, the size for values of type (dyn std::fmt::Display + 'static) cannot be known at compilation time.
The only implementation that I've seen for unsized struct is of RcBox which is a private struct used by std::rc::Rc . And it doesn't exactly make it's value field unsized (by using something like dyn Trait, like I have), but rather allows it to be questionably sized by being generic. Another point worth noting is this impl block's generic T input, as far as I understand, is bound to be Sized, so at the end of the day, Rc::new takes a sized input which defies the purpose of allowing it's generic parameter to be ?Sized.
What do I want?
Some way to initialize my Show struct.
@semicoleon I guess there isn't much space to argue if Nomicon itself accepts that "Although such a type is largely useless without a way to construct it. Currently the only properly supported way to create a custom DST is by making your type generic and performing an unsizing coercion".
I publish the slice-dst crate, which enables constructing unsized structs with slice tails ([T]) directly. I also have the indyn crate which is an old nightly-only experiment also in the same space of custom DSTs.
You can directly create non-generic structs with slice tails, but it requires doing allocation and piecewise initialization manually. There is currently no stable way to construct structs with dyn Trait tails except via unsizing.
I've done a significant chunk of work showing what's currently possible and what could be possible with a few more stabilizations. And I'll still say: just use the unsizing.
In your case it could be something like
struct Show<T: ?Sized = dyn Display> {
a: usize,
b: T,
}
impl<T: Display> Show<T> {
pub fn new_box(a: usize, b: T) -> Box<Show> {
Box::new(Show { a, b })
}
}
impl Show {
// the other stuff
}
So, the conclusion still sticks to taking a Sized input for constructing such structs, as T does have a Sized bound in quoted impl block. Hence, to some extent defying purpose of keeping the struct as a DST in the first place.