Something I have been wondering a bit is the rules for when to use ref instead of &
Take this example
struct Foo {
bar: i32,
}
fn main() {
let mut t = vec![Foo { bar: 0 }, Foo { bar: 1 }];
t.retain(|&v| v.bar != 1);
}
The compiler will tell me to use ref` here instead.
But if I add #[derive(Copy, Clone)] on the struct like this:
#[derive(Copy, Clone)]
struct Foo {
bar: i32,
}
fn main() {
let mut t = vec![Foo { bar: 0 }, Foo { bar: 1 }];
t.retain(|&v| v.bar != 1);
}
It all works fine. So I wonder when is the ref keyword supposed to be used over & in these cases the compiler is happy to help out but I would like to know the rules of it.
ref in a binding is the same as & in an expression. In other words, these two are equivalent:
let ref a=2;
let a=&2;
Both variables will have type &i32. Both exist, because sometimes you can only specify things in a binding (e.g. when pattern matching) and other times you can only specify things in an expression (e.g. when calling a function). If both are an option, prefer &.
Likewise, & in a binding is the same as * in an expression, which makes these equivalent:
let r=&1;
let &a=r;
let a=*r;
Both variables will have type i32. Again, both exist because you can't write the other form everywhere.
In your particular example the closure will be called with an argument of type &Foo. By specifying &v you are automatically dereferencing the argument to get a Foo. Since Foo is not Copy in the first example, the compiler doesn't let you dereference like that. You probably just want to specify |v| which will receive an argument of type &Foo.
Sorry for digging up an old conversation, but I'm confused, how is t.retain(|& ref v| v.bar != 1) the same as t.retain(|v| v.bar != 1)? Shouldn't it be more something like this?