I’d be in favor of “unnamed fields”, but mildly against named fields with unnamed types, because they are two pretty different things.
Named fields with unnamed types are merely a convenience, any such type can be easily outlined.
struct S {
a: u8,
b: struct {
c: u8,
}
}
=>
struct S_B {
c: u8,
}
struct S {
a: u8,
b: C_B,
}
Such outlining is 1) only two tokens longer 2) doesn’t affect interface of S and therefore invisible for users - the field c is accessed as b.c in both cases.
I’d argue that if struct { FIELDS.... } is allowed in field type position, then it should be allowed in any type position, e.g.
fn f() -> struct { key: u8, value: u8 } { .... }
and I don’t think this is a sugar that Rust urgently needs.
“Unnamed fields” with “unnamed types” as they are used in C don’t even need to be types or fields, they are layout specifiers and in theory can use any syntax not reminding struct/union declarations.
Such modifiers give ability to build an arbitrary complex layout for an aggregate S while keeping it’s interface as simple as a struct with a set of fields:
// I intentionally use the non-`struct {....}` syntax to highlight the difference from named fields with unnamed types.
struct S {
product [
a: u8,
b: u16,
sum [
c: u32,
d: u64,
]
product [
e: i8,
f: i16,
]
]
sum [
g: i32,
h: i64,
]
}
<=>
custom_aggregate S {
a: u8,
b: u16,
c: u32,
d: u64,
e: i8,
f: i16,
g: i32,
h: i64,
}
This is certainly a feature which gives new abilities (as opposed to just convenience) by affecting user-visible interfaces .
Note that this is still a fringe low level feature that is useful in quite specific situations.
One problem with this is that unions currently require unsafe blocks on any access to fields, so you can’t do some things from C, for example the field alias trick as conveniently as in C.
However, I think the rules can be relaxed a bit to allow safe access to common initial sequences, safe writes to trivially destructible fields and maybe something else.