Как я могу организовать несколько ссылок на один и тот же объект в Rust с подсчетом ссылок?

У меня есть структура, представляющая полином, и я хочу, чтобы несколько полиномов ссылались на один и тот же объект mutable Aliases. В JavaScript я бы создал экземпляр объекта Aliases и присвоил его p1.aliases, p2.aliases и так далее. В Rust, насколько я понимаю, нужно использовать RefCell, который должен выполнять подсчет ссылок, потому что в Rust нет сборщика мусора:

extern crate rand;

use std::collections::HashMap;
use std::cell::RefCell;
use std::collections::*;

pub struct Aliases {
    pub idx_to_name: HashMap<i16, String>,
    pub name_to_idx: HashMap<String, i16>,
}

pub struct Polynome {
    pub poly: BTreeMap<i16, f64>,
    pub aliases: RefCell<Aliases>,
}

impl Aliases {
    pub fn new() -> Aliases {
        Aliases {
            idx_to_name: HashMap::new(),
            name_to_idx: HashMap::new(),
        }
    }
}

impl Polynome {
    pub fn new() -> Polynome {
        Polynome {
            poly: BTreeMap::new(),
            aliases: RefCell::new(Aliases::new()),
        }
    }
    pub fn clone(&self) -> Polynome {
        Polynome {
            poly: self.poly.clone(),
            aliases: self.aliases,
        }
    }
}

Но я получаю ошибку компиляции в clone():

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:36:22
   |
36 |             aliases: self.aliases,
   |                      ^^^^ cannot move out of borrowed content

как правильно клонировать Polynome, чтобы все клоны ссылались на один и тот же экземпляр Aliases?

Обратите внимание, что этот вопрос не является дубликатом вопроса Как представить общее изменяемое состояние? . Потому что, если я попытаюсь организовать ссылку с объявлением времени жизни, как это предлагается там:

pub struct Polynome<'a> {
    pub poly: BTreeMap<i16, f64>,
    pub aliases: &'a RefCell<Aliases> 
}

тогда я получаю проблему «не живет достаточно долго» вместо «не могу съехать»:

pub fn new() -> Polynome<'a> {
    let alias= RefCell::new (Aliases::new());
    Polynome {
        poly: BTreeMap::new(),
        aliases: &alias,
    }
}

     error[E0597]: `alias` does not live long enough
   |
24 |             aliases: &alias,
   |                       ^^^^^ does not live long enough
25 |         }
26 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 19:1...

Как мне создать экземпляр Aliases, если мне нужно, чтобы он жил вне ::new()?


person Stepan Yakovenko    schedule 28.10.2017    source источник
comment
Подсчет ссылок выполняется Rc или Arc, а не RefCell. Вы можете поместить RefCell внутрь Rc, чтобы сделать его изменяемым и подсчитываемым.   -  person interjay    schedule 29.10.2017
comment
@Shepmaster, снимите пометку с дубликатов, чтобы люди могли внести свой вклад.   -  person Stepan Yakovenko    schedule 29.10.2017
comment
Это все еще дубликат, конкретная деталь, которая вам нужна, была в комментарии. Поскольку это кажется трудным найти, я переместил его в принятый ответ (это также именно то, что сказал @interjay — Rc или Arc).   -  person Shepmaster    schedule 29.10.2017