# \[Pre-RFC\]: Unnamed struct types

**URL:** <https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872>\
**Category:** language design\
**Created:** [August 17, 2016, 11:36pm UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872 "2016-08-17T23:36:03Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![iopq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/iopq/32/78_2.png) [@iopq](https://internals.rust-lang.org/u/iopq)\
**Post date:** [August 18, 2016, 3:21am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/21 "2016-08-18T03:21:02Z")

</div>

I don’t see why not, you can `impl Add for (i8,)`

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 18, 2016, 3:47am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/22 "2016-08-18T03:47:16Z")

</div>

@KiChjang I think you have misunderstood this proposal. The comments about structs / tuple structs were an analogy, there’s not a proposal to add any sort of coercion or subtyping at all.

This proposal is just to allow you to create a type like `{ x: u32, y: u32 }`, which doesn’t have a name. This type would be distinct from all other types - that is even if you had a `struct Point { x: u32, y: u32 }`, you could not coerce a `{ x: u32, y: u32 }` into a `Point`. This is just a new sort of unnamed type, similar to tuples, except that instead of having positional members, the members have names.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 18, 2016, 3:48am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/23 "2016-08-18T03:48:22Z")

</div>

To me this seems consistent and fine - the kind of feature a user could infer to exist from knowing the other features of Rust - but I’m not thrilled by the idea of trying to use this to implement named arguments.

---

<div class="post-metadata">

**Author:** ![durka](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/durka/32/1097_2.png) [@durka](https://internals.rust-lang.org/u/durka)\
**Post date:** [August 18, 2016, 4:08am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/24 "2016-08-18T04:08:50Z")

</div>

Well kinda, you can impl `MyTrait`.

---

<div class="post-metadata">

**Author:** ![retep998](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/retep998/32/729_2.png) [@retep998](https://internals.rust-lang.org/u/retep998)\
**Post date:** [August 18, 2016, 4:19am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/25 "2016-08-18T04:19:13Z")

</div>

As I understand it, this RFC is to structs with named fields as tuples are to tuple structs. I like this RFC, I like it very much indeed. I’m pretty sure there’s a bunch of places in winapi where I could totally take advantage of this to closely match what the headers are doing. If this goes through, then all I’ll need is a similar proposal for anonymous unions and oh man will it be amazing.

+1

---

<div class="post-metadata">

**Author:** ![Aatch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aatch/32/433_2.png) [@Aatch](https://internals.rust-lang.org/u/Aatch)\
**Post date:** [August 18, 2016, 4:42am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/26 "2016-08-18T04:42:05Z")

</div>

My main concern here is with the layout of the records. Intuitively,

```rust
{ a: 1.0, b: 0, c: "foo" }

```

and

```rust
{ b: 1, c: "bar", a: 0.0 }

```

should be same type. However, the layout of the data in the type is important. If we just use the ordering in the source, then the first would be `(f32,i32,&str)` while the second would be `(i32,&str,f32)`. Javascript objects are just dictionaries, where access is effectively a lookup in a hashmap. Field access in Rust is a pointer offset, so determining how to lay the data out is important.

---

<div class="post-metadata">

**Author:** ![retep998](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/retep998/32/729_2.png) [@retep998](https://internals.rust-lang.org/u/retep998)\
**Post date:** [August 18, 2016, 4:47am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/27 "2016-08-18T04:47:19Z")

</div>

@Aatch I’d be in favor of a solution where an anonymous record is “canonicalized”, aka the fields are sorted in canonical ordering so that your two examples would have an equivalent type.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 18, 2016, 4:52am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/28 "2016-08-18T04:52:12Z")

</div>

Those two should definitely be the same type, with the same layout, though there should be no guarantee about what specifically that layout is.

---

<div class="post-metadata">

**Author:** ![Manishearth](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/manishearth/32/50_2.png) [@Manishearth](https://internals.rust-lang.org/u/Manishearth)\
**Post date:** [August 18, 2016, 5:23am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/29 "2016-08-18T05:23:18Z")

</div>

There’s no coercion going on, only new types. Anonymous structs are not coerced to tuples.

Just how `(u8, )` and `struct Foo(u8)` and `struct Foo{foo: u8}` are different types, `{foo: u8,}` is also a different type and not interchangeable with `{bar: u8,}`, or any of the other types I just named.

* * *

A slight issue with the proposal is that you can’t implement Default everywhere to get optional kwargs. `{foo: u8, bar:bool}` is not a local type so you cannot impl Default on it. This means that using the splat syntax to initialize just one parameter (`{foo: 1, ..Default::default()}`) won’t work. You can do this with a named struct because it is a local type. But as a named struct, callers have to import and name it, which is noisy. We could add autocoercion from anonymous structs to named structs with the same fields (public) but then you have new classes of type errors about ambiguousness and all of KiChjang’s concerns apply.

Since default kwargs is a huge plus point of kwargs in other languages, I personally prefer if any proposal for kwargs had the ability to default them.

---

<div class="post-metadata">

**Author:** ![pcwalton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pcwalton/32/207_2.png) [@pcwalton](https://internals.rust-lang.org/u/pcwalton)\
**Post date:** [August 18, 2016, 5:47am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/30 "2016-08-18T05:47:38Z")

</div>

Everything old is new again. 🙂 Rust used to have this feature 5 years ago. In fact, it was the _only_ way to make what are now called structs at the time–nominal structures wouldn’t exist for several years.

---

<div class="post-metadata">

**Author:** ![mcpherrinm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcpherrinm/32/422_2.png) [@mcpherrinm](https://internals.rust-lang.org/u/mcpherrinm)\
**Post date:** [August 18, 2016, 5:58am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/31 "2016-08-18T05:58:15Z")

</div>

Here's the issue where they removed in the first place.

> <https://github.com/rust-lang/rust/issues/3089>

And some more recent discussion on the topic

> [@Why were structural records removed?](https://internals.rust-lang.org/t/why-were-structural-records-removed/1553/2):
>
> They had three usability problems: The fields had to be in the exact same order every time you constructed an instance of the record. This is because the compiler needed a canonical ordering. They could not be recursive without the compiler doing fancy typechecking (coinductive IIRC), which was felt to be not worth the effort. Field-level privacy can’t work with them.

---

<div class="post-metadata">

**Author:** ![iopq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/iopq/32/78_2.png) [@iopq](https://internals.rust-lang.org/u/iopq)\
**Post date:** [August 18, 2016, 6:23am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/32 "2016-08-18T06:23:46Z")

</div>

I do see that issue with using unnamed structural types for optional args. That said, if keyword arguments end up being awkward with unnamed structs, proper optional keyword arguments can be added later. There is a benefit to just adding unnamed structs now since it mirrors tuples directly anyway.

---

<div class="post-metadata">

**Author:** ![gyscos](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gyscos/32/1732_2.png) [@gyscos](https://internals.rust-lang.org/u/gyscos)\
**Post date:** [August 18, 2016, 6:33am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/33 "2016-08-18T06:33:44Z")

</div>

I’d be interested in a way to `#[derive()]` some traits for those structs: `Debug`, `Clone` and serde’s `Serialize` come to mind. Maybe annotate the variable construction this way?

```rust
fn foo() {
    #[derive(Clone, Debug)]
    let bar = {x: 1,};
    let baz = bar.clone();
    println!("{:?}", baz);
}

```

Or separately, with the type “definition”?

```rust
#[derive(Clone, Debug)]
struct {x: i32,}

```

Or without the `struct`, as written in the original post?

```rust
#[derive(Clone, Debug)]
{x: i32,}

```

An advantage of these structs it that it allows to build a struct with unnamed/unnamable members (if those come from `impl Trait`-returning functions - iterators I’m looking at you).

To come back to `Serialize`, I wonder how feasible something like this would be:

```rust
fn bar() -> impl Serialize {
    #[derive(Serialize)]
    {
        y: 1,
    }
}

fn foo() -> impl Serialize {
    #[derive(Serialize)]
    {
        x: bar(),
    }
}

fn main() {
    serde_json::to_writer(&mut ::std::io::stdout(), &foo());
}

```

---

<div class="post-metadata">

**Author:** ![KasMA1990](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kasma1990/32/1733_2.png) [@KasMA1990](https://internals.rust-lang.org/u/KasMA1990)\
**Post date:** [August 18, 2016, 6:49am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/34 "2016-08-18T06:49:26Z")

</div>

I’m personally not a fan of using this to solve the issue of named arguments; this means that named arguments are opt-in when you decide to use one of these unnamed structs as arguments in your functions, and it also makes the code more verbose when using these arguments (`args.my_named_arg`).

---

<div class="post-metadata">

**Author:** ![gyscos](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gyscos/32/1732_2.png) [@gyscos](https://internals.rust-lang.org/u/gyscos)\
**Post date:** [August 18, 2016, 6:53am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/35 "2016-08-18T06:53:25Z")

</div>

As for optional/defaults, some (procedural) macro could, given a default value for each variable, generate `Into<complete unnamed struct>` for every partial unnamed struct (we could restrict the variables being optional). Finally, just have the function take an `Into<complete unnamed struct>`. Though I’m not sure it can be done in an elegant syntax :S

---

<div class="post-metadata">

**Author:** ![CornedBee](https://avatars.discourse-cdn.com/v4/letter/c/eb8c5e/32.png) [@CornedBee](https://internals.rust-lang.org/u/CornedBee)\
**Post date:** [August 18, 2016, 9:00am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/36 "2016-08-18T09:00:41Z")

</div>

I don’t see how you can impl traits that you don’t define yourself for these types. Anonymous structs would have no canonical definition place, so the only place allowed for trait impls would be where the trait is defined.

Otherwise, what stops two places in the code from defining conflicting impls of `Add for {red: f32, green: f32, blue: f32}`? You can’t even say that two otherwise identical anonymous structs are different when defined in different modules, since that would make them unusable as function arguments - a function taking `crate1::module1::{foo:i32}` cannot be called from `crate2::module2`, since the literal `{foo:10}` written there would be a `crate2::module2::{foo:i32}`.

---

<div class="post-metadata">

**Author:** ![iopq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/iopq/32/78_2.png) [@iopq](https://internals.rust-lang.org/u/iopq)\
**Post date:** [August 18, 2016, 10:20am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/37 "2016-08-18T10:20:22Z")

</div>

> I don't see how you can impl traits that you don't define yourself for these types.

You can't, actually. You can only define it where the trait is defined.

---

<div class="post-metadata">

**Author:** ![ticki](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ticki/32/1578_2.png) [@ticki](https://internals.rust-lang.org/u/ticki)\
**Post date:** [August 18, 2016, 11:34am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/38 "2016-08-18T11:34:04Z")

</div>

Omitting the type is one thing (although I do oppose that as well), but literally allowing for closure-like struct types is a quite big change with little benefit.

Despite, there is a parsing ambiguity, there is a parsing rule, `'{' EXPR '}'`, which this clearly breaks given that `EXPR := EXPR ':' TY | ...`.

Secondly, there are a lot of other problems here. One of them is encouraging long, untyped argument lists, which is generally considered an anti-pattern.

Now, introducing such an feature would mean splitting the whole ecosystem into two, incompatible forms of passing arguments.

The `{...,}` syntax is rather strange as well.

I could go on, but my general opinion is that this is a very bad idea with little benefit.

---

<div class="post-metadata">

**Author:** ![ticki](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ticki/32/1578_2.png) [@ticki](https://internals.rust-lang.org/u/ticki)\
**Post date:** [August 18, 2016, 11:37am UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/39 "2016-08-18T11:37:29Z")

</div>

Also, tuples aren’t duck types. Semantically, they are equivalent to structs.

---

<div class="post-metadata">

**Author:** ![dan\_t](https://avatars.discourse-cdn.com/v4/letter/d/eada6e/32.png) [@dan\_t](https://internals.rust-lang.org/u/dan_t)\
**Post date:** [August 18, 2016, 12:02pm UTC](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872/40 "2016-08-18T12:02:53Z")

</div>

[quote=“ticki, post:38, topic:3872, full:true”]Despite, there is a parsing ambiguity, there is a parsing rule, ‘{’ EXPR ‘}’, which this clearly breaks given that EXPR := EXPR ‘:’ TY | …[/QUOTE]

Anonymous structs with one field certainly won’t be used that much, but you can still require them to be written with a trailing comma `{ x: i32, }`, which should solve the parsing problem.

[quote=“ticki, post:38, topic:3872, full:true”]Secondly, there are a lot of other problems here. One of them is encouraging long, untyped argument lists, which is generally considered an anti-pattern.[/QUOTE]

You can say this for pretty much every feature, that there are good and bad uses of and I can see how anonymous structs can help solving the named/default parameter case.

I wouldn’t consider it to be the nicest syntactic way for named/default parameters, but all the other ways have their own issues, which might even have a bigger impact on the whole language, and any solution for named/default parameters will most likely be opt-in, so there will be a difference between functions/methods with and without named/default parameters.

[Previous page](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872.md?page=1)

[Next page](https://internals.rust-lang.org/t/pre-rfc-unnamed-struct-types/3872.md?page=3)
