What problem does this solve? Can't you already do void::default() and u8::default?
Unit structs just declare a const with the same value as the struct. You can already do this if your struct is not a tuple struct (since those also declare a function with the same name as the struct, and that conflicts with the const)
@mjbshaw, I do not need void and core::ffi::c_void doesn’t seem really good because it is an enum. Also unit is not void cuz these types even have different sizes (unit is ZST and void is one byte). Void implementation was only an example.
(last post on void; sorry for kinda derailing this)
C's void doesn't have a size. You can't perform sizeof(void). If you're talking about Rust then it's up to the underlying implementation of void (IMO libc::c_void would ideally just be an extern type and would thus not have a size, just like C's void).
void means two different things in C, and the definition you used here is the one that's a reasonable translation of void as in void*, but not as in void functions.
The equivalent of C void foo(void); is Rust extern { fn foo(); }. Writing Rust -> () (implicit with no return type) is guaranteed the same as returning void in C.
To translate C void*, use Rust *mut std::ffi::c_void.
Again restating for full explicitness, these three uses of void in C mean different things.
C void as a return type => Rust -> ()
C void as a parameter type => marks that a function is not the old, deprecated, removed in C23, pre-K&R declaration without specifying arguments[1], and is in fact a nullary function.
C void as a pointee type => marks that pointer as pointing to arbitrary data that cannot be described without casting the pointer.
A C stack local binding of type void is 100% forbidden and I don't know of any compiler extension which allows it.
Since C89 and up until C23, void foo(); was a deprecated way of declaring the function foo as returning nothing but not declaring what arguments it takes, so you could call it with any combination of arguments, e.g. foo(1, 2, 3), and were just assumed to call it with the correct arguments for the linked implementation. Early pre-K&R was wild; even struct field names had to be globally unique because absolutely no type checking was typically done when C was purely a slightly more portable assembler. ↩︎
This could be done. But why would we? What code does this make better? Where did you want to use it? Presumably not for -> (), where the current thing is fine.
I think it's a feature, not a problem, that
fn foo() -> VecDeque<String> {}
doesn't compile. Having that invisibly allocate memory for a VecDeque -- which is Default! -- seems very strange to me.
Even for Default + Copy things,
fn bar() -> u8 {}
also doesn't seem useful. Having it be { 0 } instead seems way better, for negligible extra effort from the programmer.
If anybody else wants this, or any other, locked thread to be re-opened, use the Flag button with the “other” reason. We usually will open it if there’s something new to add to it.