]> git.proxmox.com Git - rustc.git/blame - src/doc/nomicon/src/safe-unsafe-meaning.md
New upstream version 1.31.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,
27the index passed to `slice::get_unchecked` is in-bounds.
28
29You can use `unsafe` on a trait implementation to declare that the implementation
30upholds the trait's contract. For instance, that a type implementing `Send` is
31really safe to move to another thread.
3157f602 32
3157f602
XL
33The standard library has a number of unsafe functions, including:
34
35* `slice::get_unchecked`, which performs unchecked indexing, allowing
36 memory safety to be freely violated.
37* `mem::transmute` reinterprets some value as having a given type, bypassing
38 type safety in arbitrary ways (see [conversions] for details).
3b2f2976
XL
39* Every raw pointer to a sized type has an `offset` method that
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
SL
43
44As of Rust 1.0 there are exactly two unsafe traits:
45
3157f602
XL
46* `Send` is a marker trait (a trait with no API) that promises implementors are
47 safe to send (move) to another thread.
48* `Sync` is a marker trait that promises threads can safely share implementors
49 through a shared reference.
50
3b2f2976
XL
51Much of the Rust standard library also uses Unsafe Rust internally. These
52implementations have generally been rigorously manually checked, so the Safe Rust
53interfaces built on top of these implementations can be assumed to be safe.
3157f602
XL
54
55The need for all of this separation boils down a single fundamental property
56of Safe Rust:
57
58**No matter what, Safe Rust can't cause Undefined Behavior.**
59
3b2f2976
XL
60The design of the safe/unsafe split means that there is an asymmetric trust
61relationship between Safe and Unsafe Rust. Safe Rust inherently has to
62trust that any Unsafe Rust it touches has been written correctly.
63On the other hand, Unsafe Rust has to be very careful about trusting Safe Rust.
3157f602
XL
64
65As an example, Rust has the `PartialOrd` and `Ord` traits to differentiate
3b2f2976
XL
66between types which can "just" be compared, and those that provide a "total"
67ordering (which basically means that comparison behaves reasonably).
68
69`BTreeMap` doesn't really make sense for partially-ordered types, and so it
70requires that its keys implement `Ord`. However, `BTreeMap` has Unsafe Rust code
71inside of its implementation. Because it would be unacceptable for a sloppy `Ord`
72implementation (which is Safe to write) to cause Undefined Behavior, the Unsafe
73code in BTreeMap must be written to be robust against `Ord` implementations which
74aren't actually total — even though that's the whole point of requiring `Ord`.
75
76The Unsafe Rust code just can't trust the Safe Rust code to be written correctly.
77That said, `BTreeMap` will still behave completely erratically if you feed in
78values that don't have a total ordering. It just won't ever cause Undefined
79Behavior.
80
81One may wonder, if `BTreeMap` cannot trust `Ord` because it's Safe, why can it
82trust *any* Safe code? For instance `BTreeMap` relies on integers and slices to
83be implemented correctly. Those are safe too, right?
84
85The difference is one of scope. When `BTreeMap` relies on integers and slices,
86it's relying on one very specific implementation. This is a measured risk that
87can be weighed against the benefit. In this case there's basically zero risk;
88if integers and slices are broken, *everyone* is broken. Also, they're maintained
89by the same people who maintain `BTreeMap`, so it's easy to keep tabs on them.
90
91On the other hand, `BTreeMap`'s key type is generic. Trusting its `Ord` implementation
92means trusting every `Ord` implementation in the past, present, and future.
93Here the risk is high: someone somewhere is going to make a mistake and mess up
94their `Ord` implementation, or even just straight up lie about providing a total
95ordering because "it seems to work". When that happens, `BTreeMap` needs to be
96prepared.
97
98The same logic applies to trusting a closure that's passed to you to behave
99correctly.
100
101This problem of unbounded generic trust is the problem that `unsafe` traits
102exist to resolve. The `BTreeMap` type could theoretically require that keys
103implement a new trait called `UnsafeOrd`, rather than `Ord`, that might look
104like this:
c1a9b12d
SL
105
106```rust
3157f602
XL
107use std::cmp::Ordering;
108
109unsafe trait UnsafeOrd {
110 fn cmp(&self, other: &Self) -> Ordering;
c1a9b12d
SL
111}
112```
113
3157f602
XL
114Then, a type would use `unsafe` to implement `UnsafeOrd`, indicating that
115they've ensured their implementation maintains whatever contracts the
116trait expects. In this situation, the Unsafe Rust in the internals of
3b2f2976
XL
117`BTreeMap` would be justified in trusting that the key type's `UnsafeOrd`
118implementation is correct. If it isn't, it's the fault of the unsafe trait
119implementation, which is consistent with Rust's safety guarantees.
3157f602
XL
120
121The decision of whether to mark a trait `unsafe` is an API design choice.
3b2f2976
XL
122Rust has traditionally avoided doing this because it makes Unsafe
123Rust pervasive, which isn't desirable. `Send` and `Sync` are marked unsafe
3157f602
XL
124because thread safety is a *fundamental property* that unsafe code can't
125possibly hope to defend against in the way it could defend against a bad
126`Ord` implementation. The decision of whether to mark your own traits `unsafe`
3b2f2976 127depends on the same sort of consideration. If `unsafe` code can't reasonably
3157f602
XL
128expect to defend against a bad implementation of the trait, then marking the
129trait `unsafe` is a reasonable choice.
130
3b2f2976 131As an aside, while `Send` and `Sync` are `unsafe` traits, they are *also*
3157f602
XL
132automatically implemented for types when such derivations are provably safe
133to do. `Send` is automatically derived for all types composed only of values
134whose types also implement `Send`. `Sync` is automatically derived for all
3b2f2976
XL
135types composed only of values whose types also implement `Sync`. This minimizes
136the pervasive unsafety of making these two traits `unsafe`.
3157f602 137
3b2f2976
XL
138This is the balance between Safe and Unsafe Rust. The separation is designed to
139make using Safe Rust as ergonomic as possible, but requires extra effort and
140care when writing Unsafe Rust. The rest of this book is largely a discussion
141of the sort of care that must be taken, and what contracts Unsafe Rust must uphold.
c1a9b12d 142
c1a9b12d 143[conversions]: conversions.html
3b2f2976 144[ptr_offset]: ../std/primitive.pointer.html#method.offset
3157f602 145