joel
joel

Reputation: 7867

What can ref do that references couldn't?

What can ref do that references couldn't? Could

match value.try_thing() {
    &Some(ref e) => do_stuff(e),
    // ...
}

not be equally expressed by

match value.try_thing() {
    &Some(e) => do_stuff(&e),
    // ...
}

Upvotes: 8

Views: 4020

Answers (1)

Shepmaster
Shepmaster

Reputation: 430634

Editor's note — this answer was posted when the question was titled "Was Rust's ref keyword avoidable?". The OP has since changed the title, making the phrasing of the answer less sensible.

No, it is not avoidable with your proposed syntax. Your syntax does not allow for taking a reference when otherwise a move would be permissable. In this example, inner is a copy of the integer from val and changing it has no effect on val:

fn main() {
    let mut val = Some(42);
    
    if let &mut Some(mut inner) = &mut val {
        inner += 1;
    }
    
    println!("{:?}", val); // Some(42)
}

The ref keyword is needed to force taking a reference:

fn main() {
    let mut val = Some(42);
    
    if let &mut Some(ref mut inner) = &mut val {
        *inner += 1;
    }
    
    println!("{:?}", val); // Some(43)
}

Match ergonomics allows writing this in a simpler manner:

fn main() {
    let mut val = Some(42);
    
    if let Some(inner) = &mut val {
        *inner += 1;
    }
    
    println!("{:?}", val);
}

However, if we started with only this syntax, then we'd probably have the opposite problem and keyword, one to force a move instead; perhaps Some(move inner). In that alternate universe, there'd be a question asking if the move keyword was avoidable.

See also:

Upvotes: 12

Related Questions