| Age | Commit message (Collapse) | Author | Lines |
|
Rewrite docs for pointer methods
This takes over https://github.com/rust-lang/rust/pull/51016 by @ecstatic-morse. They did most of the work, I just did some editing.
However, I realized one problem: This updates the docs for the "free functions" in `core::ptr`, but it does not update the copies of these docs for the inherent methods of the `*const T` and `*mut T` types. These getting out-of-sync is certainly bad, but I also don't feel like copying all this stuff around. Instead, we should remove this redundancy. Any good ideas?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
duplication and inconsistency
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Also rewrites the reads/writes section to be less reliant on `*const`,
`*mut`
|
|
|
|
This splits "valid" into "valid for reads" and "valid for writes", and
also adds the concept of operation size to validity. Now functions which
operate on sequences state that e.g. pointer args must be "valid for reads of
size x".
|
|
Uses `x.offset(i)` must be valid for all `i` in `0..count`.
|
|
The enumerated list of conditions is replaced by an explanation that
rust doesn't have a formal memory model. It does say that pointers
created directly from references are guaranteed to be valid, and links
to both the "Unsafe Code" section of the book and the "Undefined
Behavior" section of the reference.
|
|
|
|
|
|
They closely mirror the docs for `copy_nonoverlapping`
|
|
|
|
|
|
This also removes the overlong link that failed tidy xD.
|
|
- Add links to the GNU libc docs for `memmove`, `memcpy`, and
`memset`, as well as internally linking to other functions in `std::ptr`
- List invariants which, when violated, cause UB for all functions
- Add example to `ptr::drop_in_place` and compares it to `ptr::read`.
- Add examples which more closely mirror real world uses for the
functions in `std::ptr`. Also, move the reimplementation of `mem::swap`
to the examples of `ptr::read` and use a more interesting example for
`copy_nonoverlapping`.
- Change module level description
- Define what constitutes a "valid" pointer.
- Centralize discussion of ownership of bitwise copies in `ptr::read` and
provide an example.
|
|
Suggest direct raw-pointer dereference
People often come looking for some kind of `as_ref_unchecked` method on
raw pointers that would give them `&T` and not `Option<&T>` when they
are sure the pointer is not NULL.
There's no such method, but taking a reference of the dereferenced
pointer accomplishes the same thing. Therefore, suggest using that, at
the `as_ref` site ‒ it's a place people are likely going to look into.
|
|
People often come looking for some kind of `as_ref_unchecked` method on
raw pointers that would give them `&T` and not `Option<&T>` when they
are sure the pointer is not NULL.
There's no such method, but taking a reference of the dereferenced
pointer accomplishes the same thing. Therefore, suggest using that, at
the `as_ref` site ‒ it's a place people are likely going to look into.
|
|
Replace usages of ptr::offset with ptr::{add,sub}.
Rust provides these helper methods – so let's use them!
|
|
|
|
|
|
Remove explicit returns where unnecessary
|
|
|
|
|
|
|
|
|
|
|
|
mem::swap the obvious way for types smaller than the SIMD optimization's block size
LLVM isn't able to remove the alloca for the unaligned block in the post-SIMD tail in some cases, so doing this helps SRoA work in cases where it currently doesn't. Found in the `replace_with` RFC discussion.
Examples of the improvements:
<details>
<summary>swapping `[u16; 3]` takes 1/3 fewer instructions and no stackalloc</summary>
```rust
type Demo = [u16; 3];
pub fn swap_demo(x: &mut Demo, y: &mut Demo) {
std::mem::swap(x, y);
}
```
nightly:
```asm
_ZN4blah9swap_demo17ha1732a9b71393a7eE:
.seh_proc _ZN4blah9swap_demo17ha1732a9b71393a7eE
sub rsp, 32
.seh_stackalloc 32
.seh_endprologue
movzx eax, word ptr [rcx + 4]
mov word ptr [rsp + 4], ax
mov eax, dword ptr [rcx]
mov dword ptr [rsp], eax
movzx eax, word ptr [rdx + 4]
mov word ptr [rcx + 4], ax
mov eax, dword ptr [rdx]
mov dword ptr [rcx], eax
movzx eax, word ptr [rsp + 4]
mov word ptr [rdx + 4], ax
mov eax, dword ptr [rsp]
mov dword ptr [rdx], eax
add rsp, 32
ret
.seh_handlerdata
.section .text,"xr",one_only,_ZN4blah9swap_demo17ha1732a9b71393a7eE
.seh_endproc
```
this PR:
```asm
_ZN4blah9swap_demo17ha1732a9b71393a7eE:
mov r8d, dword ptr [rcx]
movzx r9d, word ptr [rcx + 4]
movzx eax, word ptr [rdx + 4]
mov word ptr [rcx + 4], ax
mov eax, dword ptr [rdx]
mov dword ptr [rcx], eax
mov word ptr [rdx + 4], r9w
mov dword ptr [rdx], r8d
ret
```
</details>
<details>
<summary>`replace_with` optimizes down much better</summary>
Inspired by https://github.com/rust-lang/rfcs/pull/2490,
```rust
fn replace_with<T, F>(x: &mut Option<T>, f: F)
where F: FnOnce(Option<T>) -> Option<T>
{
*x = f(x.take());
}
pub fn inc_opt(mut x: &mut Option<i32>) {
replace_with(&mut x, |i| i.map(|j| j + 1));
}
```
Rust 1.26.0:
```asm
_ZN4blah7inc_opt17heb0acb64c51777cfE:
mov rax, qword ptr [rcx]
movabs r8, 4294967296
add r8, rax
shl rax, 32
movabs rdx, -4294967296
and rdx, r8
xor r8d, r8d
test rax, rax
cmove rdx, rax
setne r8b
or rdx, r8
mov qword ptr [rcx], rdx
ret
```
Nightly (better thanks to ScalarPair, maybe?):
```asm
_ZN4blah7inc_opt17h66df690be0b5899dE:
mov r8, qword ptr [rcx]
mov rdx, r8
shr rdx, 32
xor eax, eax
test r8d, r8d
setne al
add edx, 1
mov dword ptr [rcx], eax
mov dword ptr [rcx + 4], edx
ret
```
This PR:
```asm
_ZN4blah7inc_opt17h1426dc215ecbdb19E:
xor eax, eax
cmp dword ptr [rcx], 0
setne al
mov dword ptr [rcx], eax
add dword ptr [rcx + 4], 1
ret
```
Where that add is beautiful -- using an addressing mode to not even need to explicitly go through a register -- and the remaining imperfection is well-known (https://github.com/rust-lang/rust/pull/49420#issuecomment-376805721).
</details>
|
|
LLVM isn't able to remove the alloca for the unaligned block in the SIMD tail in some cases, so doing this helps SRoA work in cases where it currently doesn't. Found in the `replace_with` RFC discussion.
|
|
The documentation of Unique::empty() and NonNull::dangling() could
potentially suggest that they work as sentinel values indicating a
not-yet-initialized pointer. However, they both declare a non-null
pointer equal to the alignment of the type, which could potentially
reference a valid value of that type (specifically, the first such valid
value in memory). Explicitly document that the return value of these
functions does not work as a sentinel value.
|
|
Add #[repr(transparent)] to some libcore types
* `UnsafeCell`
* `Cell`
* `NonZero*`
* `NonNull`
* `Unique`
CC https://github.com/rust-lang/rust/issues/43036
|
|
|