|
| 1 | +# The `unsafe` keyword |
| 2 | + |
| 3 | +The `unsafe` keyword can occur in several different contexts: |
| 4 | +unsafe functions (`unsafe fn`), unsafe blocks (`unsafe {}`), unsafe traits (`unsafe trait`), and unsafe trait implementations (`unsafe impl`). |
| 5 | +It plays several different roles, depending on where it is used and whether the `unsafe_op_in_unsafe_fn` lint is enabled: |
| 6 | +- it is used to mark code that *defines* extra safety conditions (`unsafe fn`, `unsafe trait`) |
| 7 | +- it is used to mark code that needs to *satisfy* extra safety conditions (`unsafe {}`, `unsafe impl`, `unsafe fn` without [`unsafe_op_in_unsafe_fn`]) |
| 8 | + |
| 9 | +The following discusses each of these cases. |
| 10 | +See the [keyword documentation][keyword] for some illustrative examples. |
| 11 | + |
| 12 | +## Unsafe functions (`unsafe fn`) |
| 13 | + |
| 14 | +Unsafe functions are functions that are not safe in all contexts and/or for all possible inputs. |
| 15 | +We say they have *extra safety conditions*, which are requirements that must be upheld by all callers and that the compiler does not check. |
| 16 | +For example, [`get_unchecked`] has the extra safety condition that the index must be in-bounds. |
| 17 | +The unsafe function should come with documentation explaining what those extra safety conditions are. |
| 18 | + |
| 19 | +Such a function must be prefixed with the keyword `unsafe` and can only be called from inside an `unsafe` block, or inside `unsafe fn` without the [`unsafe_op_in_unsafe_fn`] lint. |
| 20 | + |
| 21 | +## Unsafe blocks (`unsafe {}`) |
| 22 | + |
| 23 | +A block of code can be prefixed with the `unsafe` keyword, to permit calling `unsafe` functions or dereferencing raw pointers. |
| 24 | +By default, the body of an unsafe function is also considered to be an unsafe block; |
| 25 | +this can be changed by enabling the [`unsafe_op_in_unsafe_fn`] lint. |
| 26 | + |
| 27 | +By putting operations into an unsafe block, the programmer states that they have taken care of satisfying the extra safety conditions of all operations inside that block. |
| 28 | + |
| 29 | +Unsafe blocks are the logical dual to unsafe functions: |
| 30 | +where unsafe functions define a proof obligation that callers must uphold, unsafe blocks state that all relevant proof obligations have been discharged. |
| 31 | +There are many ways to discharge proof obligations; |
| 32 | +for example, there could be run-time checks or data structure invariants that guarantee that certain properties are definitely true, or the unsafe block could be inside an `unsafe fn` and use its own proof obligations to discharge the proof obligations of its callees. |
| 33 | + |
| 34 | +Unsafe blocks are used to wrap foreign libraries, make direct use of hardware or implement features not directly present in the language. |
| 35 | +For example, Rust provides the language features necessary to implement memory-safe concurrency in the language but the implementation of threads and message passing in the standard library uses unsafe blocks. |
| 36 | + |
| 37 | +Rust's type system is a conservative approximation of the dynamic safety requirements, so in some cases there is a performance cost to using safe code. |
| 38 | +For example, a doubly-linked list is not a tree structure and can only be represented with reference-counted pointers in safe code. |
| 39 | +By using `unsafe` blocks to represent the reverse links as raw pointers, it can be implemented without reference counting. |
| 40 | +(See ["Learn Rust With Entirely Too Many Linked Lists"](https://rust-unofficial.github.io/too-many-lists/) for a more in-depth exploration of this particular example.) |
| 41 | + |
| 42 | +## Unsafe traits (`unsafe trait`) |
| 43 | + |
| 44 | +An unsafe trait is a trait that comes with extra safety conditions that must be upheld by *implementations* of the trait. |
| 45 | +The unsafe trait should come with documentation explaining what those extra safety conditions are. |
| 46 | + |
| 47 | +Such a trait must be prefixed with the keyword `unsafe` and can only be implemented by `unsafe impl` blocks. |
| 48 | + |
| 49 | +## Unsafe trait implementations (`unsafe impl`) |
| 50 | + |
| 51 | +When implementing an unsafe trait, the implementation needs to be prefixed with the `unsafe` keyword. |
| 52 | +By writing `unsafe impl`, the programmer states that they have taken care of satisfying the extra safety conditions required by the trait. |
| 53 | + |
| 54 | +Unsafe trait implementations are the logical dual to unsafe traits: where unsafe traits define a proof obligation that implementations must uphold, unsafe implementations state that all relevant proof obligations have been discharged. |
| 55 | + |
| 56 | +[keyword]: ../std/keyword.unsafe.html |
| 57 | +[`get_unchecked`]: ../std/primitive.slice.html#method.get_unchecked |
| 58 | +[`unsafe_op_in_unsafe_fn`]: ../rustc/lints/listing/allowed-by-default.html#unsafe-op-in-unsafe-fn |
0 commit comments