Allow a trailing `..` in a struct literal, meaning `.. Default::default()`


#1

We have .. expr before the closing brace of a struct literal to mean “any other fields in the vale should come from expr”, but that ends up a little verbose, normally .. Default::default(). How about we let the expression there be omitted, and default it to Default::default()?

Default::default would need to become a lang item.

Examples: Struct { .. }, Struct { field: value, .. }.


Idea: reducing boilerplate in APIs that use ADTs
#2

Default is already a pseudo-lang-item by virtue of being hard-coded into #[deriving]. Of course, as far as I know that’s not something we want in the longterm. Still, we’re clearly committed to Default being a “thing”, it would be interesting if we invested deeper in its usage.

As a compromise, we could consider adding a default fn that calls Default::default() into the prelude. That way you can just do: Struct { field: value, .. default() }, which is slightly nicer. Of course a dream world where you can use std::default::Default::default as default would also work.

On the other hand, I wonder if this should be brought to its logical extreme? That is, something like let foo: Struct = ..; or let foo: Struct = _; working? Similarly take_some_values(.., ..)? This may potentially interact either very well of very poorly with the proposed range syntax in the cmp and ops reform rfc.


#3

Sub. Looks like a nice improvement.


#4

This actually already works with functional record update syntax:

use std::default::Default;

#[deriving(Default)]
struct Struct;

fn main() {

    let my_struct = Struct { .. Default::default() };
    
}

So it’d basically be sugar for that pattern. A function default() in the prelude that called Default::default() would be super useful, as it’d save an import and some noise. Optimally, the sugar should work with structs that don’t implement Default, and instead should look at the omitted fields for implementation, throwing a compiler error if there’s a field that doesn’t have it.

On a related note, it would be awesome if unit structs automatically implemented Default since there’s no other state they could possibly be initialized with. Then with this syntax, it would be a lot cleaner:

use std::kinds::marker::NoCopy, NoSend, NoSync;

struct Struct {
    nocopy: NoCopy,
    nosend: NoSend,
    nosync: NoSync,
}

let mystruct = Struct { 
    nocopy: NoCopy, // Is this really necessary?
    nosend: NoSend,
    nosync: NoSync,
};

// versus

let mystruct = Struct { .. };

// or

let mystruct = Struct { .. default() };

Will default initialisation of structures be made more ergonomic?
#5

Why are those markers struct fields and not attributes on the struct itself? Eg: #[nosend]


#6

On the other hand, I wonder if this should be brought to its logical extreme? That is, something like let foo: Struct = …; or let foo: Struct = _; working? Similarly take_some_values(…, …)?

It could be fancy to do the following

try!(stuff().map_err( |e|  detail:"detail",.. e ));

This should be equivalent of

try!(stuff().map_err( |e|  MyError{ detail:"detail", .. e }));

But perhaps it is hard to parse with little gain…