2

I have a struct representing polynome and I want multiple polynomes to reference the same mutable Aliases object. In JavaScript, I'd create an instance of the Aliases object and assign it to p1.aliases, p2.aliases and so on. In Rust, as far as I understand, I need to use RefCell, which should perform reference counting, because there is no garbage collector in 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,
        }
    }
}

But I get compilation error in clone():

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

what is the right way to clone Polynome, so that all clones reference the same Aliases instance?

Please note that this question is not duplicate of How to represent shared mutable state?. Because if I try to organize reference with lifetime declaration as proposed there:

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

then I get 'doesn't live long enough' problem instead of 'can not move out':

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...

How should I create Aliases instance if I need it to live outside ::new()?

René Hoffmann
  • 2,766
  • 2
  • 20
  • 43
Stepan Yakovenko
  • 8,670
  • 28
  • 113
  • 206
  • 1
    Reference counting is done by `Rc` or `Arc`, not `RefCell`. You can put `RefCell` inside `Rc` to make it both mutable and reference counted. – interjay Oct 28 '17 at 22:08
  • @Shepmaster, please unmark this as duplicated, so people can contribute. – Stepan Yakovenko Oct 28 '17 at 23:40
  • It's still a duplicate, the specific detail you need was in a comment. Since that appears to be hard to find, I've moved it into the accepted answer (it's also exactly what @interjay said — `Rc` or `Arc`). – Shepmaster Oct 29 '17 at 00:01

0 Answers0