-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 ptr::offset_from (feature: ptr_offset_from) #41079
Comments
I wonder whether this should have the The |
It seems suspicious at best to calculate the offset between two unrelated pointers... I agree with @scottmcm |
@pornel made the point that this should be |
Also, I find it unfortunate that this forces handling the ZST case even if you know the pointer type and know that it doesn't point to a zero-sized type. Could we use traits to provide a method that only exists for non-zero-sized types, and then returns |
I like @scottmcm's suggestion to have an unsafe I suggest omitting the [0] For example, |
I think that returning |
Renaming to I don’t really understand the @Amanieu since you added this, what do you think? |
I have no objection to renaming it to The
The current implementation rounds towards zero, however I am considering going with the UB route instead. Note that this situation can only happen if one of the pointers is misaligned, so we could just require that both pointers be properly aligned for their type. |
Can’t it also happen with aligned pointers, if |
That's a good point, I'm not sure why I thought of alignment there. You are correct. |
@SimonSapin That's a good point. C manages to avoid that issue, because in C it's undefined behavior if the pointers aren't both pointing to elements of the same array (6.5.6p9). I don't know whether Rust's |
@sunfishcode it seems... incredibly suspect to allow |
I started on a PR for this at #49297; feedback and suggestions appreciated. |
Amanieu and sunfishcode commented that doing As such, should this API change form to something where it can be |
Keep in mind that LLVM IR generated by Clang is just a I considered the name |
Introduce unsafe offset_from on pointers Adds intrinsics::exact_div to take advantage of the unsafe, which reduces the implementation from ```asm sub rcx, rdx mov rax, rcx sar rax, 63 shr rax, 62 lea rax, [rax + rcx] sar rax, 2 ret ``` down to ```asm sub rcx, rdx sar rcx, 2 mov rax, rcx ret ``` (for `*const i32`) See discussion on the `offset_to` tracking issue #41079 Some open questions - Would you rather I split the intrinsic PR from the library PR? - Do we even want the safe version of the API? #41079 (comment) I've added some text to its documentation that even if it's not UB, it's useless to use it between pointers into different objects. and todos - [x] ~~I need to make a codegen test~~ Done - [x] ~~Can the subtraction use nsw/nuw?~~ No, it can't #49297 (comment) - [x] ~~Should there be `usize` variants of this, like there are now `add` and `sub` that you almost always want over `offset`? For example, I imagine `sub_ptr` that returns `usize` and where it's UB if the distance is negative.~~ Can wait for later; C gives a signed result #41079 (comment), so we might as well, and this existing to go with `offset` makes sense.
In Nightly this is the tracking issue for three different inherent methods of both pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {…}
pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {…}
pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized {…} (Note: the The libs team discussed this and it wasn’t clear from this tracking issue or the implementation PR what is the motivation for this feature. @Amanieu Could you comment on what situations this would be used in, why it should be in the standard library, and why three different methods are needed? |
My understanding is that These methods are useful when converting between slices and raw pointers, which can happen when building data structures or with FFI. |
If this is a replacement, should |
I'll make a PR for that and to move vec&slice to offset_from. (Unless it should be deprecated for a bit first? I don't remember what the rules are for nightly things...) |
PR up at #41079 That did reinforce my feeling that |
Deprecate offset_to; switch core&alloc to using offset_from instead Bonus: might make code than uses `.len()` on slice iterators faster cc #41079
I tried using the offset_from() method on a pointer today. I like the name and API; it seemed rather intuitive. The only issue I have is that the implementations of offset_from() and wrapping_offset_from() use assert!() rather than debug_assert!(). The result is that offset_from() is a bit slower than it could be when debug = false. Is there a reason to prefer assert!()? |
@dtrebbien The assert is on the size of the type, which is a compile-time constant, so I would expect it to always get optimized out. Are you seeing otherwise? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I'd like to see this stabilized. Looks like 18 months ago most concerns were already resolved, except maybe for the I am surprised there would be a problem here, since in LLVM an allocation cannot be larger than |
…from, r=Amanieu deprecate wrapping_offset_from As per rust-lang#41079 (comment) which seems like a consensus. r? @Amanieu
…from, r=Amanieu deprecate wrapping_offset_from As per rust-lang#41079 (comment) which seems like a consensus. r? @Amanieu
…from, r=Amanieu deprecate wrapping_offset_from As per rust-lang#41079 (comment) which seems like a consensus. r? @Amanieu
…from, r=Amanieu deprecate wrapping_offset_from As per rust-lang#41079 (comment) which seems like a consensus. r? @Amanieu
I would also like to see this resolved. Since the only valid application appears to be comparing two positions within a slice, a safe API is possible, if that helps. impl<T> [T] {
fn ptr_offset(&self, p: *const T) -> Option<usize>;
/// Returns `None` if either pointer does not point to a valid position within this slice
fn ptr_sub(&self, p: *const T, q: *const T) -> Option<isize>;
} Of course, the latter is certainly not optimal. Personally I care more about making this possible (in stable Rust) than optimal. |
A safe API is very tricky at best: However, |
Stabilization PR is up: #74238 |
But it's always safe to call |
True. |
…tolnay fix const_ptr_offset_from tracking issue The old tracking issue rust-lang#41079 was for exposing those functions at all, and got closed when they were stabilized. We had nothing tracking their `const`ness so I opened a new tracking issue: rust-lang#92980.
PR: #40943
Adds an
offset_to
method to calculate the distance between two raw pointers.List o' stuff:
offset_from
and make unsafe (withwrapping_offset_from
for the safe one) Tracking issue for ptr::offset_from (feature: ptr_offset_from) #41079 (comment) -- done in Introduce unsafe offset_from on pointers #49297offset_from
abort instead of panic on ZSTs?usize
(like how isize-takingoffset
is more conveniently done with usize-takingadd
these days)The text was updated successfully, but these errors were encountered: