]> git.lizzy.rs Git - rust.git/blob - src/doc/nomicon/safe-unsafe-meaning.md
fix spacing issue in trpl/documentation doc
[rust.git] / src / doc / nomicon / safe-unsafe-meaning.md
1 % How Safe and Unsafe Interact
2
3 So what's the relationship between Safe and Unsafe Rust? How do they interact?
4
5 Rust models the separation between Safe and Unsafe Rust with the `unsafe`
6 keyword, which can be thought as a sort of *foreign function interface* (FFI)
7 between Safe and Unsafe Rust. This is the magic behind why we can say Safe Rust
8 is a safe language: all the scary unsafe bits are relegated exclusively to FFI
9 *just like every other safe language*.
10
11 However because one language is a subset of the other, the two can be cleanly
12 intermixed as long as the boundary between Safe and Unsafe Rust is denoted with
13 the `unsafe` keyword. No need to write headers, initialize runtimes, or any of
14 that other FFI boiler-plate.
15
16 There are several places `unsafe` can appear in Rust today, which can largely be
17 grouped into two categories:
18
19 * There are unchecked contracts here. To declare you understand this, I require
20 you to write `unsafe` elsewhere:
21     * On functions, `unsafe` is declaring the function to be unsafe to call.
22       Users of the function must check the documentation to determine what this
23       means, and then have to write `unsafe` somewhere to identify that they're
24       aware of the danger.
25     * On trait declarations, `unsafe` is declaring that *implementing* the trait
26       is an unsafe operation, as it has contracts that other unsafe code is free
27       to trust blindly. (More on this below.)
28
29 * I am declaring that I have, to the best of my knowledge, adhered to the
30 unchecked contracts:
31     * On trait implementations, `unsafe` is declaring that the contract of the
32       `unsafe` trait has been upheld.
33     * On blocks, `unsafe` is declaring any unsafety from an unsafe
34       operation within to be handled, and therefore the parent function is safe.
35
36 There is also `#[unsafe_no_drop_flag]`, which is a special case that exists for
37 historical reasons and is in the process of being phased out. See the section on
38 [drop flags][] for details.
39
40 Some examples of unsafe functions:
41
42 * `slice::get_unchecked` will perform unchecked indexing, allowing memory
43   safety to be freely violated.
44 * `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is
45   not "in bounds" as defined by LLVM.
46 * `mem::transmute` reinterprets some value as having the given type,
47   bypassing type safety in arbitrary ways. (see [conversions][] for details)
48 * All FFI functions are `unsafe` because they can do arbitrary things.
49   C being an obvious culprit, but generally any language can do something
50   that Rust isn't happy about.
51
52 As of Rust 1.0 there are exactly two unsafe traits:
53
54 * `Send` is a marker trait (it has no actual API) that promises implementors
55   are safe to send (move) to another thread.
56 * `Sync` is a marker trait that promises that threads can safely share
57   implementors through a shared reference.
58
59 The need for unsafe traits boils down to the fundamental property of safe code:
60
61 **No matter how completely awful Safe code is, it can't cause Undefined
62 Behaviour.**
63
64 This means that Unsafe Rust, **the royal vanguard of Undefined Behaviour**, has to be
65 *super paranoid* about generic safe code. To be clear, Unsafe Rust is totally free to trust
66 specific safe code. Anything else would degenerate into infinite spirals of
67 paranoid despair. In particular it's generally regarded as ok to trust the standard library
68 to be correct. `std` is effectively an extension of the language, and you
69 really just have to trust the language. If `std` fails to uphold the
70 guarantees it declares, then it's basically a language bug.
71
72 That said, it would be best to minimize *needlessly* relying on properties of
73 concrete safe code. Bugs happen! Of course, I must reinforce that this is only
74 a concern for Unsafe code. Safe code can blindly trust anyone and everyone
75 as far as basic memory-safety is concerned.
76
77 On the other hand, safe traits are free to declare arbitrary contracts, but because
78 implementing them is safe, unsafe code can't trust those contracts to actually
79 be upheld. This is different from the concrete case because *anyone* can
80 randomly implement the interface. There is something fundamentally different
81 about trusting a particular piece of code to be correct, and trusting *all the
82 code that will ever be written* to be correct.
83
84 For instance Rust has `PartialOrd` and `Ord` traits to try to differentiate
85 between types which can "just" be compared, and those that actually implement a
86 total ordering. Pretty much every API that wants to work with data that can be
87 compared wants Ord data. For instance, a sorted map like BTreeMap
88 *doesn't even make sense* for partially ordered types. If you claim to implement
89 Ord for a type, but don't actually provide a proper total ordering, BTreeMap will
90 get *really confused* and start making a total mess of itself. Data that is
91 inserted may be impossible to find!
92
93 But that's okay. BTreeMap is safe, so it guarantees that even if you give it a
94 completely garbage Ord implementation, it will still do something *safe*. You
95 won't start reading uninitialized or unallocated memory. In fact, BTreeMap
96 manages to not actually lose any of your data. When the map is dropped, all the
97 destructors will be successfully called! Hooray!
98
99 However BTreeMap is implemented using a modest spoonful of Unsafe Rust (most collections
100 are). That means that it's not necessarily *trivially true* that a bad Ord
101 implementation will make BTreeMap behave safely. BTreeMap must be sure not to rely
102 on Ord *where safety is at stake*. Ord is provided by safe code, and safety is not
103 safe code's responsibility to uphold.
104
105 But wouldn't it be grand if there was some way for Unsafe to trust some trait
106 contracts *somewhere*? This is the problem that unsafe traits tackle: by marking
107 *the trait itself* as unsafe to implement, unsafe code can trust the implementation
108 to uphold the trait's contract. Although the trait implementation may be
109 incorrect in arbitrary other ways.
110
111 For instance, given a hypothetical UnsafeOrd trait, this is technically a valid
112 implementation:
113
114 ```rust
115 # use std::cmp::Ordering;
116 # struct MyType;
117 # unsafe trait UnsafeOrd { fn cmp(&self, other: &Self) -> Ordering; }
118 unsafe impl UnsafeOrd for MyType {
119     fn cmp(&self, other: &Self) -> Ordering {
120         Ordering::Equal
121     }
122 }
123 ```
124
125 But it's probably not the implementation you want.
126
127 Rust has traditionally avoided making traits unsafe because it makes Unsafe
128 pervasive, which is not desirable. Send and Sync are unsafe is because thread
129 safety is a *fundamental property* that unsafe code cannot possibly hope to defend
130 against in the same way it would defend against a bad Ord implementation. The
131 only way to possibly defend against thread-unsafety would be to *not use
132 threading at all*. Making every load and store atomic isn't even sufficient,
133 because it's possible for complex invariants to exist between disjoint locations
134 in memory. For instance, the pointer and capacity of a Vec must be in sync.
135
136 Even concurrent paradigms that are traditionally regarded as Totally Safe like
137 message passing implicitly rely on some notion of thread safety -- are you
138 really message-passing if you pass a pointer? Send and Sync therefore require
139 some fundamental level of trust that Safe code can't provide, so they must be
140 unsafe to implement. To help obviate the pervasive unsafety that this would
141 introduce, Send (resp. Sync) is automatically derived for all types composed only
142 of Send (resp. Sync) values. 99% of types are Send and Sync, and 99% of those
143 never actually say it (the remaining 1% is overwhelmingly synchronization
144 primitives).
145
146
147
148
149 [drop flags]: drop-flags.html
150 [conversions]: conversions.html