This question already has answers here:
Implement graph-like data structure in Rust
(3 answers)
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 5 years ago.
I'm implementing a basic data structure. I think I understand why the following code doesn't work: I can't mutably borrow and try to access (read) the value at the same time. However, I am stuck on how to implement add_ege.
The whole idea is to have Graph hold a list of Nodes in the heap. The Node itself keeps track of adjacent nodes (edges). I don't want Node to hold copies of Node, I want it to have references to any of the Nodes held in Graph.
struct Node<'a> {
value: String,
adj_nodes: Vec<&'a Node<'a>>, // refer to Graph.nodes
}
pub struct Graph<'a> {
nodes: Vec<Box<Node<'a>>>,
}
fn mk_node<'a>(value: String) -> Node<'a> {
Node {
value,
adj_nodes: vec![],
}
}
pub fn mk_graph<'a>() -> Graph<'a> {
let nodes = vec![];
Graph { nodes }
}
impl<'a> Graph<'a> {
fn add_node(&mut self, val: String) {
let node = Box::new(mk_node(val));
self.nodes.push(node);
}
fn add_edge(&mut self, from_node: &'a mut Node<'a>, to_node: &'a mut Node<'a>) {
from_node.adj_nodes.push(to_node);
// won't work because I already have from_node as mutable borrow
to_node.adj_nodes.push(from_node);
}
}
Is there a way to do this?
Related
This question already has answers here:
Is there a way to make an immutable reference mutable?
(2 answers)
Why is transmuting &T to &mut T Undefined Behaviour?
(2 answers)
How to avoid writing duplicate accessor functions for mutable and immutable references in Rust?
(4 answers)
Closed 2 years ago.
I have a custom iterator which reads data from a reference to a Vec in a non-contiguous manner. It will never return two references to the same memory, so I believe it is safe to implement a mutable counterpart.
However, the logic for the iterator itself is quite complex, and it would be entirely identical for the mutable version. In an attempt to avoid code duplication, I use my non-mut iterator under the hood, and then cast the result to add mutability. This works as expected, but I am unsure if it's invoking some kind of undefined behavior.
pub mod lib {
pub struct Data {
pub v: Vec<u64>,
}
impl Data {
pub fn iter(&self) -> MyIter {
MyIter {
data: &self.v,
i: 0,
}
}
pub fn iter_mut(&mut self) -> MyIterMut {
MyIterMut { iter: self.iter() }
}
}
pub struct MyIter<'a> {
data: &'a [u64],
i: usize,
}
impl<'a> Iterator for MyIter<'a> {
type Item = &'a u64;
fn next(&mut self) -> Option<Self::Item> {
if self.i == self.data.len() {
return None;
}
let res = &self.data[self.i];
self.i += 1;
Some(res)
}
}
pub struct MyIterMut<'a> {
iter: MyIter<'a>,
}
impl<'a> Iterator for MyIterMut<'a> {
type Item = &'a mut u64;
fn next(&mut self) -> Option<Self::Item> {
unsafe { std::mem::transmute(self.iter.next()) }
}
}
}
fn main() {
let mut d = lib::Data { v: vec![0; 8] };
for elem in d.iter_mut() {
*elem = 123;
}
println!("{:?}", d.v);
}
Complete working example
The mutable iterator is only constructed in the iter_mut method. This means the initial value will always start as a mutable variable, due to the &mut self. It wouldn't be possible to construct this mutable iterator from an immutable variable.
In C++, often times you will use a const_cast to avoid duplicating an implementation that only varies in constness.
Is this something I can do in Rust?
If MyIter contains an immutable reference to the original vec, then you can't transmute, as you could have multiple instances of MyIter, leading to conflicting references. It seems like the duplicate crate could be of use here, providing an easy way to duplicate code with slight differences.
This question already has answers here:
Is it possible to create a wrapper around an &mut that acts like an &mut
(1 answer)
Why is the mutable reference not moved here?
(4 answers)
Closed 2 years ago.
I've been adapting some old code I wrote, one of them had the following (simplified):
pub fn a(x: &mut i32) {
for i in 0..10 {
b(x);
}
}
pub fn b(_x: &mut i32) {
}
which worked fine, even though &mut i32 isn't Copy.
I wanted to restrict what methods could be called on the underlying type, (as instead of &mut i32 I had something along the lines of &mut Vec<...>), so I created a wrapper type over the mutable reference:
#[derive(Debug)]
pub struct I32RefMut<'a>(&'a mut i32);
And I attempted to rewrite a and b using this wrapper as follows:
pub fn a2(x: I32RefMut) {
for _i in 0..10 {
b2(x);
}
}
pub fn b2(_x: I32RefMut) {
}
This gives the following error
17 | pub fn a2(x: I32RefMut) {
| - move occurs because `x` has type `I32RefMut<'_>`, which does not implement the `Copy` trait
18 | for _i in 0..10 {
19 | b2(x);
| ^ value moved here, in previous iteration of loop
Playground link
Which is understandable, as x gets moved into b2 on the first iteration of the loop.
Unfortunately I cannot implement Clone nor Copy, as there may only be 1 mutable reference to the object at a time.
My question is how does &mut i32 work around this and how can I implement this workaround (or similar) on my type I32RefMut.
If possible I'd like to avoid unsafe code as much as possible, such as using #[repr(transparent)] struct I32Wrapper(i32) and then transmuting &mut i32 to &mut I32Wrapper, unless a safe wrapper of this type of operation exists already.
EDIT:
Found a "hack" solution, but I'm not very happy about how it looks, so I'll leave the question open. If no other solutions are found, I'll post it as an answer.
If the call to b2 is changed to b2( I32RefMut(x.0) ), then it successfully compiles. This however, cannot be generalised to a function as such:
impl<'a> I32RefMut<'a> {
pub fn my_clone<'b: 'a>(&'b mut self) -> I32RefMut<'b> {
I32RefMut( self.0 )
}
}
As when we try to call it the compiler tells us we can't borrow x mutably twice.
As this wrapper type is supposed to be defined in a library, I cannot expose it's internal reference, as the whole point of the wrapper was to restrain what the user can call on the reference.
The thing is that you are taking ownership of your new type instance when calling b. Just take a reference to your type instead to get access to the underlaying type:
pub fn a2(x: &I32RefMut) {
for _i in 0..10 {
b2(x);
}
}
pub fn b2(_x: &I32RefMut) {
}
Playground
Actually if you want to mutate it you need to play around a bit with them:
pub fn a2(mut x: I32RefMut) {
for _i in 0..10 {
b2(&mut x);
}
}
pub fn b2(_x: &mut I32RefMut) {
*(_x.0) += 1
}
Playground
This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
How do I express mutually recursive data structures in safe Rust?
(4 answers)
Pass self reference to contained object's function
(2 answers)
Passing mutable self reference to method of owned object
(2 answers)
Closed 3 years ago.
I am trying to pass a reference to self down to a child struct that is a field variable
use std::cell::RefCell;
use std::rc::Rc;
pub struct BUS {
pub processor: CPU,
pub ram: [u8; 65536],
}
impl BUS {
pub fn new() -> BUS {
BUS {
processor: CPU::new(),
ram: [0; 65536],
}
}
pub fn setup(&mut self) {
self.processor.connect_bus(Rc::new(RefCell::new(self)));
self.ram.iter_mut().for_each(|x| *x = 00);
}
pub fn write(&mut self, addr: u16, data: u8) {
self.ram[addr as usize] = data;
}
pub fn read(&mut self, addr: u16, _read_only: bool) -> u8 {
self.ram[addr as usize]
}
}
pub struct CPU {
bus_ptr: Rc<RefCell<BUS>>,
}
impl CPU {
pub fn new() -> CPU {
CPU {
bus_ptr: Rc::new(RefCell::new(BUS::new())),
}
}
pub fn connect_bus(&mut self, r: Rc<RefCell<BUS>>) {
self.bus_ptr = r;
}
pub fn read_ram(&self, addr: u16, _read_only: bool) -> u8 {
(self.bus_ptr.borrow_mut().read(addr, false))
}
pub fn write_ram(&mut self, addr: u16, data: u8) {
(self.bus_ptr.borrow_mut().write(addr, data))
}
}
fn main() {
let comp = BUS::new();
comp.setup();
}
Rust Playground
This errors:
error[E0308]: mismatched types
--> src/main.rs:18:57
|
18 | self.processor.connect_bus(Rc::new(RefCell::new(self)));
| ^^^^ expected struct `BUS`, found &mut BUS
|
= note: expected type `BUS`
found type `&mut BUS`
I can't pass in self to the RefCell as it is a second mutable borrow. I got around this by moving my functions around but want to know how possible this structure is.
I achieved this in C++ by passing in this from BUS and then using *bus in connect_bus so that read_ram can be *bus->read(...).
Is it possible to call the BUS struct's read and write functions from a method on the CPU struct?
The short answer is no.
RefCell owns its inner object. This means it has the only copy of that object, so that it can fully control all access to it and not allow any other access from outside. An object can't exist in RefCell and outside of RefCell at the same time.
Your setup could take an existing Rc<RefCell<BUS>> instead and pass that around. &mut BUS without the wrapper won't do.
The borrow checker can't ensure safety of mutual parent-child relationships. It wants program data structured as trees or DAGs. Otherwise you're forced to use wrapper types or C-like raw pointers.
The borrow checker checks against interfaces, not implementation. If your setter borrows &mut self, that's exclusive borrow of the entire object, and for borrow checking that's the most restrictive and most inflexible option. You will need to peel some layers of abstraction to make this work, e.g. pass RAM down to the CPU. Alternatively, make RAM use Cell<u8> type, so that it can be mutated via shared references.
This question already has answers here:
Cannot borrow immutable borrowed content as mutable when implementing a binary tree with Rc
(1 answer)
Cannot borrow immutable borrowed content as mutable
(1 answer)
Closed 4 years ago.
I have a clonable struct, called GenICam. This struct has a HashMap of Rc<dyn Node> trait objects, and a HashMap of Rc<Category> structs which implement the Node trait. The keys are NodeName which is an alias type for String.
Each category has a list of feature names, which are represented in the nodes HashMap of GenICam. This list should be used to populate the node_list field with references to the nodes using the functions below:
use std::{collections::HashMap, rc::Rc};
type NodeName = String;
#[derive(Clone)]
pub struct GenICam {
nodes: HashMap<NodeName, Rc<Node>>,
categories: HashMap<NodeName, Rc<Category>>,
}
impl GenICam {
fn get_categories(&self) -> Vec<Rc<Category>> {
let mut collect = Vec::new();
for i in &self.categories {
collect.push(i.1.clone());
}
collect
}
/// Fills all categories with references to the features if available
fn populate_categories(&mut self) {
let mut cats = self.get_categories();
for cat in cats {
let mut mutcat = cat;
mutcat.populate(&self);
}
}
}
#[derive(Clone)]
pub struct Category {
pub name: NodeName,
features: Vec<String>,
pub node_list: HashMap<NodeName, Rc<Node>>,
}
impl Category {
pub fn populate(&mut self, genicam: &GenICam) {
for feat in &self.clone().features {
let result = genicam.node(feat.to_string());
match result {
None => (),
Some(x) => self.add_to_node_list(x),
};
}
}
/// populate the node hashmap with the given node
pub fn add_to_node_list(&mut self, node: &Rc<Node>) {
println!("Succes: {:?}", node.name());
self.node_list.insert(node.name(), node.clone());
}
}
I get the following error:
error[E0596]: cannot borrow immutable borrowed content as mutable
--> src/genicam.rs:174:4
|
| mutcat.populate(&self);
| ^^^^^^ cannot borrow as mutable
I cannot wrap my head around why mutcat is immutable, since it is defined as let mut.
This question already has answers here:
How do I return a reference to something inside a RefCell without breaking encapsulation?
(3 answers)
Closed 4 years ago.
I have a RefCell<HashMap> and want to borrow the table, find a key, and return a reference to the result:
use std::cell::RefCell;
use std::collections::HashMap;
struct Frame {
map: RefCell<HashMap<String, String>>,
}
impl Frame {
fn new() -> Frame {
Frame {
map: RefCell::new(HashMap::new()),
}
}
fn lookup<'a>(&'a self, k: &String) -> Option<&'a String> {
self.map.borrow().get(k)
}
}
fn main() {
let f = Frame::new();
println!("{}", f.lookup(&"hello".to_string()).expect("blargh!"));
}
(playground)
If I remove the RefCell then everything works okay:
struct Frame {
map: HashMap<String, String>,
}
impl Frame {
fn lookup<'a>(&'a self, k: &String) -> Option<&'a String> {
self.map.get(k)
}
}
What is the correct way to write the lookup function without copying the string in the hashtable?
When you borrow from a RefCell, the reference you get has a shorter lifetime than the RefCell's. That's because the reference's lifetime is restricted by the guard returned by borrow(). That guard ensures that nobody else can take a mutable reference to the value until the guard is dropped.
However, you are trying to return a value without keeping a guard alive. If Frame had a method that took a &self argument but tried to mutate the map (which is possible with RefCell — if you don't need to do that, then ditch the RefCell and write &mut self on the methods that mutate the map), you could accidentally destroy a String that somebody else has a reference to. That is exactly the kind of errors that the borrow checker was designed to report!
If the map values are effectively immutable (i.e. your type will not allow mutating the map's values), you could also wrap them in an Rc in your map. You could therefore return a clone of the Rc<String> (this only clones the reference-counted pointer, not the underlying string), which would let you release the borrow on the map before returning from the function.
struct Frame {
map: RefCell<HashMap<String, Rc<String>>>
}
impl Frame {
fn lookup(&self, k: &String) -> Option<Rc<String>> {
self.map.borrow().get(k).map(|x| x.clone())
}
}