3

Consider the following Rust code, using raw pointers:

struct InteriorPointer {
  element: Box<u32>,
  element_ptr: *const u32,
}

fn mk_interior_pointer() -> InteriorPointer {
  let mut result = InteriorPointer{
    element: Box::new(1u32),
    element_ptr: std::ptr::null(),
  };
  result.element_ptr = &*result.element as *const u32;
  result
}

(It's a bit silly in this minimal example, but you could imagine replacing element with a Vec<u32> and replacing element_ptr with a reference to the pointer to the largest element of the array.)

How can I write this code in safe rust, i.e. using a reference instead of a raw pointer? Here's what I tried:

struct InteriorPointer {
  element: Box<u32>,
  element_ref: &'static u32,
  // I actually want to say something like "&'self u32" or 
  // "&'lifetimeof(element) u32" but I'm not allowed.
}

fn mk_interior_pointer() -> InteriorPointer {
  let mut result = InteriorPointer{
    element: Box::new(1u32),
    element_ref: &dummy_element,
  };
  result.element_ref = &*result.element;
  result
}

static dummy_element: u32 = 5;

Unsurprisingly, this fails to compile:

src/lib.rs:11:25: 11:40 error: `*result.element` does not live long enough
src/lib.rs:11   result.element_ref = &*result.element;
                                  ^~~~~~~~~~~~~~~
note: reference must be valid for the static lifetime...
src/lib.rs:10:5: 13:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 10:4

Is there a way I can express the lifetime of element_ref correctly?

rp123
  • 3,623
  • 1
  • 18
  • 20
  • I don't see why the pointer becomes invalid. The pointer refers to heap-allocated data, and the heap allocation doesn't get deleted when moving the Box. I think this is also the difference from the potential duplicate: I'm heap-allocating the data I want to maintain a reference to. – rp123 Jun 27 '15 at 21:09
  • Woops, you're totally right, the pointer stays valid, apologies. – mdup Jun 27 '15 at 21:17
  • The answer stays the same, though; there is no way to provide an appropriate lifetime. It's a bit difficult to say without your real use case (as you say, the minimal example is... minimal). How about going with `Rc`? If you deal with vectors, how about indices instead of refs? – mdup Jun 27 '15 at 21:22
  • Ok, good to know that I'm not missing something. I'm mostly experimenting so I don't have a clear use case. I was thinking about vectors, for which indices are ok except that I now pay the cost of both a bounds check and having to read both the base pointer and the index. – rp123 Jun 27 '15 at 21:26
  • By the way, the answer "no, it's not possible" is fine by me. If you want to post that as a real answer I'll be happy to accept. Otherwise I can self-answer :). – rp123 Jun 27 '15 at 21:27

0 Answers0