Reputation: 14052
When I try to declare a struct inside of another struct:
struct Test {
struct Foo {}
}
The compiler complains:
error: expected identifier, found keyword `struct`
--> src/lib.rs:2:5
|
2 | struct Foo {}
| ^^^^^^ expected identifier, found keyword
help: you can escape reserved keywords to use them as identifiers
|
2 | r#struct Foo {}
| ^^^^^^^^
error: expected `:`, found `Foo`
--> src/lib.rs:2:12
|
2 | struct Foo {}
| ^^^ expected `:`
I could not find any documentation in either direction; are nested structs even supported in Rust?
Upvotes: 69
Views: 54345
Reputation: 11
You can use
[dependencies]
nestify = "0.3"
nestify::nest! {
#[derive(Debug)] struct Root {
a: #[derive(Debug)] struct A {
text: String,
},
b: #[derive(Debug)] struct B {
text: String,
},
}
}
Or you can implement one yourself:
macro_rules! nstruct {
(
$name:ident {
$(
$field_name:ident : $field_ty:ident $({
$($field_ty_inner:tt)*
})?
),*
$(,)? }
) => {
#[derive(Debug)]
struct $name {
$(
$field_name : $field_ty
),*
}
$(nstruct! {
$field_ty $({
$($field_ty_inner)*
})?
})*
};
($name:ident {$($fields:tt)*}) => {
nstruct! {
struct $name {
$($fields)*
}
}
};
($name:ident) => {};
}
nstruct! {
Root {
a: A {
text: String,
},
b: B {
text: String,
}
}
}
Upvotes: 1
Reputation: 49
I found a discussion regarding this topic, maybe it can help you: https://internals.rust-lang.org/t/nested-struct-declaration/13314/4
RFC Structural records 592 was discussing the nesting (without the privacy controls or naming), but was ultimately rejected.
// From the RFC (not working as of Rust 1.81.0 in 2024)
struct RectangleTidy {
dimensions: {
width: u64,
height: u64,
},
color: {
red: u8,
green: u8,
blue: u8,
},
}
Below is my old answer, which is the current way to solve it.
Build using the Stable version: 1.65.0. Here's a example for you. rust playground
codes:
#[derive(Debug)]
struct Inner {
i: i32,
}
#[derive(Debug)]
struct Outer {
o: i32,
inner: Inner,
}
pub fn test() {
// add your code here
let obj = Outer {
o: 10,
inner: Inner { i: 9 },
};
assert!(10i32 == obj.o);
assert!(9i32 == obj.inner.i);
println!("{}", obj.o);
println!("{}", obj.inner.i);
println!("{:?}", obj);
}
fn main() {
test();
}
Upvotes: 3
Reputation: 8494
They are not supported by Rust.
But you can write yourself a proc macro that emulates them. I have, it turns
structstruck::strike!{
struct Test {
foo: struct {}
}
}
into
struct Foo {}
struct Test {
foo: Foo,
}
You haven't explicitly said so, but I suspect that your goal for using nested structs is not more easily readable data structure declarations, but namespacing?
You can't actually have a struct named Test
and access Foo
as Test::Foo
, but you could make yourself a proc macro that at least automatically creates a mod test { Foo {} }
.
Upvotes: 0
Reputation: 127781
No, they are not supported. You should use separate struct declarations and regular fields:
struct Foo {}
struct Test {
foo: Foo,
}
Upvotes: 72