Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Structs with slices pointing to data in themselves

Tags:

rust

I have a struct

struct Foo<'a> {
    buf: [u8, ..64],
    slice: &'a [u8]
}

The slice is supposed to point into the buf field of the struct. Is there any way to construct such a struct? Something like:

impl<'a> Foo<'a> {
    fn new() -> Foo<'a> {
        Foo {
            buf: [0, ..64],
            slice: ???? /* I don't know what to write here */
    }
}

If I try to do something like the following, the borrow checker complains (correctly), since the slice will have a shorter lifetime than the struct.

impl<'a> Foo<'a> {
    fn new() -> Foo<'a> {
        let buf = [0, ..64];
        Foo {
            buf: buf,
            slice: buf.slice_from(0)
        }
    }
}

I realize that for this simple case I could keep offsets and manually call the slice functions:

struct Foo {
    buf: [u8, ..64],
    slice_from: uint,
    slice_to: uint
}

However this question is just a simplification of a more general use case of a struct owning data and having references into the same data and I'm wondering if that is possible (in a safe way) in Rust.

like image 259
dnaq Avatar asked Dec 04 '14 12:12

dnaq


1 Answers

No, you can't do it safely, because in general such a structure is not movable. Pretend it is possible, and you can create such a structure:

let foo = Foo {
    buf: [0, ..64],
    slice: obtain_slice_somehow()
};

The slice field is now a slice of buf field, in particular, it contains a pointer to buf, which is currently located on the stack. Now put foo into a box and return it from the function:

return Box::new(foo);

foo value is now moved to heap, and the function exits, freeing its stack memory. However, slice pointer is not adjusted to point to heap, because it is impossible to do in general, and so it left dangling, violating memory safety.

like image 59
Vladimir Matveev Avatar answered Oct 05 '22 07:10

Vladimir Matveev