6

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),
    // ...
}
joel
  • 6,359
  • 2
  • 30
  • 55
  • 1
    Complement: [Rust by example: The ref pattern](https://stackoverflow.com/questions/27911656/rust-by-example-the-ref-pattern) – Denys Séguret Oct 08 '19 at 19:15
  • 1
    I'm not sure what you mean by "avoidable". Is it necessary in *this* code? No. Is it necessary in *any* code? Kind of, yes, depending on how much you're willing to rewrite to avoid writing `ref`. Could the language have been designed without it? I suppose so, especially if something like default binding modes had been part of the original design, but that doesn't seem like a particularly interesting counterfactual to me... What's the point of this question? – trent Oct 08 '19 at 19:37

1 Answers1

11

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:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • This seems to suggest that only one of `ref` or `move` would have been strictly necessary, possibly at the cost of having the wrong default in certain scenarios. – Ryan1729 Oct 09 '19 at 20:08
  • @Ryan1729 recall that `move` is not a valid keyword in pattern matching today. We are already in a state where only one (`ref`) is necessary and we have the wrong default in certain scenarios. The OPs implicit assertion is that there's a world where no keyword is needed and the language can just Do The Right Thing. – Shepmaster Oct 09 '19 at 20:11
  • Why not using & instead of `ref` here?: if let &mut Some(ref mut inner) = &mut val { – frankelot Mar 16 '23 at 06:06
  • @frankelot I think the already-linked question and answer [Why is `ref` used instead of an asterisk in pattern matching?](https://stackoverflow.com/q/58184472/155423) covers that. Let me know if there's something missing. – Shepmaster Apr 14 '23 at 20:49