Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

71%
+3 −0
Q&A Recursive traversal of composite tree of mutable "trait objects"?

I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components and these are structured using the Composite design pattern. The composite...

2 answers  ·  posted 6mo ago by ghost-in-the-zsh‭  ·  last activity 2mo ago by ghost-in-the-zsh‭

Question rust
#7: Post edited by user avatar ghost-in-the-zsh‭ · 2024-07-03T11:47:39Z (6 months ago)
Remove numbering from diagnostic message, which could be confused with the list
  • I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components and these are structured using the Composite design pattern. The composite type from the pattern is called `Component` in the service:
  • ```rust
  • pub trait Component:
  • // ...
  • + Debug
  • + Sync
  • + Send
  • + 'static
  • {
  • fn components(&self) -> Vec<&dyn Component> {
  • vec![]
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • vec![]
  • }
  • }
  • ```
  • There are several different concrete types that implement this trait. For example:
  • ```rust
  • #[derive(Debug)]
  • pub struct KeypadModel {
  • components: Vec<Box<dyn Component>>,
  • }
  • // ...
  • impl KeypadModel {
  • pub fn new() -> Self {
  • debug!("Creating {} ...", stringify!(KeypadModel));
  • Self {
  • components: vec![
  • Box::new(ButtonGroupModel::new()),
  • Box::new(NumberpadModel::new()),
  • ],
  • }
  • }
  • }
  • ```
  • The problem is that the elements of the `components` vector are *not concrete types*; they *must be trait objects*. To clarify what I'm after, I have [a working example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3228f2b58cc2580fa6bb9a2d7a1ab5c7) using *same concrete type*, but the actual system needs a version that works with trait objects.
  • So, I'm left with something like this (which doesn't work):
  • ```
  • impl Component for KeypadModel {
  • fn components(&self) -> Vec<&dyn Component> {
  • fn subtree(root: &dyn Component) -> Vec<&dyn Component> {
  • let mut v = vec![];
  • root.components // !! Error: See below !!
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v.push(root);
  • v
  • }
  • let mut v = vec![];
  • self.components
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • todo!() // ??
  • }
  • }
  • ```
  • The error is that the code wants/expects `root.components()`, which is the *method* that belongs to the trait, but, I need access to the `root.components` *field*, which belongs to the concrete type.
  • **The question is:** How can I traverse[^1] the trait object tree structure, starting at an arbitrary `root` node, to generate a vector of *all[^2]* descendants?
  • Please, note:
  • 1. Trying to use the `root.components()` method shows the following error:
  • ```
  • Diagnostics:
  • 1. cannot return value referencing temporary value
  • returns a value referencing data owned by the current function [E0515]
  • ```
  • 2. Even if it weren't an error, the recursive logic would be incorrect, b/c deeper leaf nodes would be added more than once. (This is easier for me to show with an initial [Python prototype](https://pastebin.com/GYzvEiaY) I had, which can be run at https://playground.programiz.com)
  • 3. The composite/container types hold *different* concrete types in their `components` vector, which is why the vector *must* work with trait objects.
  • 4. Modifying the `Component` trait and/or concrete types implementing it *might* be feasible.
  • [^1]: Recursively is likely more natural, but an iterative solution is also OK.
  • [^2]: Including composite/non-leaf nodes.
  • I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components and these are structured using the Composite design pattern. The composite type from the pattern is called `Component` in the service:
  • ```rust
  • pub trait Component:
  • // ...
  • + Debug
  • + Sync
  • + Send
  • + 'static
  • {
  • fn components(&self) -> Vec<&dyn Component> {
  • vec![]
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • vec![]
  • }
  • }
  • ```
  • There are several different concrete types that implement this trait. For example:
  • ```rust
  • #[derive(Debug)]
  • pub struct KeypadModel {
  • components: Vec<Box<dyn Component>>,
  • }
  • // ...
  • impl KeypadModel {
  • pub fn new() -> Self {
  • debug!("Creating {} ...", stringify!(KeypadModel));
  • Self {
  • components: vec![
  • Box::new(ButtonGroupModel::new()),
  • Box::new(NumberpadModel::new()),
  • ],
  • }
  • }
  • }
  • ```
  • The problem is that the elements of the `components` vector are *not concrete types*; they *must be trait objects*. To clarify what I'm after, I have [a working example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3228f2b58cc2580fa6bb9a2d7a1ab5c7) using *same concrete type*, but the actual system needs a version that works with trait objects.
  • So, I'm left with something like this (which doesn't work):
  • ```
  • impl Component for KeypadModel {
  • fn components(&self) -> Vec<&dyn Component> {
  • fn subtree(root: &dyn Component) -> Vec<&dyn Component> {
  • let mut v = vec![];
  • root.components // !! Error: See below !!
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v.push(root);
  • v
  • }
  • let mut v = vec![];
  • self.components
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • todo!() // ??
  • }
  • }
  • ```
  • The error is that the code wants/expects `root.components()`, which is the *method* that belongs to the trait, but, I need access to the `root.components` *field*, which belongs to the concrete type.
  • **The question is:** How can I traverse[^1] the trait object tree structure, starting at an arbitrary `root` node, to generate a vector of *all[^2]* descendants?
  • Please, note:
  • 1. Trying to use the `root.components()` method shows the following error:
  • ```
  • Diagnostics:
  • cannot return value referencing temporary value
  • returns a value referencing data owned by the current function [E0515]
  • ```
  • 2. Even if it weren't an error, the recursive logic would be incorrect, b/c deeper leaf nodes would be added more than once. (This is easier for me to show with an initial [Python prototype](https://pastebin.com/GYzvEiaY) I had, which can be run at https://playground.programiz.com)
  • 3. The composite/container types hold *different* concrete types in their `components` vector, which is why the vector *must* work with trait objects.
  • 4. Modifying the `Component` trait and/or concrete types implementing it *might* be feasible.
  • [^1]: Recursively is likely more natural, but an iterative solution is also OK.
  • [^2]: Including composite/non-leaf nodes.
#6: Post edited by user avatar ghost-in-the-zsh‭ · 2024-07-03T11:46:51Z (6 months ago)
Improve wording
  • I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components and these are structured using the Composite design pattern. The composite type from the pattern is called `Component` in the service:
  • ```rust
  • pub trait Component:
  • // ...
  • + Debug
  • + Sync
  • + Send
  • + 'static
  • {
  • fn components(&self) -> Vec<&dyn Component> {
  • vec![]
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • vec![]
  • }
  • }
  • ```
  • There are several different concrete types that implement this trait. For example:
  • ```rust
  • #[derive(Debug)]
  • pub struct KeypadModel {
  • components: Vec<Box<dyn Component>>,
  • }
  • // ...
  • impl KeypadModel {
  • pub fn new() -> Self {
  • debug!("Creating {} ...", stringify!(KeypadModel));
  • Self {
  • components: vec![
  • Box::new(ButtonGroupModel::new()),
  • Box::new(NumberpadModel::new()),
  • ],
  • }
  • }
  • }
  • ```
  • The problem is that the elements of the `components` vector are *not concrete types*; they *must be trait objects*. I have [a working example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3228f2b58cc2580fa6bb9a2d7a1ab5c7) when using a vector of the *same concrete type*, but that's not feasible in this system.
  • So, I'm left with something like this (which doesn't work):
  • ```
  • impl Component for KeypadModel {
  • fn components(&self) -> Vec<&dyn Component> {
  • fn subtree(root: &dyn Component) -> Vec<&dyn Component> {
  • let mut v = vec![];
  • root.components // !! Error: See below !!
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v.push(root);
  • v
  • }
  • let mut v = vec![];
  • self.components
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • todo!() // ??
  • }
  • }
  • ```
  • The error is that the code wants/expects `root.components()`, which is the *method* that belongs to the trait, but, I need access to the `root.components` *field*, which belongs to the concrete type.
  • **The question is:** How can I traverse[^1] the trait object tree structure, starting at an arbitrary `root` node, to generate a vector of *all[^2]* descendants?
  • Please, note:
  • 1. Trying to use the `root.components()` method shows the following error:
  • ```
  • Diagnostics:
  • 1. cannot return value referencing temporary value
  • returns a value referencing data owned by the current function [E0515]
  • ```
  • 2. Even if it weren't an error, the recursive logic would be incorrect, b/c deeper leaf nodes would be added more than once. (This is easier for me to show with an initial [Python prototype](https://pastebin.com/GYzvEiaY) I had, which can be run at https://playground.programiz.com)
  • 3. The composite/container types hold *different* concrete types in their `components` vector, which is why the vector *must* work with trait objects.
  • 4. Modifying the `Component` trait and/or concrete types implementing it *might* be feasible.
  • [^1]: Recursively is likely more natural, but an iterative solution is also OK.
  • [^2]: Including composite/non-leaf nodes.
  • I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components and these are structured using the Composite design pattern. The composite type from the pattern is called `Component` in the service:
  • ```rust
  • pub trait Component:
  • // ...
  • + Debug
  • + Sync
  • + Send
  • + 'static
  • {
  • fn components(&self) -> Vec<&dyn Component> {
  • vec![]
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • vec![]
  • }
  • }
  • ```
  • There are several different concrete types that implement this trait. For example:
  • ```rust
  • #[derive(Debug)]
  • pub struct KeypadModel {
  • components: Vec<Box<dyn Component>>,
  • }
  • // ...
  • impl KeypadModel {
  • pub fn new() -> Self {
  • debug!("Creating {} ...", stringify!(KeypadModel));
  • Self {
  • components: vec![
  • Box::new(ButtonGroupModel::new()),
  • Box::new(NumberpadModel::new()),
  • ],
  • }
  • }
  • }
  • ```
  • The problem is that the elements of the `components` vector are *not concrete types*; they *must be trait objects*. To clarify what I'm after, I have [a working example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3228f2b58cc2580fa6bb9a2d7a1ab5c7) using *same concrete type*, but the actual system needs a version that works with trait objects.
  • So, I'm left with something like this (which doesn't work):
  • ```
  • impl Component for KeypadModel {
  • fn components(&self) -> Vec<&dyn Component> {
  • fn subtree(root: &dyn Component) -> Vec<&dyn Component> {
  • let mut v = vec![];
  • root.components // !! Error: See below !!
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v.push(root);
  • v
  • }
  • let mut v = vec![];
  • self.components
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • todo!() // ??
  • }
  • }
  • ```
  • The error is that the code wants/expects `root.components()`, which is the *method* that belongs to the trait, but, I need access to the `root.components` *field*, which belongs to the concrete type.
  • **The question is:** How can I traverse[^1] the trait object tree structure, starting at an arbitrary `root` node, to generate a vector of *all[^2]* descendants?
  • Please, note:
  • 1. Trying to use the `root.components()` method shows the following error:
  • ```
  • Diagnostics:
  • 1. cannot return value referencing temporary value
  • returns a value referencing data owned by the current function [E0515]
  • ```
  • 2. Even if it weren't an error, the recursive logic would be incorrect, b/c deeper leaf nodes would be added more than once. (This is easier for me to show with an initial [Python prototype](https://pastebin.com/GYzvEiaY) I had, which can be run at https://playground.programiz.com)
  • 3. The composite/container types hold *different* concrete types in their `components` vector, which is why the vector *must* work with trait objects.
  • 4. Modifying the `Component` trait and/or concrete types implementing it *might* be feasible.
  • [^1]: Recursively is likely more natural, but an iterative solution is also OK.
  • [^2]: Including composite/non-leaf nodes.
#5: Post edited by user avatar ghost-in-the-zsh‭ · 2024-07-03T11:30:58Z (6 months ago)
Corrected some errors, added playground example links, and error message diagnostics from LSP.
  • I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components, and these are structured using the Composite design pattern. The composite type from the pattern is called `Component` in the service:
  • ```rust
  • pub trait Component:
  • // ...
  • + Debug
  • + Sync
  • + Send
  • + 'static
  • {
  • fn components(&self) -> Vec<&dyn Component> {
  • vec![]
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • vec![]
  • }
  • }
  • ```
  • There are several different concrete types that implement this trait. For example:
  • ```rust
  • #[derive(Debug)]
  • pub struct KeypadModel {
  • components: Vec<Box<dyn Component>>,
  • }
  • // ...
  • impl KeypadModel {
  • pub fn new() -> Self {
  • debug!("Creating {} ...", stringify!(KeypadModel));
  • Self {
  • components: vec![
  • Box::new(ButtonGroupModel::new()),
  • Box::new(NumberpadModel::new()),
  • ],
  • }
  • }
  • }
  • ```
  • The problem is that the elements of the `components` vector are *not concrete types*; they *must be trait objects*. I have a working example (not listed) when using a vector of the same concrete type, but that's not feasible in this system.
  • So, I'm left with something like this (which doesn't work):
  • ```
  • impl Component for KeypadModel {
  • fn components(&self) -> Vec<&dyn Component> {
  • todo!()
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • fn subtree_mut(root: &mut dyn Component) -> Vec<&mut dyn Component> {
  • let mut v = vec![];
  • // !! Error Here: Explanation below !!
  • match root.components.is_empty() {
  • true => v.push(root),
  • false => root.components
  • .iter_mut()
  • .for_each(|c| v.append(&mut subtree_mut(c.deref_mut())))
  • }
  • v
  • }
  • let mut v = vec![];
  • self.components
  • .iter_mut()
  • .for_each(|c| v.append(&mut subtree_mut(c.deref_mut())));
  • v
  • }
  • }
  • ```
  • The error is that the code wants/expects `root.components_mut()`, which is the *method* that belongs to the trait, but I need access to the `root.components` *field*, which belongs to the concrete type.
  • **The question is:** How can I traverse[^1] the trait object tree structure, starting at an arbitrary `root` node, to generate a vector of *all* descendants objects?
  • Please, note the following:
  • 1. Using `root.components_mut()` would create a temporary value owned by the function and trying to return that is an error.
  • 2. Even if it weren't an error, the recursive logic would be incorrect and several objects would be added more than once.
  • 3. The composite/container types hold *different* concrete types in their `components` vector, which is why the vector *must* work with trait objects.
  • 4. Modifying the `Component` trait and/or concrete types implementing it may be feasible.
  • [^1]: Recursively is likely more natural, but an iterative solution is also OK.
  • I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components and these are structured using the Composite design pattern. The composite type from the pattern is called `Component` in the service:
  • ```rust
  • pub trait Component:
  • // ...
  • + Debug
  • + Sync
  • + Send
  • + 'static
  • {
  • fn components(&self) -> Vec<&dyn Component> {
  • vec![]
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • vec![]
  • }
  • }
  • ```
  • There are several different concrete types that implement this trait. For example:
  • ```rust
  • #[derive(Debug)]
  • pub struct KeypadModel {
  • components: Vec<Box<dyn Component>>,
  • }
  • // ...
  • impl KeypadModel {
  • pub fn new() -> Self {
  • debug!("Creating {} ...", stringify!(KeypadModel));
  • Self {
  • components: vec![
  • Box::new(ButtonGroupModel::new()),
  • Box::new(NumberpadModel::new()),
  • ],
  • }
  • }
  • }
  • ```
  • The problem is that the elements of the `components` vector are *not concrete types*; they *must be trait objects*. I have [a working example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3228f2b58cc2580fa6bb9a2d7a1ab5c7) when using a vector of the *same concrete type*, but that's not feasible in this system.
  • So, I'm left with something like this (which doesn't work):
  • ```
  • impl Component for KeypadModel {
  • fn components(&self) -> Vec<&dyn Component> {
  • fn subtree(root: &dyn Component) -> Vec<&dyn Component> {
  • let mut v = vec![];
  • root.components // !! Error: See below !!
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v.push(root);
  • v
  • }
  • let mut v = vec![];
  • self.components
  • .iter()
  • .for_each(|m| v.append(&mut Self::subtree(m)));
  • v
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • todo!() // ??
  • }
  • }
  • ```
  • The error is that the code wants/expects `root.components()`, which is the *method* that belongs to the trait, but, I need access to the `root.components` *field*, which belongs to the concrete type.
  • **The question is:** How can I traverse[^1] the trait object tree structure, starting at an arbitrary `root` node, to generate a vector of *all[^2]* descendants?
  • Please, note:
  • 1. Trying to use the `root.components()` method shows the following error:
  • ```
  • Diagnostics:
  • 1. cannot return value referencing temporary value
  • returns a value referencing data owned by the current function [E0515]
  • ```
  • 2. Even if it weren't an error, the recursive logic would be incorrect, b/c deeper leaf nodes would be added more than once. (This is easier for me to show with an initial [Python prototype](https://pastebin.com/GYzvEiaY) I had, which can be run at https://playground.programiz.com)
  • 3. The composite/container types hold *different* concrete types in their `components` vector, which is why the vector *must* work with trait objects.
  • 4. Modifying the `Component` trait and/or concrete types implementing it *might* be feasible.
  • [^1]: Recursively is likely more natural, but an iterative solution is also OK.
  • [^2]: Including composite/non-leaf nodes.
#4: Post edited by user avatar Andreas witnessed the end of the world today‭ · 2024-07-03T10:24:47Z (6 months ago)
Remove fluff
Recursive traversal of composite tree of mutable "trait objects"?
  • Hi,
  • I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components and these are structured using the Composite design pattern. The composite type from the pattern is called `Component` in the service:
  • ```rust
  • pub trait Component:
  • // ...
  • + Debug
  • + Sync
  • + Send
  • + 'static
  • {
  • fn components(&self) -> Vec<&dyn Component> {
  • vec![]
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • vec![]
  • }
  • }
  • ```
  • There're several different concrete types that implement this trait. For example:
  • ```rust
  • #[derive(Debug)]
  • pub struct KeypadModel {
  • components: Vec<Box<dyn Component>>,
  • }
  • // ...
  • impl KeypadModel {
  • pub fn new() -> Self {
  • debug!("Creating {} ...", stringify!(KeypadModel));
  • Self {
  • components: vec![
  • Box::new(ButtonGroupModel::new()),
  • Box::new(NumberpadModel::new()),
  • ],
  • }
  • }
  • }
  • ```
  • The problem is that the elements of the `components` vector are *not concrete types*; they *must be trait objects*. I have a working example (not listed) when using a vector of the same concrete type, but that's not feasible in this system.
  • So, I'm left with something like this (which doesn't work):
  • ```
  • impl Component for KeypadModel {
  • fn components(&self) -> Vec<&dyn Component> {
  • todo!()
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • fn subtree_mut(root: &mut dyn Component) -> Vec<&mut dyn Component> {
  • let mut v = vec![];
  • // !! Error Here: Explanation below !!
  • match root.components.is_empty() {
  • true => v.push(root),
  • false => root.components
  • .iter_mut()
  • .for_each(|c| v.append(&mut subtree_mut(c.deref_mut())))
  • }
  • v
  • }
  • let mut v = vec![];
  • self.components
  • .iter_mut()
  • .for_each(|c| v.append(&mut subtree_mut(c.deref_mut())));
  • v
  • }
  • }
  • ```
  • The error is that the code wants/expects `root.components_mut()`, which is the *method* that belongs to the trait, but I need access to the `root.components` *field*, which belongs to the concrete type.
  • **The question is:** How can I traverse[^1] the trait object tree structure, starting at an arbitrary `root` node, to generate a vector of *all* descendants objects?
  • Please, note the following:
  • 1. Using `root.components_mut()` would create a temporary value owned by the function and trying to return that is an error.
  • 2. Even if it weren't an error, the recursive logic would be incorrect and several objects would be added more than once.
  • 3. The composite/container types hold *different* concrete types in their `components` vector, which is why the vector *must* work with trait objects.
  • 4. Modifying the `Component` trait and/or concrete types implementing it may be feasible.
  • I hope this is clear enough, but I can add clarifications, and a working example that uses concrete (not trait) types, if needed.
  • Thank you in advance for the help.
  • [^1]: Recursively is likely more natural, but an iterative solution is also OK.
  • I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components, and these are structured using the Composite design pattern. The composite type from the pattern is called `Component` in the service:
  • ```rust
  • pub trait Component:
  • // ...
  • + Debug
  • + Sync
  • + Send
  • + 'static
  • {
  • fn components(&self) -> Vec<&dyn Component> {
  • vec![]
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • vec![]
  • }
  • }
  • ```
  • There are several different concrete types that implement this trait. For example:
  • ```rust
  • #[derive(Debug)]
  • pub struct KeypadModel {
  • components: Vec<Box<dyn Component>>,
  • }
  • // ...
  • impl KeypadModel {
  • pub fn new() -> Self {
  • debug!("Creating {} ...", stringify!(KeypadModel));
  • Self {
  • components: vec![
  • Box::new(ButtonGroupModel::new()),
  • Box::new(NumberpadModel::new()),
  • ],
  • }
  • }
  • }
  • ```
  • The problem is that the elements of the `components` vector are *not concrete types*; they *must be trait objects*. I have a working example (not listed) when using a vector of the same concrete type, but that's not feasible in this system.
  • So, I'm left with something like this (which doesn't work):
  • ```
  • impl Component for KeypadModel {
  • fn components(&self) -> Vec<&dyn Component> {
  • todo!()
  • }
  • fn components_mut(&mut self) -> Vec<&mut dyn Component> {
  • fn subtree_mut(root: &mut dyn Component) -> Vec<&mut dyn Component> {
  • let mut v = vec![];
  • // !! Error Here: Explanation below !!
  • match root.components.is_empty() {
  • true => v.push(root),
  • false => root.components
  • .iter_mut()
  • .for_each(|c| v.append(&mut subtree_mut(c.deref_mut())))
  • }
  • v
  • }
  • let mut v = vec![];
  • self.components
  • .iter_mut()
  • .for_each(|c| v.append(&mut subtree_mut(c.deref_mut())));
  • v
  • }
  • }
  • ```
  • The error is that the code wants/expects `root.components_mut()`, which is the *method* that belongs to the trait, but I need access to the `root.components` *field*, which belongs to the concrete type.
  • **The question is:** How can I traverse[^1] the trait object tree structure, starting at an arbitrary `root` node, to generate a vector of *all* descendants objects?
  • Please, note the following:
  • 1. Using `root.components_mut()` would create a temporary value owned by the function and trying to return that is an error.
  • 2. Even if it weren't an error, the recursive logic would be incorrect and several objects would be added more than once.
  • 3. The composite/container types hold *different* concrete types in their `components` vector, which is why the vector *must* work with trait objects.
  • 4. Modifying the `Component` trait and/or concrete types implementing it may be feasible.
  • [^1]: Recursively is likely more natural, but an iterative solution is also OK.
#3: Nominated for promotion by user avatar Alexei‭ · 2024-07-03T07:37:37Z (6 months ago)
#2: Post edited by user avatar ghost-in-the-zsh‭ · 2024-07-03T00:45:51Z (6 months ago)
Fix title typo
  • Recursive traversal of composite tree of mutable "trait objects"
  • Recursive traversal of composite tree of mutable "trait objects"?
#1: Initial revision by user avatar ghost-in-the-zsh‭ · 2024-07-03T00:44:07Z (6 months ago)
Recursive traversal of composite tree of mutable "trait objects"
Hi,

I'm working on a background service/daemon for an embedded device, in Rust. The daemon manages several hardware components and these are structured using the Composite design pattern. The composite type from the pattern is called `Component` in the service:

```rust
pub trait Component:
    // ...
    + Debug
    + Sync
    + Send
    + 'static
{
    fn components(&self) -> Vec<&dyn Component> {
        vec![]
    }

    fn components_mut(&mut self) -> Vec<&mut dyn Component> {
        vec![]
    }
}
```

There're several different concrete types that implement this trait. For example:

```rust
#[derive(Debug)]
pub struct KeypadModel {
    components: Vec<Box<dyn Component>>,
}
// ...
impl KeypadModel {
    pub fn new() -> Self {
        debug!("Creating {} ...", stringify!(KeypadModel));
        Self {
            components: vec![
                Box::new(ButtonGroupModel::new()),
                Box::new(NumberpadModel::new()),
            ],
        }
    }
}
```

The problem is that the elements of the `components` vector are *not concrete types*; they *must be trait objects*. I have a working example (not listed) when using a vector of the same concrete type, but that's not feasible in this system.

So, I'm left with something like this (which doesn't work):

```
impl Component for KeypadModel {
    fn components(&self) -> Vec<&dyn Component> {
        todo!()
    }

    fn components_mut(&mut self) -> Vec<&mut dyn Component> {
        fn subtree_mut(root: &mut dyn Component) -> Vec<&mut dyn Component> {
            let mut v = vec![];
            // !! Error Here: Explanation below !!
            match root.components.is_empty() {
                true => v.push(root),
                false => root.components 
                    .iter_mut()
                    .for_each(|c| v.append(&mut subtree_mut(c.deref_mut())))
            }
            v
        }

        let mut v = vec![];
        self.components
            .iter_mut()
            .for_each(|c| v.append(&mut subtree_mut(c.deref_mut())));
        v
    }
}
```

The error is that the code wants/expects `root.components_mut()`, which is the *method* that belongs to the trait, but I need access to the `root.components` *field*, which belongs to the concrete type.

**The question is:** How can I traverse[^1] the trait object tree structure, starting at an arbitrary `root` node, to generate a vector of *all* descendants objects?

Please, note the following:

1. Using `root.components_mut()` would create a temporary value owned by the function and trying to return that is an error.
2. Even if it weren't an error, the recursive logic would be incorrect and several objects would be added more than once.
3. The composite/container types hold *different* concrete types in their `components` vector, which is why the vector *must* work with trait objects.
4. Modifying the `Component` trait and/or concrete types implementing it may be feasible.

I hope this is clear enough, but I can add clarifications, and a working example that uses concrete (not trait) types, if needed.

Thank you in advance for the help.


[^1]: Recursively is likely more natural, but an iterative solution is also OK.