Skip to content

Commit 1150fb0

Browse files
committed
TRPL: unsafe -> raw pointers
Many unsafe features are now in the unstable section, so this section is really just about raw pointers now. That also makes sense for its place in the TOC. This addresses part of #12905.
1 parent 5910dc0 commit 1150fb0

File tree

3 files changed

+124
-101
lines changed

3 files changed

+124
-101
lines changed

src/doc/trpl/SUMMARY.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
* [Associated Types](associated-types.md)
5555
* [Unsized Types](unsized-types.md)
5656
* [Macros](macros.md)
57-
* [`unsafe` Code](unsafe-code.md)
57+
* [Raw Pointers](raw-pointers.md)
5858
* [Nightly Rust](nightly-rust.md)
5959
* [Compiler Plugins](compiler-plugins.md)
6060
* [Inline Assembly](inline-assembly.md)

src/doc/trpl/raw-pointers.md

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
% Raw Pointers
2+
3+
Rust has a number of different smart pointer types in its standard library, but
4+
there are two types that are extra-special. Much of Rust’s safety comes from
5+
compile-time checks, but raw pointers don’t have such guarantees, and are
6+
[unsafe][unsafe] to use.
7+
8+
`*const T` and `*mut T` are called ‘raw pointers’ in Rust. Sometimes, when
9+
writing certain kinds of libraries, you’ll need to get around Rust’s safety
10+
guarantees for some reason. In this case, you can use raw pointers to implement
11+
your library, while exposing a safe interface for your users. For example, `*`
12+
pointers are allowed to alias, allowing them to be used to write
13+
shared-ownership types, and even thread-safe shared memory types (the `Rc<T>`
14+
and `Arc<T>` types are both implemented entirely in Rust).
15+
16+
Here are some things to remember about raw pointers that are different than
17+
other pointer types. They:
18+
19+
- are not guaranteed to point to valid memory and are not even
20+
guaranteed to be non-null (unlike both `Box` and `&`);
21+
- do not have any automatic clean-up, unlike `Box`, and so require
22+
manual resource management;
23+
- are plain-old-data, that is, they don't move ownership, again unlike
24+
`Box`, hence the Rust compiler cannot protect against bugs like
25+
use-after-free;
26+
- lack any form of lifetimes, unlike `&`, and so the compiler cannot
27+
reason about dangling pointers; and
28+
- have no guarantees about aliasing or mutability other than mutation
29+
not being allowed directly through a `*const T`.
30+
31+
# Basics
32+
33+
Creating a raw pointer is perfectly safe:
34+
35+
```rust
36+
let x = 5;
37+
let raw = &x as *const i32;
38+
39+
let mut y = 10;
40+
let raw_mut = &mut y as *mut i32;
41+
```
42+
43+
However, dereferencing one is not. This won’t work:
44+
45+
```rust,ignore
46+
let x = 5;
47+
let raw = &x as *const i32;
48+
49+
println!("raw points at {}", *raw);
50+
```
51+
52+
It gives this error:
53+
54+
```text
55+
error: dereference of unsafe pointer requires unsafe function or block [E0133]
56+
println!("raw points at{}", *raw);
57+
^~~~
58+
```
59+
60+
When you dereference a raw pointer, you’re taking responsibility that it’s not
61+
pointing somewhere that would be incorrect. As such, you need `unsafe`:
62+
63+
```rust
64+
let x = 5;
65+
let raw = &x as *const i32;
66+
67+
let points_at = unsafe { *raw };
68+
69+
println!("raw points at {}", points_at);
70+
```
71+
72+
For more operations on raw pointers, see [their API documentation][rawapi].
73+
74+
[unsafe]: unsafe.html
75+
[rawapi]: ../std/primitive.pointer.html
76+
77+
# FFI
78+
79+
Raw pointers are useful for FFI: Rust’s `*const T` and `*mut T` are similar to
80+
C’s `const T*` and `T*`, respectfully. For more about this use, consult the
81+
[FFI chapter][ffi].
82+
83+
[ffi]: ffi.md
84+
85+
# References and raw pointers
86+
87+
At runtime, a raw pointer `*` and a reference pointing to the same piece of
88+
data have an identical representation. In fact, an `&T` reference will
89+
implicitly coerce to an `*const T` raw pointer in safe code and similarly for
90+
the `mut` variants (both coercions can be performed explicitly with,
91+
respectively, `value as *const T` and `value as *mut T`).
92+
93+
Going the opposite direction, from `*const` to a reference `&`, is not safe. A
94+
`&T` is always valid, and so, at a minimum, the raw pointer `*const T` has to
95+
point to a valid instance of type `T`. Furthermore, the resulting pointer must
96+
satisfy the aliasing and mutability laws of references. The compiler assumes
97+
these properties are true for any references, no matter how they are created,
98+
and so any conversion from raw pointers is asserting that they hold. The
99+
programmer *must* guarantee this.
100+
101+
The recommended method for the conversion is
102+
103+
```rust
104+
let i: u32 = 1;
105+
106+
// explicit cast
107+
let p_imm: *const u32 = &i as *const u32;
108+
let mut m: u32 = 2;
109+
110+
// implicit coercion
111+
let p_mut: *mut u32 = &mut m;
112+
113+
unsafe {
114+
let ref_imm: &u32 = &*p_imm;
115+
let ref_mut: &mut u32 = &mut *p_mut;
116+
}
117+
```
118+
119+
The `&*x` dereferencing style is preferred to using a `transmute`. The latter
120+
is far more powerful than necessary, and the more restricted operation is
121+
harder to use incorrectly; for example, it requires that `x` is a pointer
122+
(unlike `transmute`).

src/doc/trpl/unsafe-code.md

+1-100
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,4 @@
1-
% Unsafe Code
2-
3-
# Introduction
4-
5-
Rust aims to provide safe abstractions over the low-level details of
6-
the CPU and operating system, but sometimes one needs to drop down and
7-
write code at that level. This guide aims to provide an overview of
8-
the dangers and power one gets with Rust's unsafe subset.
9-
10-
Rust provides an escape hatch in the form of the `unsafe { ... }`
11-
block which allows the programmer to dodge some of the compiler's
12-
checks and do a wide range of operations, such as:
13-
14-
- dereferencing [raw pointers](#raw-pointers)
15-
- calling a function via FFI ([covered by the FFI guide](ffi.html))
16-
- casting between types bitwise (`transmute`, aka "reinterpret cast")
17-
- [inline assembly](#inline-assembly)
18-
19-
Note that an `unsafe` block does not relax the rules about lifetimes
20-
of `&` and the freezing of borrowed data.
21-
22-
Any use of `unsafe` is the programmer saying "I know more than you" to
23-
the compiler, and, as such, the programmer should be very sure that
24-
they actually do know more about why that piece of code is valid. In
25-
general, one should try to minimize the amount of unsafe code in a
26-
code base; preferably by using the bare minimum `unsafe` blocks to
27-
build safe interfaces.
28-
29-
> **Note**: the low-level details of the Rust language are still in
30-
> flux, and there is no guarantee of stability or backwards
31-
> compatibility. In particular, there may be changes that do not cause
32-
> compilation errors, but do cause semantic changes (such as invoking
33-
> undefined behaviour). As such, extreme care is required.
34-
35-
# Pointers
36-
37-
## References
38-
39-
One of Rust's biggest features is memory safety. This is achieved in
40-
part via [the ownership system](ownership.html), which is how the
41-
compiler can guarantee that every `&` reference is always valid, and,
42-
for example, never pointing to freed memory.
43-
44-
These restrictions on `&` have huge advantages. However, they also
45-
constrain how we can use them. For example, `&` doesn't behave
46-
identically to C's pointers, and so cannot be used for pointers in
47-
foreign function interfaces (FFI). Additionally, both immutable (`&`)
48-
and mutable (`&mut`) references have some aliasing and freezing
49-
guarantees, required for memory safety.
50-
51-
In particular, if you have an `&T` reference, then the `T` must not be
52-
modified through that reference or any other reference. There are some
53-
standard library types, e.g. `Cell` and `RefCell`, that provide inner
54-
mutability by replacing compile time guarantees with dynamic checks at
55-
runtime.
56-
57-
An `&mut` reference has a different constraint: when an object has an
58-
`&mut T` pointing into it, then that `&mut` reference must be the only
59-
such usable path to that object in the whole program. That is, an
60-
`&mut` cannot alias with any other references.
61-
62-
Using `unsafe` code to incorrectly circumvent and violate these
63-
restrictions is undefined behaviour. For example, the following
64-
creates two aliasing `&mut` pointers, and is invalid.
65-
66-
```
67-
use std::mem;
68-
let mut x: u8 = 1;
69-
70-
let ref_1: &mut u8 = &mut x;
71-
let ref_2: &mut u8 = unsafe { mem::transmute(&mut *ref_1) };
72-
73-
// oops, ref_1 and ref_2 point to the same piece of data (x) and are
74-
// both usable
75-
*ref_1 = 10;
76-
*ref_2 = 20;
77-
```
78-
79-
## Raw pointers
1+
% Raw Pointers
802

813
Rust offers two additional pointer types (*raw pointers*), written as
824
`*const T` and `*mut T`. They're an approximation of C's `const T*` and `T*`
@@ -160,24 +82,3 @@ The `&*x` dereferencing style is preferred to using a `transmute`.
16082
The latter is far more powerful than necessary, and the more
16183
restricted operation is harder to use incorrectly; for example, it
16284
requires that `x` is a pointer (unlike `transmute`).
163-
164-
165-
166-
## Making the unsafe safe(r)
167-
168-
There are various ways to expose a safe interface around some unsafe
169-
code:
170-
171-
- store pointers privately (i.e. not in public fields of public
172-
structs), so that you can see and control all reads and writes to
173-
the pointer in one place.
174-
- use `assert!()` a lot: since you can't rely on the protection of the
175-
compiler & type-system to ensure that your `unsafe` code is correct
176-
at compile-time, use `assert!()` to verify that it is doing the
177-
right thing at run-time.
178-
- implement the `Drop` for resource clean-up via a destructor, and use
179-
RAII (Resource Acquisition Is Initialization). This reduces the need
180-
for any manual memory management by users, and automatically ensures
181-
that clean-up is always run, even when the thread panics.
182-
- ensure that any data stored behind a raw pointer is destroyed at the
183-
appropriate time.

0 commit comments

Comments
 (0)