Почему `ref` заставляет этот пример *разыменовывать* поле?

Я столкнулся со следующим (уменьшенным) примером:

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 за то, что обычно делают наоборот — заявляют, что не хотят захватывать по значению. Как это объясняет то, что здесь происходит?

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
3
0
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Другие вопросы по теме