Hello, I have the following situation, that is best explained with the code below.
I have a struct with multiple similar fields, that I need to modify by calling a kind-of-setter method that calls other methods implemented on the struct.
This single setter method should modify the given field, however as I also require other methods implemented on the struct, I need to parse the struct instance as well as the reference to the field.
This doesn't work in Rust because now I have multiple mutable references to basically the same variable.
Are there other solutions that I'm not considering? *reference_to_field = 42; would work if I don't pass the reference to the struct instance along, however I need that to call the i_need_to_call_this method ...
Problems of this type should, when possible, be solved by making the borrows more specific. Not every function needs to be a method. Here is a “naive” application of that principle:
Of course, this may expose more detailed structure than you want to. Consider this the “just barely makes it work” version, and then refine it from there. To get more help, share with us more of the actual structure of your problem — what do the fields mean? Does i_need_to_call_this() modify multiple fields? Does your struct have any invariants?
You can write such a function in a way that the compiler will help you get it right.
let Self { foo, bar } = self;
match field {
Field::Foo => *foo = 0,
Field::Bar => *bar = 0,
}
This way, you will get an error reminding you to update the match, and thus the enum too, any time a field is added or removed.
Thanks for your answer, I will try modifying my code accordingly, I'm currently spamming &mut self in nearly every method. That's probably the root cause of this problem now.
a and y are registers of an emulated CPU, while foo is the program counter.
i_need_to_call_this represents emulated CPU instructions that do the same but affecting different registers (a & y).
So i_need_to_call_this writes / reads from another field which represents the RAM, changes foo.
My guess is that the enum will be a good way to handle this problem. You can think of this enum not as referring to fields but referring to registers, and being a small piece of the instruction decoding part of the problem, rather than something introduced purely for the sake of following borrowing rules.
I will be using both of your recommendations, restructuring part of the code to avoid excessive usage of &mut self and usage of the an enum to represent register usage.
Thank you for your help!