Hi to all. The background for problem: I ran into some bizarre borrowck issues when trying to write a function that would modify a &mut &mut [u8]. The goal here was to make it simple to shove data DATA Online Ordering | DATA Brand Manufactures | PDF Datasheet | In-Stock into a [u8, ..512] by virtue of copying data into the corresponding &mut [u8] and then modifying the slice. I tried three different approaches, and they all had issues. The various errors are commented into the source.
(All 3 approaches require use std::vdc::MutableCloneableVector)
The first approach tried to define a function append(buf: &mut &mut [u8], v: &[u8]) that would copy the data into buf and then modify *buf to contain the new slice. This ran into an odd lifetime error where it thinks that I can't say *buf = buf.mut_slice_from(len). It claims the lifetime of buf is too short, but I don't see why that matters. I'm actually re-slicing *buf, and putting the result back into the same location that held the original slice, so I would expect it to have the same lifetime and, therefore, be valid.
fn one() {
let mut line = [0u8, ..512];
let mut buf = line.as_mut_slice();
fn append(buf: &mut &mut [u8], v: &[u8]) {
let len = buf.clone_from_slice(v);
*buf = buf.slice_from_mut(len);
// error: lifetime of buf
is too short to guarantee its contents can be safely reborrowed
// ^~~
// note: buf
would have to be valid for the anonymous lifetime #2 defined on the block at 7:45...
// note: ...but buf
is only valid for the anonymous lifetime #1 defined on the block at 7:45
}
append(&mut buf, b"test");
append(&mut buf, b"foo");
}
The second approach was to give both levels of indirection the same lifetime, e.g. append<'a>(&'a mut &'a mut [u8], v: &[u8]) to try and squelch the error. This didn't work because I wasn't allowed to reassign back to *buf, as it considered buf.mut_slice_from(len) to borrow it. I assume the borrow check is tied to the lifetime, which is shared at both levels, so borrowck thinks buf is borrowed when it's really *buf that's borrowed.
Curiously, it also decided I couldn't use &mut buf twice in the calling code, as it seemed to think it was already borrowed.
fn two() {
let mut line = [0u8, ..512];
let mut buf = line.as_mut_slice();
fn append<'a>(buf: &'a mut &'a mut [u8], v: &[u8]) {
let len = buf.copy_from(v);
*buf = buf.mut_slice_from(len);
// error: cannot assign to *buf
because it is borrowed
// ^~~~
// note: borrow of *buf
occurs here
// ^~~
}
append(&mut buf, bytes!("test"));
append(&mut buf, bytes!("foo"))
// error: cannot borrow buf
as mutable more than once at a time
// ^~~~~~~~
// note: previous borrow of buf
as mutable occurs here
// ^~~~~~~~
}
The third approach was to ditch &mut &mut [u8] entirely and try capturing buf in a closure instead. This gave some odd errors. First off, it kept referencing (*buf), and I don't know what it meant by that. Also, the first error here indicates that a borrow on a later line was blocking a borrow on an earlier line, which is quite bizarre. How can buf have been borrowed already when the later line is, well, later? It also considered the same reference to buf to consist of multiple mutable borrows.
fn three() {
let mut line = [0u8, ..512];
let mut buf = line.as_mut_slice();
let append = |v: &[u8]| {
let len = buf.copy_from(v);
// error: cannot borrow (*buf)[]
as mutable more than once at a time
// ^~~
buf = buf.mut_slice_from(len);
// note: previous borrow of (*buf)[]
as mutable occurs here
// ^~~
// error: cannot borrow (*buf)[]
as mutable more than once at a time
// ^~~
// note: previous borrow of (*buf)[]
as mutable occurs here
// ^~~
// error: cannot assign to buf
because it is borrowed
// ^~~
// note: borrow of buf
occurs here
// ^~~
};
append(bytes!("test"));
append(bytes!("foo"));
}
In the end, I couldn't figure out any way to accomplish what I wanted. It seems to me the first approach should have worked.
Thank you.