Open MatiasLyyra opened 1 year ago
In fact, your question is equivalent to
fn merge_tree(root: &mut Root, path: Vec<String>) {
let mut elements = &mut root.children;
if let Some((idx, el)) = elements.iter_mut().enumerate().next() {
// elements = &mut elements[idx].children;
elements = &mut el.children;
}
if let Some((idx, el)) = elements.iter_mut().enumerate().next() {
// elements = &mut elements[idx].children;
elements = &mut el.children;
}
}
I experimented more with this, and found that this is also equivalent. Also found a very suspicious workaround.
#[derive(Clone)]
pub struct Node {
pub children: Vec<Node>,
}
pub fn works(mut root: Vec<Node>) {
let mut null = Vec::new();
let mut elements = &mut root;
{
let mut tmp = &mut null;
if let Some(el) = elements.get_mut(0) {
tmp = &mut el.children;
}
elements = tmp;
}
elements.clear();
}
pub fn breaks(mut root: Vec<Node>) {
let mut elements = &mut root;
if let Some(el) = elements.get_mut(0) {
elements = &mut el.children;
}
elements.clear();
}
pub fn breaks(mut root: Vec<Node>) { let mut elements = &mut root; if let Some(el) = elements.get_mut(0) { elements = &mut el.children; } elements.clear(); }
Note that these two pieces of code are not equivalent.
The code equivalent to works is:
pub fn breaks(mut root: Vec<Node>) {
let mut null = Vec::new();
let mut elements = &mut root;
{
if let Some(el) = elements.get_mut(0) {
elements = &mut el.children;
} else {
elements = &mut null;
}
}
elements.clear();
}
This is because get_mut
is a method of &mut [T]
.
pub fn breaks(mut root: Vec<Node>) {
let mut elements = &mut root;
{
if let Some(el) = elements.deref_mut().get_mut(0) { // element's ownership is taken away by deref_mut
elements = &mut el.children; // this assignment extends the duration of ownership taken by deref_mut to the same as the lifetime of element
} else {
// Do Nothing
}
// element was borrowed all the lifetime, but only one branch returned it
}
elements.clear();
}
The original code compiles with -Zpolonius
.
Hi,
I came across following weird borrow check behaviour. If you uncomment
elements = &mut elements[idx].children;
and comment line below, program compiles ok. I think this is a bug.I tried this code:
I expected to see this happen: No compiler error.
Instead, this happened: Following compiler error:
Meta
rustc --version --verbose
:Backtrace
``` N/A ```