Are nested structs supported in Rust? - struct

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?

No, they are not supported. You should use separate struct declarations and regular fields:
struct Foo {}
struct Test {
foo: Foo,
}

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 {} }.

I found the optional answer for your request.
Maybe it can help you:
https://internals.rust-lang.org/t/nested-struct-declaration/13314/4
Structural records 592 would give you the nesting (without the privacy controls or naming).
// From the RFC
struct RectangleTidy {
dimensions: {
width: u64,
height: u64,
},
color: {
red: u8,
green: u8,
blue: u8,
},
}
Below is my old answer, please ignore.
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();
}

Related

How to wrap up functions using NodeIndex in petgraph

Newbie question: I want to use the petgraph rust crate. The graph should be a part of the struct MyGraph. For this, I need to wrap some functions to make them acessible from outside:
use petgraph::graph::DiGraph;
use petgraph::adj::NodeIndex;
#[derive(Default)]
struct MyNode {}
#[derive(Default)]
struct MyGraph {
g: DiGraph<MyNode,()>
}
impl MyGraph {
pub fn add_node(&mut self, node: MyNode) -> NodeIndex {
self.g.add_node(node) // does not compile: return value is u32 != NodeIndex
}
pub fn update_edge(&mut self, a: NodeIndex, b: NodeIndex) {
self.g.update_edge(a, b, ()); // does not compile: a: NodeIndex expected, got u32
}
}
fn main() {
let mut my_graph=MyGraph::default();
let node1=my_graph.add_node(MyNode::default());
let node2=my_graph.add_node(MyNode::default());
my_graph.update_edge(node1,node2);
}
The rust compiler however complains the an u32 is returned by the self.g.add_node() function, which is not the case if you call the function directly (and it's documented to return a NodeIndex). The smae problem applies to the self.g.update_edge() function. What would be the correct parameter type to use here???
A return type NodeIndex did not work as well. The (partial) compile error message:
...
error[E0308]: arguments to this function are incorrect
--> src\main.rs:17:16
|
17 | self.g.update_edge(a, b, ());
| ^^^^^^^^^^^
|
note: expected struct `NodeIndex`, found `u32`
--> src\main.rs:17:28
|
17 | self.g.update_edge(a, b, ());
| ^
= note: expected struct `NodeIndex`
found type `u32`
...
What I am doing wrong here?
You're importing petgraph::adj::NodeIndex, which is an alias for u32, but what you need to import is petgraph::graph::NodeIndex, which is a different struct.

How to call Iter::chain and what will be the return type?

I'm trying to create an iterator that will add one element to the start of a vector
struct World {
player: Object,
npcs: Vec<Object>,
}
impl World {
pub fn all_objects(&mut self) -> ???
}
I understand I need to use the chain function for this but I'm not sure how, or what will the return type be
Maybe someone can explain to me how to use it?
The exact types of iterators can be complex. A fast way to determine them is to try to return the wrong type on purpose, and see what the compiler says:
struct Object;
struct World {
player: Object,
npcs: Vec<Object>,
}
impl World {
pub fn all_objects(&mut self) -> () {
std::iter::once(&self.player).chain(self.npcs.iter())
}
}
(Permalink to the playground)
This gives:
error[E0308]: mismatched types
--> src/lib.rs:10:9
|
9 | pub fn all_objects(&mut self) -> () {
| -- expected `()` because of return type
10 | std::iter::once(&self.player).chain(self.npcs.iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;`
| |
| expected `()`, found struct `std::iter::Chain`
|
= note: expected unit type `()`
found struct `std::iter::Chain<std::iter::Once<&Object>, std::slice::Iter<'_, Object>>`
and indeed if you replace that, it will compile:
struct Object;
struct World {
player: Object,
npcs: Vec<Object>,
}
impl World {
pub fn all_objects(
&mut self,
) -> std::iter::Chain<std::iter::Once<&Object>, std::slice::Iter<'_, Object>> {
std::iter::once(&self.player).chain(self.npcs.iter())
}
}
But the exact type usually doesn't matter with iterators, so you can simply specify that your function returns some kind of iterator:
struct Object;
struct World {
player: Object,
npcs: Vec<Object>,
}
impl World {
pub fn all_objects(&mut self) -> impl Iterator<Item = &Object> {
std::iter::once(&self.player).chain(self.npcs.iter())
}
}
(Permalink to the playground)
This is also more flexible, as it will let you change the implementation without affecting the users of the function.

Can Rust constant expressions use traits like Default?

This code gives an error:
#[derive(Default)]
struct A {
b: Option<()>,
c: Option<()>,
}
const a: A = A {
b: None,
..Default::default()
};
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> src/lib.rs:9:7
|
9 | ..Default::default()
| ^^^^^^^^^^^^^^^^^^
In this small example it's not a big problem, but if I have a struct composed by multiple structs that implement the Default trait, not being able to use it becomes at minimum an inconvenience.
While I could write this, it wouldn't have the flexibility that Default provides:
impl A {
const fn new(b: Option<()>) -> Self {
A { b, c: None }
}
}
const a: A = A::new(None);
Is there any way to avoid doing that?
The ..Default::default() syntax is not restricted to Default::default(), so you can write a const fn default-like function and use that inside of a constant:
struct A {
b: Option<()>,
c: Option<()>,
}
impl A {
const fn new() -> A {
A {
b: None,
c: None,
}
}
}
impl Default for A {
fn default() -> A {
// implementing using new() instead of #[derive]
// to avoid diverging implementations
A::new()
}
}
const a: A = A {
b: None,
..A::new()
};
Run in Playground
No, it is not possible to use traits in a constant context. This is still being discussed in RFC #2632 — Calling methods on generic parameters of const fns.
See also:
Can I use const with overloading operators in Rust?

How can a Rust module have the same name as a const in the same namespace?

I came across some code in a piece of published code that had something like the following structure (which compiles and runs fine):
pub mod foo {
pub const BAR: u32 = 53;
#[allow(non_snake_case)]
pub mod BAR {
pub fn eep() {
println!("This is attached to BAR");
}
}
}
fn main() {
println!("Hello, world!, {}", foo::BAR);
foo::BAR::eep();
}
This seems strange and interesting to me. The strange bit being BAR being defined as both a const and a mod.
Is this idiomatic Rust?
What is going on here? Should I be able to find out about this in the docs? When is such a pattern valid?
I can see that this might be useful, but is there some really compelling use case?
No, it's not idiomatic, and the compiler already tells you this:
warning: module `BAR` should have a snake case name
--> src/main.rs:4:13
|
4 | pub mod BAR {
| ^^^ help: convert the identifier to snake case: `bar`
|
= note: #[warn(non_snake_case)] on by default
The warning has been silenced in the code you have presented, for whatever reason.
normally whilst programming one can't attach the same label to multiple constructs in the same namespace
That's correct. Modules and constants are in different namespaces. There are three namespaces:
types
values
macros
fn main() {
macro_rules! BAR { () => {} }
mod BAR {}
let BAR = 1;
}
Modules are in the type namespace.
I don't understand what BAR is. Is it a module, or is it a const?
There's one of each.
See also:
Why does a module with a submodule and a function with conflicting names work?
I'd probably write this:
pub mod foo {
use std::fmt;
pub const BAR: Bar = Bar(53);
pub struct Bar(u32);
impl Bar {
pub fn eep(&self) {
println!("This is attached to Bar");
}
}
impl fmt::Display for Bar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
}
fn main() {
println!("Hello, world!, {}", foo::BAR);
foo::BAR.eep();
}

What is 'self: Box<Self>' on a method? [duplicate]

I wanted to create a method that only works where the self parameter was an Rc. I saw that I could use Box, so I thought I might try to mimic how that works:
use std::rc::Rc;
use std::sync::Arc;
struct Bar;
impl Bar {
fn consuming(self) {}
fn reference(&self) {}
fn mutable_reference(&mut self) {}
fn boxed(self: Box<Bar>) {}
fn ref_count(self: Rc<Bar>) {}
fn atomic_ref_count(self: Arc<Bar>) {}
}
fn main() {}
Yields these errors:
error[E0308]: mismatched method receiver
--> a.rs:11:18
|
11 | fn ref_count(self: Rc<Bar>) {}
| ^^^^ expected struct `Bar`, found struct `std::rc::Rc`
|
= note: expected type `Bar`
= note: found type `std::rc::Rc<Bar>`
error[E0308]: mismatched method receiver
--> a.rs:12:25
|
12 | fn atomic_ref_count(self: Arc<Bar>) {}
| ^^^^ expected struct `Bar`, found struct `std::sync::Arc`
|
= note: expected type `Bar`
= note: found type `std::sync::Arc<Bar>`
This is with Rust 1.15.1.
Before Rust 1.33, there are only four valid method receivers:
struct Foo;
impl Foo {
fn by_val(self: Foo) {} // a.k.a. by_val(self)
fn by_ref(self: &Foo) {} // a.k.a. by_ref(&self)
fn by_mut_ref(self: &mut Foo) {} // a.k.a. by_mut_ref(&mut self)
fn by_box(self: Box<Foo>) {} // no short form
}
fn main() {}
Originally, Rust didn't have this explicit self form, only self, &self, &mut self and ~self (the old name for Box). This changed so that only by-value and by-references have the short-hand built-in syntax, since they are the common cases, and have very key language properties, while all smart pointers (including Box) require the explicit form.
As of Rust 1.33, some additional selected types are available for use as self:
Rc
Arc
Pin
This means that the original example now works:
use std::{rc::Rc, sync::Arc};
struct Bar;
impl Bar {
fn consuming(self) { println!("self") }
fn reference(&self) { println!("&self") }
fn mut_reference(&mut self) { println!("&mut self") }
fn boxed(self: Box<Bar>) { println!("Box") }
fn ref_count(self: Rc<Bar>) { println!("Rc") }
fn atomic_ref_count(self: Arc<Bar>) { println!("Arc") }
}
fn main() {
Bar.consuming();
Bar.reference();
Bar.mut_reference();
Box::new(Bar).boxed();
Rc::new(Bar).ref_count();
Arc::new(Bar).atomic_ref_count();
}
However, the impl handling hasn't yet been fully generalised to match the syntax, so user-created types still don't work. Progress on this is being made under the feature flag arbitrary_self_types and discussion is taking place in the tracking issue 44874.
(Something to look forward to!)
It's now possible to use arbitrary types for self, including Arc<Self>, but the feature is considered unstable and thus requires adding this crate attribute:
#![feature(arbitrary_self_types)]
Using feature crate attributes requires using nightly Rust.

Resources