-
Notifications
You must be signed in to change notification settings - Fork 13k
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 Rc::into_raw, Rc::from_raw, Arc::into_raw, Arc::from_raw #37197
Comments
Add `{into,from}_raw` to Rc and Arc These methods convert to and from a `*const T` for `Rc` and `Arc` similar to the way they work on `Box`. The only slight complication is that `from_raw` needs to offset the pointer back to find the beginning of the `RcBox`/`ArcInner`. I felt this is a fairly small addition, filling in a gap (when compared to `Box`) so it wouldn't need an RFC. The motivation is primarily for FFI. (I'll create an issue and update a PR with the issue number if reviewers agree with the change in principle **Edit: done #37197**) ~~Edit: This was initially `{into,from}_raw` but concerns were raised about the possible footgun if mixed with the methods of the same name of `Box`.~~ Edit: This was went from `{into,from}_raw` to `{into,from}_inner_raw` then back to `{into,from}_raw` during review.
@alexcrichton shouldn't this have a |
Oops, indeed! |
And while we're at it, I'd like to stabilize this! @rfcbot fcp merge |
Team member @alexcrichton has proposed to merge 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. |
Is there any chance of putting |
Also I think |
@Amanieu could you elaborate on why you'd like to see these as a trait? I do think that'd be a breaking change to remove the inherent methods on Also on a technical level is accepting unsized types possible? Consider something like going from |
@alexcrichton I'm building a safe interface for Regarding vtables, I was under the impression that the vtable pointer in |
Hm yeah it's true I'm not entirely sure what the vtable would look like. Would be good to clarify before we support the functionality! |
|
I'm looking forward to have something like |
Unlike C++ we don't support splitting the allocation of the ref counts from
the allocation of the data, so that would be a bigger change. Not sure it
can be done backwards compatibly even without this functionality.
What use case is not covered by Rc::new(self)? (i. e. Moving into an Rc)
…On Thu, 29 Dec 2016, 03:41 Tatsuyuki Ishi, ***@***.***> wrote:
I'm looking forward to have something like std::shared_from_this(C++),
thus constructing a new Arc from a reference (probably &self).
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#37197 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAw6MBL-NyHx80L_EJKVAwzSHeBPoAF8ks5rMyvcgaJpZM4KX0hQ>
.
|
The best thing is to take self as &Arc, but it's impossible due to the language design. This is common in building circular reference, which has been hard to do in safe area of Rust. |
Hmm this might be trickier than I thought. How would you implement |
I'm not ready to sign off on this until the DST implications as raised by @Amanieu are understood. |
Here is an implementation of unsafe fn from_raw(ptr: *const T) -> Rc<T> {
let fake_rc: Self = mem::transmute(ptr);
let fake_rc_target = fake_rc.as_ref() as *const _ as *const u8;
mem::forget(fake_rc);
let raw_ptr = ptr as *const u8;
let rc_ptr = raw_ptr.offset(raw_ptr as isize - fake_rc_target as isize);
let mut result = mem::transmute(ptr);
ptr::write(&mut result as *mut _ as *mut *const u8, rc_ptr);
result
} |
@Amanieu That's great! My only worry is:
Doesn't |
@cristicbz Yes it's an invalid pointer, but it should be fine as long as it isn't dereferenced. Here is an updated version of the code with more comments: unsafe fn from_raw(ptr: *const T) -> Rc<T> {
// Create a temporary fake Rc object from the given pointer and
// calculate the address of the inner T.
let fake_rc: Self = mem::transmute(ptr);
let fake_rc_target = fake_rc.as_ref() as *const _;
mem::forget(fake_rc);
// Calculate the offset of T in RcBox<T>
let rc_offset = (fake_rc_target as *const u8) as isize - (ptr as *const u8) as isize;
// Get the address of the RcBox<T> by subtracting the offset from the
// pointer we were originally given.
let rc_ptr = (ptr as *const u8).offset(-rc_offset);
// If T is an unsized type, then *const T is a fat pointer. To handle
// this case properly we need to preserve the second word of the fat
// pointer but overwrite the first one with our adjusted pointer.
let mut result = mem::transmute(ptr);
ptr::write(&mut result as *mut _ as *mut *const u8, rc_ptr);
result
} |
@Amanieu I'm never too clear on exactly under what conditions producing pointers to unallocated (or one past the end of an allocation) memory is fine. I thought using the GEP instruction in LLVM to produce one (which I think includes field access in rust) was UB (as per http://llvm.org/docs/GetElementPtr.html#what-happens-if-an-array-index-is-out-of-bounds) |
The only other option is to make |
Another option is to only support it for |
Compiled in release mode, the optimised IR looks reasonable:
The debug version is less fun to read because it actually invokes |
@Amanieu I don't think we can hardcode the offset since different Edit: What sorcery is this: https://is.gd/2vbxPp? It looks like field offsets are stored in vtable somehow? But then |
@cristicbz The alignment is encoded in the vtable for unsized types. We can still do this alignment in the offset calculation ourselves: |
I posted this on the original PR, but here is probably better. I find @cristicbz's reasoning for initially going with |
@rkjnsn Your statement about my statement is correct. Sometimes these types directly point to mutable memory, so the pointer should be mutable. With the ambiguity about the semantics of |
@brson I think that the main argument in favor of |
@brson, I seem to recall |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
I would like to reiterate that I am strongly opposed to these stabilizing using |
@rkjnsn I guess that's what FCP is for. I still agree with you and am happy to write a quick PR to change the return type if @brson and @alexcrichton are persuaded. For me For what it's worth, I don't buy the argument about people putting mutable things into an |
Ah yes that's what FCP is for to figure out details such as this. So to elaborate on my opinion again first of all I'd like to clarify that With that in mind I still believe that In general we have lots of precedent with |
Full ack, that's why I didn't put up any kind of "fight" on the original PR.
So maybe I'm missing something here, but I see two cases for an
The reason we have lots of precedent with
|
For me, the fact that It is true that many usages of While The documentation for
The contents of an If the author of safe code ensures there are no aliases and none can be created while mutation is possible (as |
The point about So #37192 was using I definitely agree that it seems odd to return A naive attempt at a reproduction failed, but I'd be worried about a case where:
Is such a scenario possible? Or am I just thinking of something totally different? |
@alexcrichton Hadn't thought about variance, why is |
@alexcrichton Acutally, it looks like (which makes sense to me, it's just like a shared-ref, |
Oh yes I would want to be sure that if we choose |
As I understand it (forgive me if I am mistaken in here somewhere), Further, since Finally, neither It seems to me, then, that If I had to speculate, I would guess that EDIT: Rather, I would speculate that |
That seems like a reasonable explanation to me, and if we change @brson do you have other specific thoughts here? |
So what is the consensus regarding support for DSTs? We could start by only implementing |
I'm not very enthusiastic about stabilizing this with so much confusion about the proper type. The questions about variance worry me too. If there are variance concerns here let's add tests for them. This all feels risky. |
So #29110 added @brson What sort of tests would you like added? For the variance of @Amanieu DST-wise yeah I thought that's sort-of where we left it. For DST-s it's a slightly bigger can of worms (see #37197 (comment)) and I'd be too worried about potential UB without an |
The final comment period is now complete. |
Since the FCP is over, I'll sum up where I stand:
|
My summary:
|
Ah so to clarify the FCP ending here is just the standard one week period. In reality it'll "end" a week before the end of the cycle when we merge this. I'm leaning towards changing to |
Discussed during @rust-lang/libs triage today, the conclusion was to go with |
Methods being added in #37192.
The text was updated successfully, but these errors were encountered: