Почему сопоставление с образцом в & Option <T>дает что-то типа Some (& T)? - PullRequest
1 голос
/ 11 апреля 2019

У меня крошечный пример детской площадки здесь

fn main() {
    let l = Some(3);
    match &l {
        None => {}
        Some(_x) => {} // x is of type &i32
    }
}

Я сопоставляюсь с шаблоном на &Option, и если я использую Some(x) в качестве ветви, почему x имеет тип &i32?

1 Ответ

7 голосов
/ 11 апреля 2019

Тип выражения &l, с которым вы сопоставляете, равен &Option<i32>, поэтому, если мы строгие, шаблоны должны быть &None и &Some(x), и если мы используем эти шаблоны, тип x действительно это i32. Если мы опускаем амперсанд в шаблонах, как вы это делали в своем коде, сначала кажется, что шаблоны вообще не должны совпадать, и компилятор должен выдать ошибку, похожую на «ожидаемый вариант, найденная ссылка», и действительно это то, что компилятор делал до версии Rust 1.26.

Текущие версии Rust поддерживают «эргономику соответствия», представленную RFC 2005 , и теперь разрешено сопоставление ссылки на перечисление с шаблоном без амперсанда. В общем, если ваше выражение соответствия является только ссылкой, вы не можете перемещать какие-либо элементы из перечисления, поэтому сопоставление ссылки с Some(x) эквивалентно сопоставлению с шаблоном &Some(ref x), то есть x становится ссылкой к внутреннему значению Option. В вашем конкретном случае внутренним значением является i32, то есть Copy, поэтому вам будет разрешено совпадать с &Some(x) и получить i32, но это невозможно для общих типов.

Идея RFC состоит в том, чтобы упростить правильную настройку амперсандов и ref в шаблонах, но я не совсем уверен, действительно ли новые правила упростили вещи, или они добавили путаницы, создавая В некоторых случаях все волшебным образом срабатывает, что затрудняет понимание людьми истинной логики.

...