-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Tracking issue for borrow_state
stabilization
#27733
Comments
I believe @nikomatsakis has mentioned that he's found a use for these methods at some point, but I can't remember what those uses were off the top of my head. |
I've never used this pattern in Rust, but in previous lives I've been in the situation where I had a graph that was supposed to be acyclic. I was walking the graph, acquiring locks on the nodes as I went. This should not result in deadlock. The problem was that the graph was constructed from untrusted user input, and hence a deadlock was possible if the input was in error. This was neatly solved by using a 'try lock' structure, such that whenever we failed to acquire a lock, we could infer that the graph was potentially cyclic (and, if so, report an error). I can easily imagine a similar scenario arising with |
This issue is now entering its cycle-long FCP for stabilization in 1.5 |
I argued in the meeting today that we should instead opt to break the fallible/infallible convention and just have General ambivalence about this problem. This will remain unstable for at least one more release. |
The libs team discussed this during triage today and the decision was to punt to a future FCP. |
I find the "borrow-state" version rather annoying to use in practice. For On Wed, Oct 21, 2015 at 5:06 PM, Alex Crichton notifications@github.com
|
+1 for one method returning |
So to be clear here, the issue at hand is that we long ago settled on a simple convention to avoid combinatoric bloat:
This stance is strongly championed by @alexcrichton and @aturon, and for good reason! I don't want to live in a world with Vec::try_insert, try_remove, try_swap_remove, ...etc. However I maintain that all good conventions exist to be broken! Most obviously, we break this convention with indexing (and soon, slicing!). Part of this is that indexing and slicing are so fundamental that they deserve several ways to do them. Indexing in particular has 4:
At the heart of this convention is "decide if this is panicky or should be checked". For most interfaces we deem that it should be checked, because that's the strictly more general operation. There are two reasons to use panciky ops:
Index-based ops like insert/remove have both of these properties, and are therefore a great candidate for panicky ops. RefCell only has the second condition. It would be an ergonomic nightmare to have to unwrap ever borrow, so we went for panicky. However there's no way to introspect its state to check in a pinch. In deference to The Convention, the original solution was to make it so it could be trivially checked, but the problem here is that checking is totally useless unless you're about to |
@gankro I definitely think
The downside of "try" variants, of course, is just that you need to have one per function, typically, whereas you only need one method to expose the state. I wanted to expand on point 4, about forwards compatibility. I could imagine wanting to extend Another way to address concerns 2 and 4 (but not 3) by making the borrow-state opaque and have it offer methods like |
To be clear, I'm not advocating that borrow_state is more ergonomic than I see @gankro's slicing/indexing examples above as separate because they all deal with @nikomatsakis I definitely agree with many of your points, and it's why this is an extreme case for I also disagree that it's a cliff in terms of ergnomics, e.g. compare: if let Some(borrow) = cell.try_borrow_mut() {
// ...
} and if let BorrowState::None = cell.borrow_state() {
// .. work with cell.borrow_mut()
} Again, though, I'm not claiming it to be more ergonomic, I just want to point out that it's not necessarily the end of the world. This is especially compounded by the fact that we're talking about the 0.1% use case, if it were expected to be called quite a bit then we'd of course choose the more ergonomic version. I think your suggestion about method accessors would also be fine as it'd even reduce the number of imports! |
I think the real comparison is: if let Some(borrow) = cell.try_borrow_mut() {
} and use std::cell::BorrowState;
...
if BorrowState::None == cell.borrow_state() {
let borrow = cell.borrow_mut();
..
} I certainly agree it's not the end of the world, but I still think it kind I also disagree that this use case is 0.1%. I agree that detecting a cycle, However, ultimately, I would perhaps be mollified if we removed the borrow |
Although I nominated this for stabilization in 1.8, the libs team decided against it due to the double-check on the borrow flag. We'd instead like to explore methods like |
Isn't this code a race condition, in that it still may panic?
I'm not saying that |
@cbreeden |
oh right, thanks for clarifying that :) |
@rfcbot fcp close We've added/stabilized |
Team member @alexcrichton has proposed to close this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
👍 from me to removing in favor of |
🔔 This is now entering its final comment period, as per the review above. 🔔 psst @alexcrichton, I wasn't able to add the |
The final comment period is now complete. |
Library stabilizations/deprecations for 1.15 release Stabilized: - `std::iter::Iterator::{min_by, max_by}` - `std::os::*::fs::FileExt` - `std::sync::atomic::Atomic*::{get_mut, into_inner}` - `std::vec::IntoIter::{as_slice, as_mut_slice}` - `std::sync::mpsc::Receiver::try_iter` - `std::os::unix::process::CommandExt::before_exec` - `std::rc::Rc::{strong_count, weak_count}` - `std::sync::Arc::{strong_count, weak_count}` - `std::char::{encode_utf8, encode_utf16}` - `std::cell::Ref::clone` - `std::io::Take::into_inner` Deprecated: - `std::rc::Rc::{would_unwrap, is_unique}` - `std::cell::RefCell::borrow_state` Closes #23755 Closes #27733 Closes #27746 Closes #27784 Closes #28356 Closes #31398 Closes #34931 Closes #35601 Closes #35603 Closes #35918 Closes #36105
It turns out I actually have a use case in Servo where I can't use |
We've re-introduced this API as the unstable |
Servo has been using this since servo/servo#23196 to add a runtime check to some unsafe code, as discussed in PR #59211. Stabilizing would help do more of the same in libraries that also have users on Stable. @rfcbot fcp merge |
It looks like rfcbot doesn’t want to do FCP again in the same thread, even after removing labels. I’ve proposed FCP in a stabilization PR: #60850 |
It looks like this has not yet been addressed, but all the features discussed here are already stabilized. |
I'm not a technical writer and I don't see how to reduce the main use case into something smaller than how we are using this in Servo. |
Sure, no problem. Just noting the inconsistency. I guess it's fine to close this tracking issue though, since everything tracked is now stable. |
The
RefCell
API offers a way to determine the state of the borrow, to avoid panics on additional borrowing. It's not clear how useful this API is in practice, but it's otherwise ready for stabilization.EDIT: @KodrAus
Before stabilization:
The text was updated successfully, but these errors were encountered: