0

I wish to use an external struct (Framer) which &'a mut borrows a number of parameters in its new() method. This is a problem when I insert an instance of the struct in a HashMap with a larger scope. I understand why.

I wrapped the offending struct in my own struct in an attempt to overcome the problem - but again ran into ownership problems. Playground

struct Owned<'b> {
    buf: Box<[u8]>,
    foo: Option<Foo<'b>>,
}

impl<'b> Owned<'b> {
    pub fn new() -> Self {
        let mut owned = Self {
            buf: Box::new([0; 1000]),
            foo: None,
        };
        owned.foo = Some(Foo::new(&mut *owned.buf));
        owned
        /*
        ^^^^^ returns a value referencing data owned by the current function
        ^^^^^ returning this value requires that `*owned.buf` is borrowed for `'a`
        */
    }
}

I understand why returning owned exposes the borrowed buf. But, I feel that I should be able link the lifetime of owned.buf to owned.foo - but I cannot see how.

I would like to know:

  1. How to wrap Foo in Owned successfully
  2. Or alternatively, some better way to insert Foo in a HashMap from a larger scope.
Ry-
  • 218,210
  • 55
  • 464
  • 476
nhoj
  • 135
  • 2
  • 11
  • Thank you - but I have worked thru that answer - and still do not know how to proceed. If fact I thought that I was attempting to "Place types that own data into a structure together and then provide methods that allow you to get references or objects containing references as needed." but could not quite make it work – nhoj Mar 28 '22 at 00:24
  • In your case it means constructing the `Foo` instance on-the-fly. Is `Foo::new()` expensive? If not, it may be a viable approach. In general, we would need more details to come with a concrete solution. – Chayim Friedman Mar 28 '22 at 00:32
  • Unfortunately yes - `Foo::new()` is expensive. In the real-world case `Framer::new()` is followed by `Framer::connect()` which negotiates the setup of an enduring WebSocket. `Framer` is then stored in a HashMap for later retrieval and message processing. – nhoj Mar 28 '22 at 00:43
  • What is the error when stored in the map? – Chayim Friedman Mar 28 '22 at 00:51
  • As per the Playground link above - the HashMap.insert() is fine - but the HashMap.get() fails with `borrowed value does not live long enough` in the outer scope. – nhoj Mar 28 '22 at 01:22
  • 1
    It seems then that the answer is that this cannot be done in rust. This is a good answer because I learned a lot about rust trying to get this done. I was not missing some silly thing as I feared. (clearly I am still missing plenty - this is rust right!) So, the next question is: why was Framer designed in such an annoying way? And it turns out (with a little digging past the examples and into the code) that I was doing it wrong. And (as Chayim Friedman enquired) it is cheap to create a Framer (the cost is elsewhere), and a modest code redesign is in order. Thank you StackOverflow :-) – nhoj Mar 28 '22 at 08:14
  • @nhoj Note that it _is_ possible but you have to use `unsafe` and know what you're doing. – cdhowie Mar 29 '22 at 03:29

0 Answers0