[Pre-RFC]: Unnamed struct types

This could potentially be solved with module-level #![repr(C)], so all structs and tuples, named and unnamed are #[repr(C)]. The 'struct literal' at the call site is inferred to be the unnamed type defined in the FFI module.

it’s worse, it’s

fn area(Args { width, height }: Args) -> u32 {
    width * height
}

note you have to write Args twice

I like the idea of having an equivalent of anonymous tuples with named fields. From a language consistency standpoint it makes sense. There is an unnamed equivalent of tuple structs, so why is there no unnamed equivalent of regular structs? Plus, sometimes you want something that behaves like a tuple, but with more readable names for the fields.

In order to be consistent, it should be treated similarly to how tuples are treated today. That means no repr, no C FFI, no implicit type conversions, etc.

On the other hand, I don’t think this will be useful for APIs as suggested by the author. When I see code like this, I would never dream of writing it, because it is so unnecessarily verbose, and I hope that API authors would not inflict this on their users.

rectangle({red: 1.0, blue: 0.0, green: 1.0, alpha: 1.0},
     {position: {x: 0.0, y: 0.0}, size: {width: 100.0, height: 100.0}},
     c.transform, g);

As for canonical ordering, that seems like an easy problem to solve. For Debug, just print them in lexicographic order (either by utf8 bytes or by code point, doesn’t really matter which you choose as long as it is easily understandable), and for the memory layout, leave it up to the whims of the compiler.

If the trait fields RFC gets accepted, impls for anonymous structs feel like a natural extension, just like impls for tuples, e.g.


impl<A, B> Foo for (A, B) { /*...*/ }

// maybe use (a :A, b :B) if the grammar doesn't play nicely.
impl<A, B> Bar for { a: A, b: B } {
     a = a;
     b = b;
}

If the generic tuples RFC gets accepted maybe it should apply to structs too so that many procedural macro style impl can be written generically.

impl<A: Clone, ...Tail: Clone> for (A, ...Tail) {
   /* ... */
}

You’d probably still need macros for things that need field names, e.g. Serialize and it might be too magical anyway.

Unnamed structs would also be pretty great for deserializing one-off structures with serde. Sometimes when deserializing a JSON response, you will want to ensure that the response fits a certain structure, but will only care about field names (rather than struct names), for example when you are just extracting a couple Strings from a deeply nested object.

This would be nice for serializing as well, but (for JSON at least) the newish json macro in serde_json already provides a nice interface for the producer side of things (albeit with presumably some overhead).

4 Likes

I’ve proposed this formally:

6 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.