• python
  • javascript
  • reactjs
  • sql
  • c#
  • java
Facebook Twitter Instagram
Devs Fixed
  • python
  • javascript
  • reactjs
  • sql
  • c#
  • java
Devs Fixed
Home ยป Resolved: Is it possible to borrow different parts of self with different mutability statically?

Resolved: Is it possible to borrow different parts of self with different mutability statically?

0
By Isaac Tonny on 17/06/2022 Issue
Share
Facebook Twitter LinkedIn

Question:

I am designing some struct with a prepare-commit pattern in rust, which mostly looks like this after simplified:
This snippet does not compile. The problem with the code snippet is that since Adder is borrowing data as mutable, upon the creation of Adder struct, all other immutable borrows (e.g.Holder here) could not live past. However, the add_once calls really do not need to borrow data mutably, only commit does that. Ideally there should be some way in rust to let the compiler know that add_once only needs added as mutable but not data, so that Holder could live past add_once calls but not commit call.
I do know two possible current solutions to this, however I think they both have drawbacks:
  1. I could wrap fields of Adder in RefCell and borrow entire Adder immutably, only borrows mutably when needed. The problem with this approach is that RefCell checks borrowing dynamically, when in this case it really does not need to be that way since all lifetime bounds should be known at compile time, just different parts of a struct could have different bounds.
  2. I could do unsafe blocks to convert references to raw pointers and do whatever I want. However as far as I think about it I could not find a way to do it without disable all borrow checks altogether (I don’t really know how to do unsafe rust properly). And I want a borrow check so that if Holder lives past commit the compiler would still give a proper borrow error

So summary of questions:
  • Is there a static and safe way in rust to borrow different parts of self, with different mutability?
  • If not, is there a unsafe boilerplate to do so, still ensuring the proper borrow check as described above? (and if there is an existing crate for this)
  • What is the best practice in general for these situations?
  • Is there any RFC addressing this issue from rust language level?

Answer:

Is there a static and safe way in rust to borrow different parts of self, with different mutability?


No.

If not, is there a unsafe boilerplate to do so, still ensuring the proper borrow check as described above? (and if there is an existing crate for this)


You can use unsafe for that, but it will require you to work with raw pointers only. You may be able to encapsulate it in a safe API, but it’s unlikely that inside the code you’ll have proper automatic verification. For this reason I also don’t believe there is a crate for that, at least I don’t know one.

What is the best practice in general for these situations?


It depends.
I would use RefCell (or other interior mutability primitives such as Cell – note that if you can use Cell it is actually zero-cost) for that generally, and use unsafe code if profiling shows a bottleneck. However, this kind of issues many times arises from improper API design. So first I’ll see if I can redesign my API so the problem will not exist.

Is there any RFC addressing this issue from rust language level?


Not today, and I think it is very unlikely in the future.
There was something similar suggested while working on two phase borrows: https://github.com/rust-lang/rust/issues/49434. The idea was that any mutable reference will start as shared and only “upgrade” when it is actually used. In can be extended to “upgrade” only when a mutable reference is actually required, and this is basically what you propose.
However, the effect of two-phase borrows is completely local. For your code to work, we will have to need some way to represent time-aware mutable reference in a type. I don’t see that happening.
In addition, two-phase borrows work poorly with Stacked Borrows. @RalfJung ended up with just using raw pointers when two phase borrows are involved. Using them for everything will probably mean poor optimization opportunities (although maybe future models, or even Stacked Borrows itself, will find a way to handle that).

If you have better answer, please add a comment about this, thank you!

rust
Share. Facebook Twitter LinkedIn

Related Posts

Resolved: How to make statement case insensitive when uploading a dta file with specified columns?

27/03/2023

Resolved: Sort dataframe columns value by close it to another column

27/03/2023

Resolved: PostgreSQL resample 1 minute OHLCV candle data into 5 minute OHLCV candle data

27/03/2023

Leave A Reply

© 2023 DEVSFIX.COM

Type above and press Enter to search. Press Esc to cancel.