-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Simplify manual ptr arithmetic in slice::Iter with ptr_sub #106393
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,30 +9,20 @@ macro_rules! is_empty { | |
}; | ||
} | ||
|
||
// To get rid of some bounds checks (see `position`), we compute the length in a somewhat | ||
// unexpected way. (Tested by `codegen/slice-position-bounds-check`.) | ||
macro_rules! len { | ||
($self: ident) => {{ | ||
#![allow(unused_unsafe)] // we're sometimes used within an unsafe block | ||
|
||
let start = $self.ptr; | ||
let size = size_from_ptr(start.as_ptr()); | ||
if size == 0 { | ||
// This _cannot_ use `unchecked_sub` because we depend on wrapping | ||
if T::IS_ZST { | ||
// This _cannot_ use `ptr_sub` because we depend on wrapping | ||
// to represent the length of long ZST slice iterators. | ||
$self.end.addr().wrapping_sub(start.as_ptr().addr()) | ||
} else { | ||
// We know that `start <= end`, so can do better than `offset_from`, | ||
// which needs to deal in signed. By setting appropriate flags here | ||
// we can tell LLVM this, which helps it remove bounds checks. | ||
// SAFETY: By the type invariant, `start <= end` | ||
let diff = unsafe { unchecked_sub($self.end.addr(), start.as_ptr().addr()) }; | ||
// By also telling LLVM that the pointers are apart by an exact | ||
// multiple of the type size, it can optimize `len() == 0` down to | ||
// `start == end` instead of `(end - start) < size`. | ||
// SAFETY: By the type invariant, the pointers are aligned so the | ||
// distance between them must be a multiple of pointee size | ||
unsafe { exact_div(diff, size) } | ||
// To get rid of some bounds checks (see `position`), we use ptr_sub instead of | ||
// offset_from (Tested by `codegen/slice-position-bounds-check`.) | ||
// SAFETY: by the type invariant pointers are aligned and `start <= end` | ||
unsafe { $self.end.sub_ptr(start.as_ptr()) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This safety comment is incomplete. See Zulip |
||
} | ||
}}; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is odd, where is
T
bound? Does this macro assume that there is aT
in scope wherever it is used (violating hygiene)? That at least warrants a comment.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The macro is only used in another macro (in the same file) which defines T