1

I have a struct App:

struct App { cmd: Command } 

that owns a command of type Command:

enum Command { Cmd1 { flag: bool } } 

(I use StructOpt to derive a command line interface from that.)

To execute the right command I have a function like this:

impl App { fn execute(&mut self) { match &self.cmd { Command::Cmd1 { flag } => self.do_cmd1(*flag) }; } } 

where I handle the actual execution in an extra function do_cmd1(&mut self, flag: bool) to keep execute clean. However, this does not work since in self.do_cmd1(*flag) I borrow self as mutable and also as immutable via *flag which belongs to cmd which in turn belongs to self.

My question is: What would be the proper way to access flag in do_cmd1 that respects the borrowing rules?

Clarification: I need this to also work for things like

enum Command { Cmd2 { text: String } } 

where the variant's field is not Copy.

1

3 Answers 3

1

If you move or copy the flag out of self before calling do_cmd1, the borrows don't need to overlap.

 fn execute(&mut self) { match self.cmd { Command::Cmd1 { flag } => self.do_cmd1(flag), }; } 

The only changes are removing the & from &self.cmd and the * from *flag.

The above works because bool is a Copy type. For types that are not Copy, you will need to do some extra work to ensure the borrows do not overlap, as in these related questions:

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer. You're right, this solution works for Copy types. It does not work for types like String which you might also like to have as a command parameter. I will clarify my question.
@Andreas I have edited the answer to add links to some other questions that I think answer the question. Do these help?
The two main strategies will probably be cloning the String inside the match and calling do_cmd1 outside (so the borrows aren't live at the same time), or redefining do_cmd1 to not borrow all of self (so the borrows don't refer to the same thing).
Thanks for pointing out those related questions. I agree with your conclusion about the two solutions that work in this case (since using StructOpt prevents altering the types in App and Command). @phimuemue's answer goes into a similar direction. I think, I like do_cmd1 not borrowing all of self best and am going to implement that. I wil accept your answer. Thanks again for the help!
0

This is a solution I have come up with, although I think there should be a better one:

Extend the Command enum in the following way:

impl Command { fn get_cmd1_flag(&self) -> Option<bool> { match &self { Command::Cmd1 { flag } => Some(*flag), _ => None } } } 

Then, alter the signature of do_cmd1 to do_cmd1(&mut self) (i.e. remove the flag argument). To access flag inside of do_cmd1 you can just call self.cmd.get_cmd1_flag() and handle the Option. Together with proper return types and use of the ? operator this is even quite comfortable to write.

What I dislike about this solution is that you somehow implement an own layer of type checking, which is why I think there should be a more elegant way. But at least this works.

Comments

0

Does do_cmd1 really need to be a method of App?

In other words: You may be able to separate the cmd and the "other", non-cmd part (let's call it Executor) and put them in different fields of your struct:

struct App { cmd: Command exe: Executor } impl App { fn execute(&mut self) { match &self.cmd { Command::Cmd1 { flag } => self.exe.do_cmd1(*flag) }; } } 

This way, it is clear which parts of self are actually borrowed mutably.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.