Skip to content

document raw-addr-of operators #1001

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

Merged
merged 5 commits into from
Jul 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ A *value expression* is an expression that represents an actual value.
The following contexts are *place expression* contexts:

* The left operand of a [compound assignment] expression.
* The operand of a unary [borrow] or [dereference][deref] operator.
* The operand of a unary [borrow], [address-of][addr-of] or [dereference][deref] operator.
* The operand of a field expression.
* The indexed operand of an array indexing expression.
* The operand of any [implicit borrow].
Expand Down Expand Up @@ -308,6 +308,7 @@ They are never allowed before:

[assign]: expressions/operator-expr.md#assignment-expressions
[borrow]: expressions/operator-expr.md#borrow-operators
[addr-of]: expressions/operator-expr.md#raw-address-of-operators
[comparison]: expressions/operator-expr.md#comparison-operators
[compound assignment]: expressions/operator-expr.md#compound-assignment-expressions
[deref]: expressions/operator-expr.md#the-dereference-operator
Expand Down
47 changes: 47 additions & 0 deletions src/expressions/operator-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,50 @@ let a = && && mut 10;
let a = & & & & mut 10;
```

### Raw address-of operators

Related to the borrow operators are the *raw address-of operators*, which do not have first-class syntax, but are exposed via the macros [`ptr::addr_of!(expr)`][addr_of] and [`ptr::addr_of_mut!(expr)`][addr_of_mut].
The expression `expr` is evaluated in place expression context.
`ptr::addr_of!(expr)` then creates a const raw pointer of type `*const T` to the given place, and `ptr::addr_of_mut!(expr)` creates a mutable raw pointer of type `*mut T`.

The raw address-of operators must be used instead of a borrow operator whenever the place expression could evaluate to a place that is not properly aligned or does not store a valid value as determined by its type, or whenever creating a reference would introduce incorrect aliasing assumptions.
In those situations, using a borrow operator would cause [undefined behavior] by creating an invalid reference, but a raw pointer may still be constructed using an address-of operator.

The following is an example of creating a raw pointer to an unaligned place through a `packed` struct:

```rust
use std::ptr;

#[repr(packed)]
struct Packed {
f1: u8,
f2: u16,
}

let packed = Packed { f1: 1, f2: 2 };
// `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
let raw_f2 = ptr::addr_of!(packed.f2);
assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
```

The following is an example of creating a raw pointer to a place that does not contain a valid value:

```rust
use std::{ptr, mem::MaybeUninit};

struct Demo {
field: bool,
}

let mut uninit = MaybeUninit::<Demo>::uninit();
// `&uninit.as_mut().field` would create a reference to an uninitialized `bool`,
// and thus be Undefined Behavior!
let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) };
unsafe { f1_ptr.write(true); }
let init = unsafe { uninit.assume_init() };
```


## The dereference operator

> **<sup>Syntax</sup>**\
Expand Down Expand Up @@ -595,6 +639,9 @@ See [this test] for an example of using this dependency.
[float-float]: https://github.com/rust-lang/rust/issues/15536
[Function pointer]: ../types/function-pointer.md
[Function item]: ../types/function-item.md
[undefined behavior]: ../behavior-considered-undefined.md
[addr_of]: ../../std/ptr/macro.addr_of.html
[addr_of_mut]: ../../std/ptr/macro.addr_of_mut.html

[_BorrowExpression_]: #borrow-operators
[_DereferenceExpression_]: #the-dereference-operator
Expand Down