-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added RefCell methods update
and update_in_place
#38741
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
5e6c572
to
7ccda56
Compare
b56286f
to
04e1b29
Compare
04e1b29
to
e2ba791
Compare
Thanks for the PR @peterjoel! I'll cc @rust-lang/libs here as well in case others would like to weigh in. Personally, though, I feel that these APIs don't belong on It's true, though, that borrow scopes can often be a problem. Do explicit scopes not work out well in your use case? Do you find that they lose out in ergonomics? |
It's partly ergonomics. In the example above, the code is shorter and (I think) easier to read. It also doesn't introduce a new binding into the current block scope. I've been stung a few times where I've written code that works, and the borrow is in a small scope, but a future change grows the scope. The borrow and drop move further away from each other, which can be dangerous, especially when other methods could also borrow the same data. Expressing an update in a closure makes it inconvenient to let the block grow large, reducing the chance of this type of bug. Obviously it's not foolproof - borrowing the value again from inside the closure will still cause a panic. But I feel like it's easier to spot and less likely to happen. |
I have pretty mixed feelings about this PR. I understand the motivation, but I worry about a couple things:
In other words, it seems like a hard line to draw for API recommendation. I think this is another way of making @alexcrichton's point about the current minimalistic API for I also feel like, if you are worried enough about the issue to use these methods, you could just as well use explicit blocks today and get basically the same benefits. Finally, while On the whole, I think I'm personally not inclined to take this PR at this time. |
The line is probably that you should use
|
@aturon @alexcrichton I think I'm happy with your comment to not merge this, and to keep it in a 3rd party crate. The methods can be added to |
Ok in that case I'm going to close this, but thanks regardless for the PR @peterjoel! |
These two small methods help you protect yourself from accidentally mutably borrowing from a RefCell twice. This can happen easily when you need to update the data in a RefCell, when the new value depends on the old data.
The two variants are for ergonomic reasons, as you may have a method already of one form or the other. Or mutating the data in place may be more efficient sometimes.
Example usage with methods:
As a slightly contrived example of a problem case, the following code panics because the first borrow is still alive when the next one is requested:
This bug can be fixed by putting the borrow in its own block, so that it's dropped before it's needed again. But that not always obvious and might not be fixed if this only happens in an edge case or triggered by an untested error condition.
Using
update_in_place
, there is no possibility to make this mistake: