Я столкнулся со следующим (уменьшенным) примером:
enum Thing {
A { value: f32 },
B { value: f32 },
}
fn main() {
let mut thing = Thing::A { value: 0. };
let thing_mut_ref = &mut thing;
if let Thing::A {value} = thing_mut_ref {
*thing_mut_ref = Thing::B { value: value * 2.0};
}
}
Следующее не компилируется, потому что значение захвачено как &mut f32 и, следовательно, не поддерживает умножение на 2.0.
Что меня удивило, так это то, что добавление ref к сопоставленному шаблону внезапно приводит к его компиляции, то есть захвату по значению (разыменованию value):
enum Thing {
A { value: f32 },
B { value: f32 },
}
fn main() {
let mut thing = Thing::A { value: 0. };
let thing_mut_ref = &mut thing;
if let Thing::A {ref value} = thing_mut_ref {
*thing_mut_ref = Thing::B { value: value * 2.0};
}
}
Я знаю ref за то, что обычно делают наоборот — заявляют, что не хотят захватывать по значению. Как это объясняет то, что здесь происходит?

На самом деле это не разыменование, а преобразование изменяемой ссылки в общую.
И как видно из документации Mul это реализовано для &f32 и f32, но не для &mut f32