I was originally envisioning this as pure sugar for Default::default()
but reading the feedback I think it'll be worthwhile to tackle partial initialization first so this sugar can be used for that. I'm picturing the following:
#[derive(Debug)]
struct S {
a: usize,
b: usize = 42,
}
fn main() {
let x = S {
a: 42,
..
};
println!("x {:?}", x);
let y = S {
.. //~ ERROR field `a` must be specified
};
println!("y {:?}", y);
}
being sugar for something along the lines of
#[derive(Debug)]
struct S {
a: usize,
b: usize,
}
trait PartialDefault {
unsafe fn partial_default() -> Self;
}
impl PartialDefault for S {
unsafe fn partial_default() -> Self {
S {
a: std::mem::uninitialized(),
b: 42,
}
}
}
fn main() {
let x = S {
a: 42,
.. unsafe { S::partial_default() }
};
println!("x {:?}", x);
let y = S {
.. unsafe { S::partial_default() }
};
println!("y {:?}", y);
}
where the compiler verifies that the uninitialized fields are provided.
We would also then be able to provide a blanket impl<T: std::default::Default> PartialDefault for T {}
, so the new syntax would work then be equivalent to calling ..default()
, and extend the #[derive(Default)]
macro to understand the field: Type = <const value>,
syntax so that you could write
#[derive(Default)]
struct S {
a: usize = 42,
b: Option<usize>,
}