Borrowing mutable reference with an explicit lifetime in a build method (constructor) [Solved]


#1

Hello, dear community!

I’ve met an issue related to mutable borrowing with pointing lifetimes. I have a structure that has a field contains a vector of references. The references live same time as an instance of the structure; it references on values from a vector from the same instance.

I’ve decided to separate a synchronization of references and values to a method; I get an error says me that the instance does not live not enough. And it happens only when I point lifetime and mutable borrowing. But without them I can’t make a reference on data from the instance.

How can I use a method borrows a mutable reference inside a method that should return a newly created instance?

https://play.rust-lang.org/?gist=9b1637146422d688fbadf738e6d44df7&version=stable it is code sample for clearance.

Thanks. Sorry if my English is not clear.


#2

I removed the 'r lifetime bound on the sync() method and it compiles fine (i.e. fn sync(&mut self) {...}).

I think the issue is that when you declare fn sync(&'r mut self) {...} you explicitly say that self must at least live as long as 'r. However in the Point::new() method, 'r can be thought of as starting at the very beginning of the method, while the lifetime of your p starts at the first line. So in that case, your point’s lifetime is smaller than 'r and compilation fails saying the thing’s lifetime is too small.


#3

I think what @ANtlord wants to do will ultimately not work, if I understood the intent, since it’ll try to create a self referencing struct.


#4

But I need to point a lifetime. sync method will have code gets a reference on a vector of values from the instance.

https://play.rust-lang.org/?gist=a7b8ed1471de6081e250282d1ef94409&version=stable I’ve renamed sync to sync_first_element. It implements getting a reference on first elements from the vector values and adds the refence to vector of references. If a lifetime from the mothod is removed then we can get an error about inferencing of a lifetime.

Is it self referencing struct? Is it design issue?


#5

I think @vitalyd has a point here, if vals_ref is pointing to the vals then that means part of your struct is borrowing itself. For one, that means you’ve got a permanent immutable borrow of the struct, so you’d never be able to update vals_ref anyway (syncing requires mutation and a mutable borrow).

The fact you are having these tricky lifetime issues may also be an indicator that you are trying to do something which may not actually work, or won’t work out as you expect it to. In that case it may be beneficial to step back and think about your design a bit more or look at alternatives.


#6

I got it. It appears i need advice. I have a set of structures NamedStruct. The structure has a field name. And I want to create ability to get an instance from the set by pointed name.

How did i create this? I created a field HashMap<String, NamedStruct> and I pushed all data to the field. But I’m confused by copying names to keys of the container. Does it possible to solve this issue? Or there is no way to implement this. I undestand I can remove name field but I want to be able to get name of an instance of NamedStruct structure.


#7

It appears I find what i need.

Thanks for all!


#8

A few options I see, which you may have already found:

  1. Use a HashSet to store your NamedStruct values. Then use HashSet::get to retrieve them. To make this work, you need to make NamedStruct impl Eq and Hash in terms of just the name String field. Then implement Borrow<str> for NamedStruct. You can then use str to get the struct.
  2. Continue storing in HashMap but use Rc<String> for the name.
  3. Continue storing in HashMap but take the name out of the struct. On retrieval, associate the name and struct in a tuple or another struct that couples the name with the rest of the values.

I’d probably try to use #1 above.


#9

Yes, I got the same conclusion. Thank you again!