Is it possible to have it compile given the create_container method signature? The stream function from ChildA doesn't compile because the code has been stripped down and omitted field_a and field_b for demonstration purposes, but it is something like that.
I've tried many different variations but I've been unable to have it compile and at the same time maintain the code structure that I do control.
It would be helpful if you could provide the exact error message. Without that or a fully working example on the playground the best we can usually do is guess what the problem might be.
The only thing that really sticks out in a quick once-over is that you seem to be attempting to move child_a out of self.parent. If that's the case, Rust will reject the code because it would be invalid to transfer ownership and then later attempt to use self.parent.child_a.
Cloning child_a might be a solution if you do not expect the external container and your Parent to reference the same child_a struct. If you do need to reference the child from both places, your ExternalStreamTraitImpl could hold a reference to a ChildA type instead of holding ownership over one. Shared ownership is another option, and can be easier to deal with.
Again, this all just shooting in the dark. More info would be helpful.
You are totally right, let me fix that. I'll update my original post with a link to a full example in the playground, though it'll not compile because I don't know how.
I have updated my original post with a link to the playground. I am not sure if that is sufficient, but if not I can continue adding more realism to the demo. It's just that there are many parts to it and try to have it all in a small demo is difficult.
I was able to identify the issue with moving child_a out of self.inner, and using a reference-counting pointer worked for that.
The other thing I wasn't able to identify was the ExternalStreamTrait::bar implementation trying to borrow from self.inner for longer than necessary. This is fixed with a few lifetime annotations.
I started with Rc to turn the move into a cheap clone:
This is great. Thank you very much for your time. I'll try to adapt this to the original code and see if it works as clean as here because the full code has more thorns in it.
Yes, that is usually the expected case! The takeaway is that it's ok to use shared ownership if necessary (in this case I think it is...) and that the lifetime annotations can be finicky. The real trick to understanding the latter is to just think about how references relate to one another1; in the original code, the lifetime annotation claimed the input and output had an equivalent lifetime. I changed it so the lifetimes between input and output are unique.
1 Well, this has been the way I've become most comfortable with lifetimes. I don't know if this is common, or even "correct", but it works out for me in most cases.