# Nested struct declaration

**URL:** <https://internals.rust-lang.org/t/nested-struct-declaration/13314>\
**Category:** language design\
**Created:** [October 31, 2020, 10:26pm UTC](https://internals.rust-lang.org/t/nested-struct-declaration/13314 "2020-10-31T22:26:12Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![hoxonstudios](https://avatars.discourse-cdn.com/v4/letter/h/b782af/32.png) [@hoxonstudios](https://internals.rust-lang.org/u/hoxonstudios)\
**Post date:** [October 31, 2020, 10:26pm UTC](https://internals.rust-lang.org/t/nested-struct-declaration/13314/1 "2020-10-31T22:26:12Z")

</div>

I was wondering if having nested struct declarations could be a nice feature for Rust. In Rust and most of the languages we declare structs this way:

> ```
> pub struct Parent {
> pub child: Child;
> }
> pub struct Child {
> ... // Some props
> }
> 
> ```

when sometimes the Child would not exist without the parent. I think something like this could be nice:

> ```
> pub struct Parent {
> pub child: pub struct Child {
> ... // Some props
> }
> }
> 
> ```

We can discuss the details but will be nice to hear your opinions

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [October 31, 2020, 11:12pm UTC](https://internals.rust-lang.org/t/nested-struct-declaration/13314/2 "2020-10-31T23:12:52Z")

</div>

I guess my question is: what problem would it solve, exactly?

Please keep in mind that privacy issues (e.g. Which types are publicly exported and which are not) are currently elegantly solved by the use of modules.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [October 31, 2020, 11:54pm UTC](https://internals.rust-lang.org/t/nested-struct-declaration/13314/3 "2020-10-31T23:54:47Z")

</div>

Surely a user wouldn't construct `Child` if there's literally no way to use it other than with `Parent`? Even if they did, what's the harm?

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)\
**Post date:** [November 1, 2020, 3:54am UTC](https://internals.rust-lang.org/t/nested-struct-declaration/13314/4 "2020-11-01T03:54:53Z")

</div>

[Structural records](https://github.com/rust-lang/rfcs/pull/2584) would give you the nesting (without the privacy controls or naming).

```rust
// From the RFC
struct RectangleTidy {
    dimensions: {
        width: u64,
        height: u64,
    },
    color: {
        red: u8,
        green: u8,
        blue: u8,
    },
}

```

---

<div class="post-metadata">

**Author:** ![ekuber](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ekuber/32/1646_2.png) [@ekuber](https://internals.rust-lang.org/u/ekuber)\
**Post date:** [November 1, 2020, 6:16pm UTC](https://internals.rust-lang.org/t/nested-struct-declaration/13314/5 "2020-11-01T18:16:22Z")

</div>

First of all, thank you for your desire to improve Rust. I would like to hear more about what the expected benefit of this would be.

From a `rustc` implementation perspective, this would be possible to do in a relatively straightforward manner. But there are some drawbacks that need to be considered.

`rustc` is not the only tool that needs to understand the Rust grammar, whenever we change the language, either in its syntax or its semantics, we need to be mindful of how these changes will affect other implementors, like rust-analyzer or `mrustc`.

Even if the parser is able to understand the new syntax, it doesn't mean that a human can. In this context it does seem easy to follow, but the more complex the container-containee relationship becomes, the harder it will be to read. [John Carmack once said "if something can syntactically be entered incorrectly, it eventually _will_ be"](https://blogs.uw.edu/ajko/2012/08/22/john-carmack-discusses-the-art-and-science-of-software-engineering/). In order for `rustc`'s fame as "friendly" to hold, we need to anticipate how invalid syntactical constructs would be handled. For code like `struct Parent { child: Child {}}`, `struct Parent { child: struct {}}` or `struct Parent { child: pub }` we need to have enough context in order to help 1) the parser recover and continue and 2) the user by recognizing what they were trying to do and explaining to them why it isn't allowed. Complicating what _can_ go in certain places makes it harder for to us differentiate from likely intended possibilities.

Having more places to define ADTs makes it harder for people to skim an unfamiliar codebase. You could argue that we've already gone down this route by allowing `impl` blocks in expressions, which have non-local effects, but I would qualify that as a "grandfathered-in mistake" that we should avoid to repeat.

We need to consider how this would interact with proc and derive macros, particularly things like `#[derive(Default)]`: would it flow down? Would each field newtype need an annotation?

We would also need to consider how this would interact or preclude potential future features, like [recently restarted conversation around field default values](https://internals.rust-lang.org/t/pre-pre-rfc-syntactic-sugar-for-default-default/13234). How would this syntax compose (both when it is correct and when there are missing tokens or typos) with something like:

```rust
struct Parent {
    pub child: Child = Child::Empty,
}
enum Child {
    Empty,
    Parent(Box<Parent>),
}

```

Finally, you have to consider how you would refer to `Child`, what would it's path be? `crate::Parent::Child`? `crate::Child`? The former would be confusing because it complicates the understanding that ADTs are not modules, and even if made to work would be problematic on the face of name clashes with associated types. The later would be confusing because the type's path wouldn't match the code the user sees. How this would be taught to people is so important that it is an explicitly required section of the RFC process.

Because of all of these points, I would consider this feature to be more trouble than it is worth. That being said, please do not be discouraged by my position. There are plenty of features I have thought of that sounded great but upon closer inspection were problematic or rejected for one reason or many.

With that out of the way, **I would like to hear more** from you about the intention behind the feature request, as I might be missing a big benefit this feature could bring, but I think that there already existing or proposed alternatives that could work better. If the intention is to make the grammar be more expressive, I think that the raised points overpower that desire. If it is to have the common pattern of dynamic languages of having rigid map trees in a type-safe language endorsed manner, @quinedot's point of using structural records would be a better fit. If it is to make `Child` only constructable when used in a `Parent`, there are design patterns that could be used (and even uplifted into language features), like builders or making `Child` private and only constructable from a method on `Parent`. And of course, we always have macros, where we can try things out and experiment with different behaviors in the real wold before attempting to uplift them into the language.

---

<div class="post-metadata">

**Author:** ![hoxonstudios](https://avatars.discourse-cdn.com/v4/letter/h/b782af/32.png) [@hoxonstudios](https://internals.rust-lang.org/u/hoxonstudios)\
**Post date:** [November 1, 2020, 6:51pm UTC](https://internals.rust-lang.org/t/nested-struct-declaration/13314/6 "2020-11-01T18:51:09Z")

</div>

Thanks, this is the feature I was looking for, I didn't find it. Sorry for open the proposal.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [January 30, 2021, 6:51pm UTC](https://internals.rust-lang.org/t/nested-struct-declaration/13314/7 "2021-01-30T18:51:19Z")

</div>

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