Skip to content

Commit b1fced7

Browse files
authored
Merge pull request #1567 from RalfJung/raw-ptr-op
operator expressions: add &raw
2 parents b1b50e4 + 60ccf42 commit b1fced7

File tree

6 files changed

+19
-21
lines changed

6 files changed

+19
-21
lines changed

src/behavior-considered-undefined.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ the pointer that was dereferenced, *not* the type of the field that is being
102102
accessed.
103103

104104
Note that a place based on a misaligned pointer only leads to undefined behavior
105-
when it is loaded from or stored to. `addr_of!`/`addr_of_mut!` on such a place
105+
when it is loaded from or stored to. `&raw const`/`&raw mut` on such a place
106106
is allowed. `&`/`&mut` on a place requires the alignment of the field type (or
107107
else the program would be "producing an invalid value"), which generally is a
108108
less restrictive requirement than being based on an aligned pointer. Taking a

src/expressions.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ A *value expression* is an expression that represents an actual value.
146146
The following contexts are *place expression* contexts:
147147

148148
* The left operand of a [compound assignment] expression.
149-
* The operand of a unary [borrow], [address-of][addr-of] or [dereference][deref] operator.
149+
* The operand of a unary [borrow], [raw borrow] or [dereference][deref] operator.
150150
* The operand of a field expression.
151151
* The indexed operand of an array indexing expression.
152152
* The operand of any [implicit borrow].
@@ -276,7 +276,6 @@ They are never allowed before:
276276

277277
[assign]: expressions/operator-expr.md#assignment-expressions
278278
[borrow]: expressions/operator-expr.md#borrow-operators
279-
[addr-of]: expressions/operator-expr.md#raw-address-of-operators
280279
[comparison]: expressions/operator-expr.md#comparison-operators
281280
[compound assignment]: expressions/operator-expr.md#compound-assignment-expressions
282281
[deref]: expressions/operator-expr.md#the-dereference-operator
@@ -294,6 +293,7 @@ They are never allowed before:
294293
[Mutable `static` items]: items/static-items.md#mutable-statics
295294
[scrutinee]: glossary.md#scrutinee
296295
[promoted]: destructors.md#constant-promotion
296+
[raw borrow]: expressions/operator-expr.md#raw-borrow-operators
297297
[slice]: types/slice.md
298298
[statement]: statements.md
299299
[static variables]: items/static-items.md

src/expressions/operator-expr.md

+12-14
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ The following things are considered to be overflow:
4141
> **<sup>Syntax</sup>**\
4242
> _BorrowExpression_ :\
4343
> &nbsp;&nbsp; &nbsp;&nbsp; (`&`|`&&`) [_Expression_]\
44-
> &nbsp;&nbsp; | (`&`|`&&`) `mut` [_Expression_]
44+
> &nbsp;&nbsp; | (`&`|`&&`) `mut` [_Expression_]\
45+
> &nbsp;&nbsp; | (`&`|`&&`) `raw` `const` [_Expression_]\
46+
> &nbsp;&nbsp; | (`&`|`&&`) `raw` `mut` [_Expression_]
4547
4648
The `&` (shared borrow) and `&mut` (mutable borrow) operators are unary prefix operators.
4749
When applied to a [place expression], this expressions produces a reference (pointer) to the location that the value refers to.
@@ -79,20 +81,18 @@ let a = && && mut 10;
7981
let a = & & & & mut 10;
8082
```
8183

82-
### Raw address-of operators
84+
### Raw borrow operators
8385

84-
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].
85-
The expression `expr` is evaluated in place expression context.
86-
`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`.
86+
`&raw const` and `&raw mut` are the *raw borrow operators*.
87+
The operand expression of these operators is evaluated in place expression context.
88+
`&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`.
8789

88-
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.
89-
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.
90+
The raw borrow 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.
91+
In those situations, using a borrow operator would cause [undefined behavior] by creating an invalid reference, but a raw pointer may still be constructed.
9092

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

9395
```rust
94-
use std::ptr;
95-
9696
#[repr(packed)]
9797
struct Packed {
9898
f1: u8,
@@ -101,14 +101,14 @@ struct Packed {
101101

102102
let packed = Packed { f1: 1, f2: 2 };
103103
// `&packed.f2` would create an unaligned reference, and thus be undefined behavior!
104-
let raw_f2 = ptr::addr_of!(packed.f2);
104+
let raw_f2 = &raw const packed.f2;
105105
assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
106106
```
107107

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

110110
```rust
111-
use std::{ptr, mem::MaybeUninit};
111+
use std::mem::MaybeUninit;
112112

113113
struct Demo {
114114
field: bool,
@@ -117,7 +117,7 @@ struct Demo {
117117
let mut uninit = MaybeUninit::<Demo>::uninit();
118118
// `&uninit.as_mut().field` would create a reference to an uninitialized `bool`,
119119
// and thus be undefined behavior!
120-
let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) };
120+
let f1_ptr = unsafe { &raw mut (*uninit.as_mut_ptr()).field };
121121
unsafe { f1_ptr.write(true); }
122122
let init = unsafe { uninit.assume_init() };
123123
```
@@ -674,8 +674,6 @@ See [this test] for an example of using this dependency.
674674
[Function pointer]: ../types/function-pointer.md
675675
[Function item]: ../types/function-item.md
676676
[undefined behavior]: ../behavior-considered-undefined.md
677-
[addr_of]: std::ptr::addr_of
678-
[addr_of_mut]: std::ptr::addr_of_mut
679677

680678
[_BorrowExpression_]: #borrow-operators
681679
[_DereferenceExpression_]: #the-dereference-operator

src/items/static-items.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ unsafe fn bump_levels_unsafe() -> u32 {
117117
// must still guard against concurrent access.
118118
fn bump_levels_safe() -> u32 {
119119
unsafe {
120-
return atomic_add(std::ptr::addr_of_mut!(LEVELS), 1);
120+
return atomic_add(&raw mut LEVELS, 1);
121121
}
122122
}
123123
```

src/type-layout.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -575,9 +575,9 @@ was wrapped in a newtype `struct` with the same `align` modifier.
575575
> println!("{}", {e.f2});
576576
> // Or if you need a pointer, use the unaligned methods for reading and writing
577577
> // instead of dereferencing the pointer directly.
578-
> let ptr: *const u16 = std::ptr::addr_of!(e.f2);
578+
> let ptr: *const u16 = &raw const e.f2;
579579
> let value = unsafe { ptr.read_unaligned() };
580-
> let mut_ptr: *mut u16 = std::ptr::addr_of_mut!(e.f2);
580+
> let mut_ptr: *mut u16 = &raw mut e.f2;
581581
> unsafe { mut_ptr.write_unaligned(3) }
582582
> ```
583583

src/types/pointer.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ they exist to support interoperability with foreign code, and writing performanc
4444
When comparing raw pointers they are compared by their address, rather than by what they point to.
4545
When comparing raw pointers to [dynamically sized types] they also have their additional data compared.
4646

47-
Raw pointers can be created directly using [`core::ptr::addr_of!`] for `*const` pointers and [`core::ptr::addr_of_mut!`] for `*mut` pointers.
47+
Raw pointers can be created directly using `&raw const` for `*const` pointers and `&raw mut` for `*mut` pointers.
4848

4949
## Smart Pointers
5050

0 commit comments

Comments
 (0)