Unable to mutably borrow the contents inside a RefCell, even after the scope of the previous mutable borrow...
Consider the following bit of code
use std::{cell::RefCell, rc::Rc};
type NodeRef = Rc<RefCell<_Node>>;
#[derive(Debug)]
struct _Node {
id: usize,
data: Option<NodeRef>,
edges: Vec<NodeRef>,
}
impl _Node {
fn add(&mut self, other: NodeRef) {
println!("at {}", self.id);
self.data = match self.data.take() {
Some(current_data) => {
{
let mut current_data_raw = current_data.borrow_mut();
current_data_raw.id += other.borrow().id;
}
Some(current_data)
}
None => Some(Rc::clone(&other)),
};
for e in &self.edges {
e.borrow_mut().add(Rc::clone(&other));
}
println!("done {}", self.id);
}
}
#[derive(Debug)]
struct Node(NodeRef);
impl Node {
fn new(id: usize) -> Node {
Node(Rc::new(RefCell::new(_Node {
id,
data: None,
edges: vec!,
})))
}
fn add_edge(&self, other: &Node) {
self.0.borrow_mut().edges.push(Rc::clone(&other.0));
}
fn add(&self, other: Self) {
self.0.borrow_mut().add(other.0);
}
}
fn main() {
let a = Node::new(0);
let b = Node::new(1);
let c = Node::new(2);
let d = Node::new(3);
let e = Node::new(4);
let f = Node::new(5);
d.add_edge(&a);
d.add_edge(&b);
e.add_edge(&b);
e.add_edge(&c);
f.add_edge(&d);
f.add_edge(&e);
f.add(Node::new(6));
}
The output generated on running this is
at 5
at 3
at 0
done 0
at 1
done 1
done 3
at 4
at 1
thread 'main' panicked at 'already mutably borrowed: BorrowError', src/libcore/result.rs:1009:5
This creates a graph of the form
F--E--A
B
/
D
C
I am trying to propagate a value through the entire graph, so it starts from F, and goes to E and D. From E it goes to A and B without any error. Then from D, the runtime panics saying the RefCell constraint for mutable borrows has been broken.
It seems that it is considering the mutable borrow from the previous invocation of the callback with B, however, the mutable borrow (current_data_raw) inside _Node::add has a limited scope, and after the scope ends, I should be allowed to mutably borrow the value again. From the output, when the function is called for node B for the second time, the entire first invocation of the function and not just the mutable borrow scope has exited.
What am I missing here?
rust
add a comment |
Consider the following bit of code
use std::{cell::RefCell, rc::Rc};
type NodeRef = Rc<RefCell<_Node>>;
#[derive(Debug)]
struct _Node {
id: usize,
data: Option<NodeRef>,
edges: Vec<NodeRef>,
}
impl _Node {
fn add(&mut self, other: NodeRef) {
println!("at {}", self.id);
self.data = match self.data.take() {
Some(current_data) => {
{
let mut current_data_raw = current_data.borrow_mut();
current_data_raw.id += other.borrow().id;
}
Some(current_data)
}
None => Some(Rc::clone(&other)),
};
for e in &self.edges {
e.borrow_mut().add(Rc::clone(&other));
}
println!("done {}", self.id);
}
}
#[derive(Debug)]
struct Node(NodeRef);
impl Node {
fn new(id: usize) -> Node {
Node(Rc::new(RefCell::new(_Node {
id,
data: None,
edges: vec!,
})))
}
fn add_edge(&self, other: &Node) {
self.0.borrow_mut().edges.push(Rc::clone(&other.0));
}
fn add(&self, other: Self) {
self.0.borrow_mut().add(other.0);
}
}
fn main() {
let a = Node::new(0);
let b = Node::new(1);
let c = Node::new(2);
let d = Node::new(3);
let e = Node::new(4);
let f = Node::new(5);
d.add_edge(&a);
d.add_edge(&b);
e.add_edge(&b);
e.add_edge(&c);
f.add_edge(&d);
f.add_edge(&e);
f.add(Node::new(6));
}
The output generated on running this is
at 5
at 3
at 0
done 0
at 1
done 1
done 3
at 4
at 1
thread 'main' panicked at 'already mutably borrowed: BorrowError', src/libcore/result.rs:1009:5
This creates a graph of the form
F--E--A
B
/
D
C
I am trying to propagate a value through the entire graph, so it starts from F, and goes to E and D. From E it goes to A and B without any error. Then from D, the runtime panics saying the RefCell constraint for mutable borrows has been broken.
It seems that it is considering the mutable borrow from the previous invocation of the callback with B, however, the mutable borrow (current_data_raw) inside _Node::add has a limited scope, and after the scope ends, I should be allowed to mutably borrow the value again. From the output, when the function is called for node B for the second time, the entire first invocation of the function and not just the mutable borrow scope has exited.
What am I missing here?
rust
Idiomatic Rust uses a leading underscore to indicate that a variable or type is unused. That's not the case here, so you should not name your type_Node.
– Shepmaster
Jan 20 at 15:54
add a comment |
Consider the following bit of code
use std::{cell::RefCell, rc::Rc};
type NodeRef = Rc<RefCell<_Node>>;
#[derive(Debug)]
struct _Node {
id: usize,
data: Option<NodeRef>,
edges: Vec<NodeRef>,
}
impl _Node {
fn add(&mut self, other: NodeRef) {
println!("at {}", self.id);
self.data = match self.data.take() {
Some(current_data) => {
{
let mut current_data_raw = current_data.borrow_mut();
current_data_raw.id += other.borrow().id;
}
Some(current_data)
}
None => Some(Rc::clone(&other)),
};
for e in &self.edges {
e.borrow_mut().add(Rc::clone(&other));
}
println!("done {}", self.id);
}
}
#[derive(Debug)]
struct Node(NodeRef);
impl Node {
fn new(id: usize) -> Node {
Node(Rc::new(RefCell::new(_Node {
id,
data: None,
edges: vec!,
})))
}
fn add_edge(&self, other: &Node) {
self.0.borrow_mut().edges.push(Rc::clone(&other.0));
}
fn add(&self, other: Self) {
self.0.borrow_mut().add(other.0);
}
}
fn main() {
let a = Node::new(0);
let b = Node::new(1);
let c = Node::new(2);
let d = Node::new(3);
let e = Node::new(4);
let f = Node::new(5);
d.add_edge(&a);
d.add_edge(&b);
e.add_edge(&b);
e.add_edge(&c);
f.add_edge(&d);
f.add_edge(&e);
f.add(Node::new(6));
}
The output generated on running this is
at 5
at 3
at 0
done 0
at 1
done 1
done 3
at 4
at 1
thread 'main' panicked at 'already mutably borrowed: BorrowError', src/libcore/result.rs:1009:5
This creates a graph of the form
F--E--A
B
/
D
C
I am trying to propagate a value through the entire graph, so it starts from F, and goes to E and D. From E it goes to A and B without any error. Then from D, the runtime panics saying the RefCell constraint for mutable borrows has been broken.
It seems that it is considering the mutable borrow from the previous invocation of the callback with B, however, the mutable borrow (current_data_raw) inside _Node::add has a limited scope, and after the scope ends, I should be allowed to mutably borrow the value again. From the output, when the function is called for node B for the second time, the entire first invocation of the function and not just the mutable borrow scope has exited.
What am I missing here?
rust
Consider the following bit of code
use std::{cell::RefCell, rc::Rc};
type NodeRef = Rc<RefCell<_Node>>;
#[derive(Debug)]
struct _Node {
id: usize,
data: Option<NodeRef>,
edges: Vec<NodeRef>,
}
impl _Node {
fn add(&mut self, other: NodeRef) {
println!("at {}", self.id);
self.data = match self.data.take() {
Some(current_data) => {
{
let mut current_data_raw = current_data.borrow_mut();
current_data_raw.id += other.borrow().id;
}
Some(current_data)
}
None => Some(Rc::clone(&other)),
};
for e in &self.edges {
e.borrow_mut().add(Rc::clone(&other));
}
println!("done {}", self.id);
}
}
#[derive(Debug)]
struct Node(NodeRef);
impl Node {
fn new(id: usize) -> Node {
Node(Rc::new(RefCell::new(_Node {
id,
data: None,
edges: vec!,
})))
}
fn add_edge(&self, other: &Node) {
self.0.borrow_mut().edges.push(Rc::clone(&other.0));
}
fn add(&self, other: Self) {
self.0.borrow_mut().add(other.0);
}
}
fn main() {
let a = Node::new(0);
let b = Node::new(1);
let c = Node::new(2);
let d = Node::new(3);
let e = Node::new(4);
let f = Node::new(5);
d.add_edge(&a);
d.add_edge(&b);
e.add_edge(&b);
e.add_edge(&c);
f.add_edge(&d);
f.add_edge(&e);
f.add(Node::new(6));
}
The output generated on running this is
at 5
at 3
at 0
done 0
at 1
done 1
done 3
at 4
at 1
thread 'main' panicked at 'already mutably borrowed: BorrowError', src/libcore/result.rs:1009:5
This creates a graph of the form
F--E--A
B
/
D
C
I am trying to propagate a value through the entire graph, so it starts from F, and goes to E and D. From E it goes to A and B without any error. Then from D, the runtime panics saying the RefCell constraint for mutable borrows has been broken.
It seems that it is considering the mutable borrow from the previous invocation of the callback with B, however, the mutable borrow (current_data_raw) inside _Node::add has a limited scope, and after the scope ends, I should be allowed to mutably borrow the value again. From the output, when the function is called for node B for the second time, the entire first invocation of the function and not just the mutable borrow scope has exited.
What am I missing here?
rust
rust
edited Jan 20 at 15:53
Shepmaster
154k14304442
154k14304442
asked Jan 20 at 13:59
suyashsuyash
169211
169211
Idiomatic Rust uses a leading underscore to indicate that a variable or type is unused. That's not the case here, so you should not name your type_Node.
– Shepmaster
Jan 20 at 15:54
add a comment |
Idiomatic Rust uses a leading underscore to indicate that a variable or type is unused. That's not the case here, so you should not name your type_Node.
– Shepmaster
Jan 20 at 15:54
Idiomatic Rust uses a leading underscore to indicate that a variable or type is unused. That's not the case here, so you should not name your type
_Node.– Shepmaster
Jan 20 at 15:54
Idiomatic Rust uses a leading underscore to indicate that a variable or type is unused. That's not the case here, so you should not name your type
_Node.– Shepmaster
Jan 20 at 15:54
add a comment |
1 Answer
1
active
oldest
votes
What am I missing here?
Your algorithm is broken. You can see this by adding this debugging code inside of the Some arm of the match:
{
let a = current_data.borrow();
let b = other.borrow();
assert_ne!(a.id, b.id);
}
This fails:
thread 'main' panicked at 'assertion failed: `(left != right)`
left: `6`,
right: `6`', src/main.rs:23:25
You are trying to borrow the exact same node twice at the same time.
Thanks! realized need to explicitly clone on theNonebranch for individual nodes to have independentdata
– suyash
Jan 20 at 16:31
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54277188%2funable-to-mutably-borrow-the-contents-inside-a-refcell-even-after-the-scope-of%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
What am I missing here?
Your algorithm is broken. You can see this by adding this debugging code inside of the Some arm of the match:
{
let a = current_data.borrow();
let b = other.borrow();
assert_ne!(a.id, b.id);
}
This fails:
thread 'main' panicked at 'assertion failed: `(left != right)`
left: `6`,
right: `6`', src/main.rs:23:25
You are trying to borrow the exact same node twice at the same time.
Thanks! realized need to explicitly clone on theNonebranch for individual nodes to have independentdata
– suyash
Jan 20 at 16:31
add a comment |
What am I missing here?
Your algorithm is broken. You can see this by adding this debugging code inside of the Some arm of the match:
{
let a = current_data.borrow();
let b = other.borrow();
assert_ne!(a.id, b.id);
}
This fails:
thread 'main' panicked at 'assertion failed: `(left != right)`
left: `6`,
right: `6`', src/main.rs:23:25
You are trying to borrow the exact same node twice at the same time.
Thanks! realized need to explicitly clone on theNonebranch for individual nodes to have independentdata
– suyash
Jan 20 at 16:31
add a comment |
What am I missing here?
Your algorithm is broken. You can see this by adding this debugging code inside of the Some arm of the match:
{
let a = current_data.borrow();
let b = other.borrow();
assert_ne!(a.id, b.id);
}
This fails:
thread 'main' panicked at 'assertion failed: `(left != right)`
left: `6`,
right: `6`', src/main.rs:23:25
You are trying to borrow the exact same node twice at the same time.
What am I missing here?
Your algorithm is broken. You can see this by adding this debugging code inside of the Some arm of the match:
{
let a = current_data.borrow();
let b = other.borrow();
assert_ne!(a.id, b.id);
}
This fails:
thread 'main' panicked at 'assertion failed: `(left != right)`
left: `6`,
right: `6`', src/main.rs:23:25
You are trying to borrow the exact same node twice at the same time.
answered Jan 20 at 15:59
ShepmasterShepmaster
154k14304442
154k14304442
Thanks! realized need to explicitly clone on theNonebranch for individual nodes to have independentdata
– suyash
Jan 20 at 16:31
add a comment |
Thanks! realized need to explicitly clone on theNonebranch for individual nodes to have independentdata
– suyash
Jan 20 at 16:31
Thanks! realized need to explicitly clone on the
None branch for individual nodes to have independent data– suyash
Jan 20 at 16:31
Thanks! realized need to explicitly clone on the
None branch for individual nodes to have independent data– suyash
Jan 20 at 16:31
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54277188%2funable-to-mutably-borrow-the-contents-inside-a-refcell-even-after-the-scope-of%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Idiomatic Rust uses a leading underscore to indicate that a variable or type is unused. That's not the case here, so you should not name your type
_Node.– Shepmaster
Jan 20 at 15:54