|
1 | 1 | # The `unsafe` keyword
|
2 | 2 |
|
3 |
| -## Unsafe functions |
| 3 | +The `unsafe` keyword in Rust can occur in several different context: unsafe |
| 4 | +functions (`unsafe fn`), unsafe blocks (`unsafe {}`), unsafe traits (`unsafe |
| 5 | +trait`), and unsafe trait implementations (`unsafe impl`). It plays several |
| 6 | +different roles, depending on where it is used and whether the |
| 7 | +`unsafe_op_in_unsafe_fn` lint is enabled: |
| 8 | +- it is used to mark code that *defines* extra safety conditions (`unsafe fn`, |
| 9 | + `unsafe trait`) |
| 10 | +- it is used to mark code that needs to *satisfy* extra safety conditions |
| 11 | + (`unsafe {}`, `unsafe impl`, `unsafe fn` without `unsafe_op_in_unsafe_fn`) |
| 12 | + |
| 13 | +The following discusses each of these cases. See the |
| 14 | +[keyword documentation][keyword] for some illustrative examples. |
| 15 | + |
| 16 | +[keyword]: ../../std/keyword.unsafe.html |
| 17 | + |
| 18 | +## Unsafe functions (`unsafe fn`) |
4 | 19 |
|
5 | 20 | Unsafe functions are functions that are not safe in all contexts and/or for all
|
6 |
| -possible inputs. Such a function must be prefixed with the keyword `unsafe` and |
7 |
| -can only be called from an `unsafe` block or another `unsafe` function. |
| 21 | +possible inputs. We say they have *extra safety conditions*, which are |
| 22 | +requirements that must be upheld by all callers and that the compiler does not |
| 23 | +check. For example, `get_unchecked` has the extra safety |
| 24 | +condition that the index must be in-bounds. The module defining an unsafe |
| 25 | +function is responsible for documenting what those extra safety conditions are. |
8 | 26 |
|
9 |
| -## Unsafe blocks |
| 27 | +Such a function must be prefixed with the keyword `unsafe` and can only be |
| 28 | +called from inside an `unsafe` block. |
| 29 | + |
| 30 | +## Unsafe blocks (`unsafe {}`) |
10 | 31 |
|
11 | 32 | A block of code can be prefixed with the `unsafe` keyword, to permit calling
|
12 |
| -`unsafe` functions or dereferencing raw pointers within a safe function. |
| 33 | +`unsafe` functions or dereferencing raw pointers. By default, the body of an |
| 34 | +unsafe function is also considered to be an unsafe block; this can be changed by |
| 35 | +enabling the `unsafe_op_in_unsafe_fn` lint. |
| 36 | + |
| 37 | +By putting operations into an unsafe block, the programmer states that they have |
| 38 | +taken care of satisfying the extra safety conditions of all operations inside |
| 39 | +that block. |
13 | 40 |
|
14 |
| -When a programmer has sufficient conviction that a sequence of potentially |
15 |
| -unsafe operations is actually safe, they can encapsulate that sequence (taken |
16 |
| -as a whole) within an `unsafe` block. The compiler will consider uses of such |
17 |
| -code safe, in the surrounding context. |
| 41 | +Unsafe blocks are the logical dual to unsafe functions: where unsafe functions |
| 42 | +define a proof obligation that callers must uphold, unsafe blocks state that all |
| 43 | +relevant proof obligations have been discharged. There are many ways to |
| 44 | +discharge proof obligations; for example, there could be run-time checks or data |
| 45 | +structure invariants that guarantee that certain properties are definitely true, |
| 46 | +or the unsafe block could be inside an `unsafe fn` and use its own proof |
| 47 | +obligations to discharge the proof obligations of its callees. |
18 | 48 |
|
19 | 49 | Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
|
20 | 50 | or implement features not directly present in the language. For example, Rust
|
21 | 51 | provides the language features necessary to implement memory-safe concurrency
|
22 |
| -in the language but the implementation of threads and message passing is in the |
23 |
| -standard library. |
| 52 | +in the language but the implementation of threads and message passing in the |
| 53 | +standard library uses unsafe blocks. |
24 | 54 |
|
25 | 55 | Rust's type system is a conservative approximation of the dynamic safety
|
26 | 56 | requirements, so in some cases there is a performance cost to using safe code.
|
27 | 57 | For example, a doubly-linked list is not a tree structure and can only be
|
28 | 58 | represented with reference-counted pointers in safe code. By using `unsafe`
|
29 | 59 | blocks to represent the reverse links as raw pointers, it can be implemented
|
30 | 60 | with only boxes.
|
| 61 | + |
| 62 | +## Unsafe traits (`unsafe trait`) |
| 63 | + |
| 64 | +An unsafe trait is a trait that comes with extra safety conditions that must be |
| 65 | +upheld by *implementations* of the trait. The module defining an unsafe trait is |
| 66 | +responsible for documenting what those extra safety conditions are. |
| 67 | + |
| 68 | +Such a trait must be prefixed with the keyword `unsafe` and can only be |
| 69 | +implemented by `unsafe impl` blocks. |
| 70 | + |
| 71 | +## Unsafe trait implementations (`unsafe impl`) |
| 72 | + |
| 73 | +When implementing an unsafe trait, the implementation needs to be prefixed with |
| 74 | +the `unsafe` keyword. By writing `unsafe impl`, the programmer states that they |
| 75 | +have taken care of satisfying the extra safety conditions required by the trait. |
| 76 | + |
| 77 | +Unsafe traits are the logical dual to unsafe traits: where unsafe traits define |
| 78 | +a proof obligation that implementations must uphold, unsafe implementations |
| 79 | +state that all relevant proof obligations have been discharged. |
0 commit comments