Карта вызовов на Опционеработает иначе, чем вызывать его в Option> - PullRequest
2 голосов
/ 22 июня 2019

Я новичок в Rust и пытаюсь понять, почему Rc ведет себя по-разному, когда его передают в замыкание. Мой полный код следующий:

use std::rc::Rc;

struct Something {
    value: i32
}

fn main() {
    let wrapped_struct = Some(Rc::new(Something { value: 1 }));
    let wrapped_integer = Some(Rc::new(1));
    // Case 1: This works
    let works: Option<i32> = wrapped_struct.map(|i| { i.value });
    // Case 2: This fails
    let fails: Option<i32> = wrapped_integer.map(|i| { i });
}

Сообщение об ошибке:

   |
13 |     let fails: Option<i32> = wrapped_integer.map(|i| { i });
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found struct `std::rc::Rc`
   |
   = note: expected type `std::option::Option<i32>`
              found type `std::option::Option<std::rc::Rc<{integer}>>`

Я не понимаю, почему в первом закрытии (Случай 1) я могу использовать i в качестве Something (я бы ожидал Rc<Something>), но во втором (Случай 2) я могу не использовать i как i32 (на самом деле я получаю Rc<i32>).

Я ценю любые ссылки на соответствующую документацию. Большое спасибо!

1 Ответ

2 голосов
/ 22 июня 2019

Тип i в обоих замыканиях на самом деле Rc<Something> и Rc<i32> соответственно.Rc может быть разыменовано для доступа к его внутренним данным, но в Rust есть места, где разыменование происходит автоматически для удобства.

В случае структуры, когда вы пишете i.value, она автоматически разыменовывается i для доступа к полю.Затем он возвращает копию i32, потому что i32 имеет тип Copy.Таким образом, тип выражения i.value равен i32.Это как если бы вы написали (*i).value, но Rust выполнил разыменование для вас.

В случае i32 вы просто возвращаете i, который по-прежнему имеет тип Rc<i32>.Вы можете исправить это путем явной разыменования:

wrapped_integer.map(|i| { *i });

См. Также:

...