]> git.proxmox.com Git - rustc.git/blame - src/doc/nomicon/src/safe-unsafe-meaning.md
New upstream version 1.49.0~beta.4+dfsg1
[rustc.git] / src / doc / nomicon / src / safe-unsafe-meaning.md
CommitLineData
8bb4bdeb 1# How Safe and Unsafe Interact
c1a9b12d 2
3157f602
XL
3What's the relationship between Safe Rust and Unsafe Rust? How do they
4interact?
5
6The separation between Safe Rust and Unsafe Rust is controlled with the
7`unsafe` keyword, which acts as an interface from one to the other. This is
8why we can say Safe Rust is a safe language: all the unsafe parts are kept
3b2f2976
XL
9exclusively behind the `unsafe` boundary. If you wish, you can even toss
10`#![forbid(unsafe_code)]` into your code base to statically guarantee that
11you're only writing Safe Rust.
3157f602
XL
12
13The `unsafe` keyword has two uses: to declare the existence of contracts the
3b2f2976
XL
14compiler can't check, and to declare that a programmer has checked that these
15contracts have been upheld.
3157f602
XL
16
17You can use `unsafe` to indicate the existence of unchecked contracts on
3b2f2976 18_functions_ and _trait declarations_. On functions, `unsafe` means that
3157f602
XL
19users of the function must check that function's documentation to ensure
20they are using it in a way that maintains the contracts the function
21requires. On trait declarations, `unsafe` means that implementors of the
22trait must check the trait documentation to ensure their implementation
23maintains the contracts the trait requires.
24
3b2f2976
XL
25You can use `unsafe` on a block to declare that all unsafe actions performed
26within are verified to uphold the contracts of those operations. For instance,
29967ef6 27the index passed to [`slice::get_unchecked`][get_unchecked] is in-bounds.
3b2f2976
XL
28
29You can use `unsafe` on a trait implementation to declare that the implementation
29967ef6 30upholds the trait's contract. For instance, that a type implementing [`Send`] is
3b2f2976 31really safe to move to another thread.
3157f602 32
3157f602
XL
33The standard library has a number of unsafe functions, including:
34
29967ef6
XL
35* [`slice::get_unchecked`][get_unchecked], which performs unchecked indexing,
36 allowing memory safety to be freely violated.
37* [`mem::transmute`][transmute] reinterprets some value as having a given type,
38 bypassing type safety in arbitrary ways (see [conversions] for details).
39* Every raw pointer to a sized type has an [`offset`][ptr_offset] method that
3b2f2976 40 invokes Undefined Behavior if the passed offset is not ["in bounds"][ptr_offset].
ff7c6d11
XL
41* All FFI (Foreign Function Interface) functions are `unsafe` to call because the
42 other language can do arbitrary operations that the Rust compiler can't check.
c1a9b12d 43
13cf67c4
XL
44As of Rust 1.29.2 the standard library defines the following unsafe traits
45(there are others, but they are not stabilized yet and some of them may never
46be):
c1a9b12d 47
13cf67c4
XL
48* [`Send`] is a marker trait (a trait with no API) that promises implementors
49 are safe to send (move) to another thread.
50* [`Sync`] is a marker trait that promises threads can safely share implementors
3157f602 51 through a shared reference.
13cf67c4 52* [`GlobalAlloc`] allows customizing the memory allocator of the whole program.
3157f602 53
3b2f2976
XL
54Much of the Rust standard library also uses Unsafe Rust internally. These
55implementations have generally been rigorously manually checked, so the Safe Rust
56interfaces built on top of these implementations can be assumed to be safe.
3157f602
XL
57
58The need for all of this separation boils down a single fundamental property
74b04a01 59of Safe Rust, the *soundness property*:
3157f602
XL
60
61**No matter what, Safe Rust can't cause Undefined Behavior.**
62
3b2f2976
XL
63The design of the safe/unsafe split means that there is an asymmetric trust
64relationship between Safe and Unsafe Rust. Safe Rust inherently has to
65trust that any Unsafe Rust it touches has been written correctly.
66On the other hand, Unsafe Rust has to be very careful about trusting Safe Rust.
3157f602 67
29967ef6 68As an example, Rust has the [`PartialOrd`] and [`Ord`] traits to differentiate
3b2f2976
XL
69between types which can "just" be compared, and those that provide a "total"
70ordering (which basically means that comparison behaves reasonably).
71
29967ef6 72[`BTreeMap`] doesn't really make sense for partially-ordered types, and so it
3b2f2976
XL
73requires that its keys implement `Ord`. However, `BTreeMap` has Unsafe Rust code
74inside of its implementation. Because it would be unacceptable for a sloppy `Ord`
75implementation (which is Safe to write) to cause Undefined Behavior, the Unsafe
76code in BTreeMap must be written to be robust against `Ord` implementations which
77aren't actually total — even though that's the whole point of requiring `Ord`.
78
79The Unsafe Rust code just can't trust the Safe Rust code to be written correctly.
80That said, `BTreeMap` will still behave completely erratically if you feed in
81values that don't have a total ordering. It just won't ever cause Undefined
82Behavior.
83
84One may wonder, if `BTreeMap` cannot trust `Ord` because it's Safe, why can it
85trust *any* Safe code? For instance `BTreeMap` relies on integers and slices to
86be implemented correctly. Those are safe too, right?
87
88The difference is one of scope. When `BTreeMap` relies on integers and slices,
89it's relying on one very specific implementation. This is a measured risk that
90can be weighed against the benefit. In this case there's basically zero risk;
91if integers and slices are broken, *everyone* is broken. Also, they're maintained
92by the same people who maintain `BTreeMap`, so it's easy to keep tabs on them.
93
94On the other hand, `BTreeMap`'s key type is generic. Trusting its `Ord` implementation
95means trusting every `Ord` implementation in the past, present, and future.
96Here the risk is high: someone somewhere is going to make a mistake and mess up
97their `Ord` implementation, or even just straight up lie about providing a total
98ordering because "it seems to work". When that happens, `BTreeMap` needs to be
99prepared.
100
101The same logic applies to trusting a closure that's passed to you to behave
102correctly.
103
104This problem of unbounded generic trust is the problem that `unsafe` traits
105exist to resolve. The `BTreeMap` type could theoretically require that keys
106implement a new trait called `UnsafeOrd`, rather than `Ord`, that might look
107like this:
c1a9b12d
SL
108
109```rust
3157f602
XL
110use std::cmp::Ordering;
111
112unsafe trait UnsafeOrd {
113 fn cmp(&self, other: &Self) -> Ordering;
c1a9b12d
SL
114}
115```
116
3157f602
XL
117Then, a type would use `unsafe` to implement `UnsafeOrd`, indicating that
118they've ensured their implementation maintains whatever contracts the
119trait expects. In this situation, the Unsafe Rust in the internals of
3b2f2976
XL
120`BTreeMap` would be justified in trusting that the key type's `UnsafeOrd`
121implementation is correct. If it isn't, it's the fault of the unsafe trait
122implementation, which is consistent with Rust's safety guarantees.
3157f602
XL
123
124The decision of whether to mark a trait `unsafe` is an API design choice.
3b2f2976
XL
125Rust has traditionally avoided doing this because it makes Unsafe
126Rust pervasive, which isn't desirable. `Send` and `Sync` are marked unsafe
3157f602 127because thread safety is a *fundamental property* that unsafe code can't
13cf67c4
XL
128possibly hope to defend against in the way it could defend against a buggy
129`Ord` implementation. Similarly, `GlobalAllocator` is keeping accounts of all
130the memory in the program and other things like `Box` or `Vec` build on top of
131it. If it does something weird (giving the same chunk of memory to another
132request when it is still in use), there's no chance to detect that and do
133anything about it.
134
135The decision of whether to mark your own traits `unsafe` depends on the same
136sort of consideration. If `unsafe` code can't reasonably expect to defend
137against a broken implementation of the trait, then marking the trait `unsafe` is
138a reasonable choice.
3157f602 139
3b2f2976 140As an aside, while `Send` and `Sync` are `unsafe` traits, they are *also*
3157f602
XL
141automatically implemented for types when such derivations are provably safe
142to do. `Send` is automatically derived for all types composed only of values
143whose types also implement `Send`. `Sync` is automatically derived for all
3b2f2976 144types composed only of values whose types also implement `Sync`. This minimizes
13cf67c4
XL
145the pervasive unsafety of making these two traits `unsafe`. And not many people
146are going to *implement* memory allocators (or use them directly, for that
147matter).
3157f602 148
3b2f2976
XL
149This is the balance between Safe and Unsafe Rust. The separation is designed to
150make using Safe Rust as ergonomic as possible, but requires extra effort and
151care when writing Unsafe Rust. The rest of this book is largely a discussion
152of the sort of care that must be taken, and what contracts Unsafe Rust must uphold.
c1a9b12d 153
13cf67c4
XL
154[`Send`]: ../std/marker/trait.Send.html
155[`Sync`]: ../std/marker/trait.Sync.html
156[`GlobalAlloc`]: ../std/alloc/trait.GlobalAlloc.html
c1a9b12d 157[conversions]: conversions.html
3b2f2976 158[ptr_offset]: ../std/primitive.pointer.html#method.offset
29967ef6
XL
159[get_unchecked]: ../std/primitive.slice.html#method.get_unchecked
160[transmute]: ../std/mem/fn.transmute.html
161[`PartialOrd`]: ../std/cmp/trait.PartialOrd.html
162[`Ord`]: ../std/cmp/trait.Ord.html
163[`BTreeMap`]: ../std/collections/struct.BTreeMap.html