-
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 as_unsafe_cell
stabilization
#27708
Comments
cc @kmcallister, I think you may have employed these methods in Servo? |
We do use the methods for RefCell: http://mxr.mozilla.org/servo/search?string=as_unsafe_cell . We appear to do so in cases where a GC could occur at virtually any time and the there may be outstanding borrows of fields that need to be traced. Similarly, it gets used for cases when we want to ensure certain resources are cleaned up if a panic occurs but there may be outstanding borrows that would prevent doing this through the stable, safe interface. Finally, we also use this for parallel code, but @pcwalton will need to explain the motivation there I think. |
Nominating for resolution in 1.5 |
The libs team decided to not move this issue to FCP for this cycle. @jdm, can you clarify something for us? It looks like this method is used to subvert any active borrows of a |
When you describe it like that, it does sound pretty incorrect. |
@jdm @alexcrichton If this is done during a tracing phase in which the thread owning the |
I'd be a little worried in terms of optimizations here if we told LLVM something along the lines of "you have a mutable pointer, make any assumption you like knowing that no one else will ever have this pointer unless you hand it to them". That sort of contract would be violated where even if the mutator were paused an optimization may still trigger undefined behavior. Concretely, if the source looked like: let slot = a.borrow_mut();
println!("{}", slot.foo);
function();
println!("{}", slot.foo); It seems like a valid optimization that the value loaded from Again though, this is all very hypothetical, I'd certainly be willing to believe that the exact situation here actually works out due to some combination of some actions or whatnot. |
Note that there should not be any mutation taking place in |
It seems that the |
I'm using this function to check if two |
@Columbus240 Why is this needed to compare memory locations? Or rather, why is comparing the location of fn same_refs<T>(a: &T, b: &T) -> bool {
let a: *const T = a;
let b: *const T = b;
a == b
} |
@SimonSapin Thank you, I didn't know that worked. I couldn't infer from the books page about unsafe pointers how I had to use them. I thought the |
"You hand it to them" is
|
Servo update: with servo/servo#11835 we have a copy of Still forking parts of the standard library is not great and we’d still like |
🔔 This issue is now entering a cycle-long final comment period 🔔 The libs team was a bit up in the air about what to do about this method. It was pointed out that we may wish to prefer a method like Of the three states that a RefCell can be in:
There was a general sentiment that to stabilize we need to document what you can actually do with the return value. That is, we're returning an unsafe pointer, but there should be some safe operations you can do on it which would otherwise be impossible with the borrow/borrow_mut methods. It was thought that depending on what Servo needs here it may actually be a different abstraction that's needed (e.g. something that can always be traced regardless of borrow state), but we weren't actually 100% clear on what Servo was actually using these methods for still. @SimonSapin or @jdm, could you clarify exactly how Servo is using these methods today? Overall the libs team feels like FCP is appropriate because:
So basically, we'd like to foster discussion during the FCP to see what the fate should be! |
I’m not entirely sure why we use this in Servo layout. My current guess is that it’s what I’ll call a "YOLO RW lock". We have one thread (script) that can write to this data, and N threads (layout) that can read it. We don’t want lots of fine-grained actual But We don’t use a raw
We can always build our own things on top of |
@SimonSapin OK, I figured it was something like that -- a case where an external protocol is providing some additional guarantees that let you access the direct contents safely. One other question: is there any reason this needs to yield an |
@aturon On one hand every call to |
That sounds pretty reasonable to me, so I wouldn't mind stabilizing something like: /// Get a raw pointer to the data contained in this `RefCell`.
///
/// The returned pointer will point directly at the data contained within, and
/// this method will make no modifications to the borrow flag of this `RefCell`
/// as well.
///
/// Note that it is not safe to use this pointer if the `RefCell` is borrowed
/// mutably at this time, but if this `RefCell` is not mutably borrowed it is
/// safe to use the returned pointer as `&T` at least.
pub fn get_ptr(&self) -> *mut T { /* ... */ } Or something akin to that. |
Yep, I agree. @SimonSapin, the reason not to expose the |
What’s the naming convention for |
Oh I'd be fine with |
There's a bit of a clash, since we use I think |
Discussed recently, the libs team decided to stabilize. Our conclusion was to call these methods |
Stabilized * `Cell::as_ptr` * `RefCell::as_ptr` * `IpAddr::is_{unspecified,loopback,multicast}` * `Ipv6Addr::octets` * `LinkedList::contains` * `VecDeque::contains` * `ExitStatusExt::from_raw` - both on Unix and Windows * `Receiver::recv_timeout` * `RecvTimeoutError` * `BinaryHeap::peek_mut` * `PeekMut` * `iter::Product` * `iter::Sum` * `OccupiedEntry::remove_entry` * `VacantEntry::into_key` Deprecated * `Cell::as_unsafe_cell` * `RefCell::as_unsafe_cell` * `OccupiedEntry::remove_pair` Closes rust-lang#27708 cc rust-lang#27709 Closes rust-lang#32313 Closes rust-lang#32630 Closes rust-lang#32713 Closes rust-lang#34029 Closes rust-lang#34392 Closes rust-lang#34285 Closes rust-lang#34529
std: Stabilize APIs for the 1.12 release Stabilized * `Cell::as_ptr` * `RefCell::as_ptr` * `IpAddr::is_{unspecified,loopback,multicast}` * `Ipv6Addr::octets` * `LinkedList::contains` * `VecDeque::contains` * `ExitStatusExt::from_raw` - both on Unix and Windows * `Receiver::recv_timeout` * `RecvTimeoutError` * `BinaryHeap::peek_mut` * `PeekMut` * `iter::Product` * `iter::Sum` * `OccupiedEntry::remove_entry` * `VacantEntry::into_key` Deprecated * `Cell::as_unsafe_cell` * `RefCell::as_unsafe_cell` * `OccupiedEntry::remove_pair` Closes #27708 cc #27709 Closes #32313 Closes #32630 Closes #32713 Closes #34029 Closes #34392 Closes #34285 Closes #34529
Stabilized * `Cell::as_ptr` * `RefCell::as_ptr` * `IpAddr::is_{unspecified,loopback,multicast}` * `Ipv6Addr::octets` * `LinkedList::contains` * `VecDeque::contains` * `ExitStatusExt::from_raw` - both on Unix and Windows * `Receiver::recv_timeout` * `RecvTimeoutError` * `BinaryHeap::peek_mut` * `PeekMut` * `iter::Product` * `iter::Sum` * `OccupiedEntry::remove_entry` * `VacantEntry::into_key` Deprecated * `Cell::as_unsafe_cell` * `RefCell::as_unsafe_cell` * `OccupiedEntry::remove_pair` Closes rust-lang#27708 cc rust-lang#27709 Closes rust-lang#32313 Closes rust-lang#32630 Closes rust-lang#32713 Closes rust-lang#34029 Closes rust-lang#34392 Closes rust-lang#34285 Closes rust-lang#34529
std: Stabilize APIs for the 1.12 release Stabilized * `Cell::as_ptr` * `RefCell::as_ptr` * `IpAddr::is_{unspecified,loopback,multicast}` * `Ipv6Addr::octets` * `LinkedList::contains` * `VecDeque::contains` * `ExitStatusExt::from_raw` - both on Unix and Windows * `Receiver::recv_timeout` * `RecvTimeoutError` * `BinaryHeap::peek_mut` * `PeekMut` * `iter::Product` * `iter::Sum` * `OccupiedEntry::remove_entry` * `VacantEntry::into_key` Deprecated * `Cell::as_unsafe_cell` * `RefCell::as_unsafe_cell` * `OccupiedEntry::remove_pair` Closes #27708 cc #27709 Closes #32313 Closes #32630 Closes #32713 Closes #34029 Closes #34392 Closes #34285 Closes #34529
So where is that method on Cell? On RefCell? We need this in Servo. Edit: oh, didn't realise the docs online aren't up-to-date. |
@alexcrichton Yeah sorry, just didn't wake up enough before opening my mouth. |
Stabilized * `Cell::as_ptr` * `RefCell::as_ptr` * `IpAddr::is_{unspecified,loopback,multicast}` * `Ipv6Addr::octets` * `LinkedList::contains` * `VecDeque::contains` * `ExitStatusExt::from_raw` - both on Unix and Windows * `Receiver::recv_timeout` * `RecvTimeoutError` * `BinaryHeap::peek_mut` * `PeekMut` * `iter::Product` * `iter::Sum` * `OccupiedEntry::remove_entry` * `VacantEntry::into_key` Deprecated * `Cell::as_unsafe_cell` * `RefCell::as_unsafe_cell` * `OccupiedEntry::remove_pair` Closes rust-lang#27708 cc rust-lang#27709 Closes rust-lang#32313 Closes rust-lang#32630 Closes rust-lang#32713 Closes rust-lang#34029 Closes rust-lang#34392 Closes rust-lang#34285 Closes rust-lang#34529
Stabilized * `Cell::as_ptr` * `RefCell::as_ptr` * `IpAddr::is_{unspecified,loopback,multicast}` * `Ipv6Addr::octets` * `LinkedList::contains` * `VecDeque::contains` * `ExitStatusExt::from_raw` - both on Unix and Windows * `Receiver::recv_timeout` * `RecvTimeoutError` * `BinaryHeap::peek_mut` * `PeekMut` * `iter::Product` * `iter::Sum` * `OccupiedEntry::remove_entry` * `VacantEntry::into_key` Deprecated * `Cell::as_unsafe_cell` * `RefCell::as_unsafe_cell` * `OccupiedEntry::remove_pair` Closes rust-lang#27708 cc rust-lang#27709 Closes rust-lang#32313 Closes rust-lang#32630 Closes rust-lang#32713 Closes rust-lang#34029 Closes rust-lang#34392 Closes rust-lang#34285 Closes rust-lang#34529
The
Cell::as_unsafe_cell
andRefCell::as_unsafe_cell
methods return a reference to the underlyingUnsafeCell
in both cases.It's not clear what the use cases are for these methods and whether they can be achieved in some alternative way. If you are using these methods, please leave a comment with your use case.
The text was updated successfully, but these errors were encountered: