Uh oh!
There was an error while loading. Please reload this page.
Implement Arc/Rc raw pointer conversions for ?Sized - #44073
Conversation
rust-highfive
commented
Aug 24, 2017
r? @BurntSushi (rust_highfive has picked a reviewer for you, use r? to override) |
murarth
commented
Aug 24, 2017
I believe this change is totally backward compatible and it makes sense with the recently merged (It was actually a comment on another project referencing that PR which made me aware that |
BurntSushi
commented
Aug 28, 2017
cc @rust-lang/libs It seems like this is a good thing to have, but I need help reviewing the actual implementation. Could someone describe at a high level what's going on in the |
murarth
commented
Aug 28, 2017
@BurntSushi: The implementation of First, the definition of So, the implementation works like this:
All of the weird trickery is used so that the same code that does the right thing for a trait object |
cristicbz
commented
Aug 30, 2017
This was discussed in #37197 . We didn't implement it for I'm pretty convinced at this point that the correct way to do this is to have a built-in |
cristicbz
commented
Aug 30, 2017
cc @Amanieu (they came up with a DST |
Here's a link to my implementation for reference. It is still technically UB since it derefs an invalid pointer, but it works well enough in practice until we get proper support for |
murarth
commented
Aug 30, 2017
Well, shoot. I didn't realize that getting an offset from an invalid pointer was technically a dereference and therefore undefined behavior. So, it looks like a compiler-supported |
carols10cents
commented
Sep 11, 2017
@BurntSushi@cristicbz @rust-lang/libs any of yinz have an answer to @murarth's question? ^^ |
BurntSushi
commented
Sep 11, 2017
I'm out of depth on this one. I've assigned it to @alexcrichton |
alexcrichton
commented
Sep 11, 2017
@murarth ah yeah unfortunately I think that may still be holding this back. That being said though I don't think anything is blocking an implementation of |
murarth
commented
Sep 12, 2017
@alexcrichton: I did run into a few issues trying to implement an |
alexcrichton
commented
Sep 12, 2017
That seems fine to me as an implementation detail for now, but an alternate route could be to use a custom macro like |
murarth
commented
Sep 12, 2017
If using a custom AST node is more flexible, that's probably a better idea than a weird intrinsic thing. Looking back at my attempted implementation, I realize the problem I ran into: In order to have Use of So, TL;DR: I'm not familiar with how AST expressions eventually become code, but I will look into it and see what I can do. |
alexcrichton
commented
Sep 12, 2017
Yeah I think using a custom AST node should help you solve that problem, for example the Another route would be to perhaps poke around with constant evaluation with an intrinsic to try to constant evaluate the field argument and that should be able to give you a string I think? |
murarth
commented
Sep 15, 2017
@alexcrichton: I've run into an issue implementing Trying to resolve this by adding a |
alexcrichton
commented
Sep 16, 2017
Ah unfortunately I may not be of much help there, but maybe @eddyb can help? |
You can use pointers inside an |
murarth
commented
Sep 16, 2017
@eddyb: I'm not sure what you're talking about. Can you give me an example? And would it work with unsized types, e.g. |
eddyb
commented
Sep 16, 2017
@murarth So the second thing people usually go to when unionMaybeUninitialized<T>{value:T,dummy:()}let uninit:MaybeUninitialized<RcBox<T>> = MaybeUninitialized{dummy:()}I assume you had a solution for unsized unionFatThin<T: ?Sized>{fat:*mutT,thin:*mut()}letmut combined = FatThin{fat: ptr as*mutRcBox<T>};
combined.thin = &uninit.valueas*const_as*const();let base_ptr = &uninit.valueas*const_asusize;let data_ptr = &(*combined.fat).dataas*const_asusize;let offset = data_ptr - base_ptr;Oh, I see, writing this, OTOH, how were you going to pass the fat metadata to the compiler in an |
murarth
commented
Sep 16, 2017
Manually calculating offset using |
eddyb
commented
Sep 16, 2017
So you wanted to implemented a safe equivalent of getting the offset by subtracting the |
murarth
commented
Sep 16, 2017
If it's safe to assume now and into the foreseeable future that @alexcrichton: Would that be acceptable for the implementation of this PR? |
eddyb
commented
Sep 16, 2017
What I meant is more like aligning Also you could use |
murarth
commented
Sep 16, 2017
Yeah, the power of two thing is what I was basing that on, but using |
alexcrichton
commented
Sep 16, 2017
This all sounds reasonable to me, thanks for the tips @eddyb! |
* Add `T: ?Sized` bound to {`Arc`,`Rc`}::{`from_raw`,`into_raw`}murarth
commented
Sep 17, 2017
@alexcrichton: Tests passed on the new implementation. |
alexcrichton
commented
Sep 17, 2017
@bors: r+ A great trick! |
bors
commented
Sep 17, 2017
📌 Commit 1cbb2b3 has been approved by |
…crichton
Implement `Arc`/`Rc` raw pointer conversions for `?Sized`
* Add `T: ?Sized` bound to {`Arc`,`Rc`}::{`from_raw`,`into_raw`}bors
commented
Sep 17, 2017
⌛ Testing commit 1cbb2b3 with merge 1d2511ea0c6bd20c9f8d843dd60f4f3529b81fd3... |
…crichton
Implement `Arc`/`Rc` raw pointer conversions for `?Sized`
* Add `T: ?Sized` bound to {`Arc`,`Rc`}::{`from_raw`,`into_raw`}TimNN
commented
Sep 17, 2017
@bors retry
|
bors
commented
Sep 17, 2017
⌛ Testing commit 1cbb2b3 with merge 278c86f8c90c8beb958003c5e3c11923357ee1e9... |
…crichton
Implement `Arc`/`Rc` raw pointer conversions for `?Sized`
* Add `T: ?Sized` bound to {`Arc`,`Rc`}::{`from_raw`,`into_raw`}TimNN
commented
Sep 17, 2017
@bors retry
|
bors
commented
Sep 17, 2017
cristicbz
commented
Sep 17, 2017
+ // Align the unsized value to the end of the ArcInner.
+ // Because it is ?Sized, it will always be the last field in memory.
+ let align = align_of_val(&*ptr);
+ let layout = Layout::new::<ArcInner<()>>();
+ let offset = (layout.size() + layout.padding_needed_for(align))asisize;Hmmm, is this actually correct if |
eddyb
commented
Sep 17, 2017
@cristicbz a pointer to |
cristicbz
commented
Sep 17, 2017
That's interesting... thanks for the explanation. I guess I assumed the vtable somehow implicitly expressed the offset to the unsized field, but I'd never given it much thought. |
T: ?Sizedbound to {Arc,Rc}::{from_raw,into_raw}