Skip to content

Commit

Permalink
operator expressions: add &raw
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Aug 10, 2024
1 parent 7226782 commit 631b808
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,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], [address-of][addr-of] or [dereference][deref] operator.
* The operand of a unary [borrow], [raw pointer][raw-ptr-to] 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 @@ -276,7 +276,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
[raw-ptr-to]: expressions/operator-expr.md#raw-pointer-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
22 changes: 11 additions & 11 deletions src/expressions/operator-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ The following things are considered to be overflow:
> **<sup>Syntax</sup>**\
> _BorrowExpression_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; (`&`|`&&`) [_Expression_]\
> &nbsp;&nbsp; | (`&`|`&&`) `mut` [_Expression_]
> &nbsp;&nbsp; | (`&`|`&&`) `mut` [_Expression_]\
> &nbsp;&nbsp; | (`&`|`&&`) `raw` `const [_Expression_]\
> &nbsp;&nbsp; | (`&`|`&&`) `raw` `mut` [_Expression_]
The `&` (shared borrow) and `&mut` (mutable borrow) operators are unary prefix operators.
When applied to a [place expression], this expressions produces a reference (pointer) to the location that the value refers to.
Expand Down Expand Up @@ -79,20 +81,18 @@ let a = && && mut 10;
let a = & & & & mut 10;
```

### Raw address-of operators
### Raw pointer 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].
Related to the borrow operators are the *raw pointer operators*, `&raw const` and `&raw 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`.
`&raw const expr` then creates a const raw pointer of type `*const T` to the given place, and `&raw 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 raw pointer 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.

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,
Expand All @@ -101,14 +101,14 @@ struct Packed {

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);
let raw_f2 = &raw const 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};
use std::mem::MaybeUninit;

struct Demo {
field: bool,
Expand All @@ -117,7 +117,7 @@ struct Demo {
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) };
let f1_ptr = unsafe { &raw mut (*uninit.as_mut_ptr()).field };
unsafe { f1_ptr.write(true); }
let init = unsafe { uninit.assume_init() };
```
Expand Down

0 comments on commit 631b808

Please sign in to comment.