Попытка перебрать структуру меша приводит к тому, что «заимствованное значение не живет достаточно долго» - PullRequest
0 голосов
/ 06 июля 2018

Я пытаюсь создать структуру данных, которая может хранить данные о местоположении монитора.

Подход, который я использую, заключается в том, что на каждом экране есть ссылки на 4 соседей, которые хранятся в HashMap<Direction, Rc<RefCell<Screen>>>.

Я борюсь с тем, как «двигаться» / итерировать в направлении, пока я не достигну края сетки:

use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

#[derive(Debug, Copy, Clone, Default)]
pub struct ScreenCoord {
    left: i32,
    right: i32,
    bottom: i32,
    top: i32,
}

impl ScreenCoord {
    fn new_primary_from_dimensions(width: i32, height: i32) -> ScreenCoord {
        ScreenCoord {
            left: 0,
            right: width,
            top: 0,
            bottom: height,
        }
    }
}

pub struct ScreenNetwork {
    primary_screen: Rc<RefCell<Screen>>,
}

impl ScreenNetwork {
    pub fn new(width: i32, height: i32) -> ScreenNetwork {
        ScreenNetwork {
            primary_screen: Rc::new(RefCell::new(Screen::new(
                ScreenCoord::new_primary_from_dimensions(width, height),
            ))),
        }
    }

    pub fn add_screen(&mut self, new_width: i32, new_height: i32, direction: Direction) {
        let mut new_scrn = Screen::new(ScreenCoord::new_primary_from_dimensions(
            new_width, new_height,
        ));
        let mut original_screen = &self.primary_screen;

        while let Some(next) = original_screen.borrow().neighbours.get(&direction) {
            original_screen = next;
        }

        // Do stuff with original_screen

        // new_scrn.neighbours.insert(Direction::from_u8((direction.clone() as u8) ^ 0b11).unwrap(), original_screen.clone());
        // original_screen.borrow_mut().neighbours.insert(direction, Rc::new(RefCell::new(new_scrn)));
    }
}

/// Screen with information about adjacent screens
#[derive(Default, Debug)]
pub struct Screen {
    neighbours: HashMap<Direction, Rc<RefCell<Screen>>>,
    coordinates: ScreenCoord,
}

impl Screen {
    pub fn new(coord: ScreenCoord) -> Screen {
        Screen {
            coordinates: coord,
            neighbours: HashMap::new(),
        }
    }
}

#[derive(Debug, PartialEq, Hash, Eq, Clone)]
pub enum Direction {
    Left = 0,
    Top,
    Bottom,
    Right,
}

fn main() {}

детская площадка

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:43:32
   |
43 |         while let Some(next) = original_screen.borrow().neighbours.get(&direction) {
   |                                ^^^^^^^^^^^^^^^^^^^^^^^^                          - temporary value dropped here while still borrowed
   |                                |
   |                                temporary value does not live long enough
...
51 |     }
   |     - temporary value needs to live until here

Я понимаю, почему происходит ошибка, но я понятия не имею, как я могу это исправить. Я пытался клонировать original_screen и next, но потом компилятор жалуется, что я пытаюсь установить original_screen, все еще заимствуя его.

1 Ответ

0 голосов
/ 06 июля 2018

Вы используете Rc, так что воспользуйтесь этим. Вообще говоря, взятие ссылки на Rc вызывает проблемы.

Первая попытка: клон Rc при необходимости:

let mut original_screen = self.primary_screen.clone();

while let Some(next) = original_screen.borrow().neighbours.get(&direction) {
    original_screen = next.clone();
}

Ошибка с сообщением:

нельзя присвоить original_screen, потому что он заимствован

Достаточно верно: наличие заимствования в условии while не позволит вам обновить его, но его можно легко переписать:

loop {
    if let Some(next) = original_screen.borrow().neighbours.get(&direction) {
         original_screen = next.clone()
    } else {
        break;
    }
}

Этот код эквивалентен, и в действительности он завершается с тем же сообщением об ошибке! Но теперь мы ближе к решению:

loop {
    let next = if let Some(next) = original_screen.borrow().neighbours.get(&direction) {
         next.clone()
    } else {
        break;
    };
    original_screen = next;
}

Теперь он компилируется, потому что назначение выполняется после освобождения заимствования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...