"Can't move out of borrowed content" explanation

Hello fellow Rustaceans,

I’m a new-comer to the language and try to wrap my head around the concept of borrowing.

I have the following code that works for me (after reading the rust-book & learning about cloning):

fn update(_app: &App, model: &mut Model, _update: Update) {
    let mut messages: Vec<osc::Message> = vec![];
    
    for (packet, _addr) in model.receiver.try_iter() {
        packet.unfold(&mut messages)
    }
    for m in messages.iter() {
        match &m.args {
            Some(values) => {
                for v in values.iter() {
                    match v.clone().int() {
                        Some(rssi) => {
                            model.rssi.push(rssi as u16);
                        }
                        _ => {}
                    }
                }
            }
            _ => {}
        }
    }
}

Now the error I try to understand is the need to invoke .clone() on the value v of type

https://docs.rs/nannou/0.9.0/nannou/osc/enum.Type.html

If I look at the method declaration

https://docs.rs/nannou/0.9.0/nannou/osc/enum.Type.html#method.int

it appears as if the culprit is the self. Instead of using &self. This makes the call want to take ownership.

Am I correct in assuming that (for this case) one could implement method.int taking a reference as reading the underlying bytes of the OSC message and converting to i32 is actually not something that needs the move?

Technically it would be possible, but there are more complex types in this enum, like String or Blob, where actual moving stuff out is much more efficient due to avoiding additional allocation and expensive copy. Obviously it would be possible, that some methods would take self (where copy is not cheap) and others &self (where copy is almost free), but it would be inconsistent.

The question is why there is no additional interface here taking &self and returning Option<&T>, this looks like pretty valid and easy to do for this enum.

I’m happy with the design decision, it was more about my reasoning being correct.

I do not understand what the Option<&T would be about. Why would it improve the situation here?

I can imagine cases, where I don’t want internal object for my ownership, I just want to check some predicate on it. Even in your case, there is good to know that this clone is not as cheap as cloning int - it has to do dispatch basing on value on RT, because in this place the interior of enum may be String or Vec<u8>, and cloning them involves additional actions.

Obviously if you are sure there is always an int, the overhead is probably not an issue here, but it is there and might be easly avoided by ref based API. And after all it is easy to make Some<T> form Some<&T> - there is Option::cloned.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.