@@ -5,7 +5,7 @@ So what's the relationship between Safe and Unsafe Rust? How do they interact?
55Rust models the separation between Safe and Unsafe Rust with the ` unsafe `
66keyword, which can be thought as a sort of * foreign function interface* (FFI)
77between 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
8+ is a safe language: all the scary unsafe bits are relegated exclusively to FFI
99* just like every other safe language* .
1010
1111However because one language is a subset of the other, the two can be cleanly
@@ -61,50 +61,50 @@ The need for unsafe traits boils down to the fundamental property of safe code:
6161** No matter how completely awful Safe code is, it can't cause Undefined
6262Behaviour.**
6363
64- This means that Unsafe, ** the royal vanguard of Undefined Behaviour** , has to be
65- * super paranoid* about generic safe code. Unsafe is free to trust * specific * safe
66- code (or else you would degenerate into infinite spirals of paranoid despair).
67- It is generally regarded as ok to trust the standard library to be correct, as
68- ` std ` is effectively an extension of the language ( and you * really * just have
69- to trust the language) . If ` std ` fails to uphold the guarantees it declares,
70- then it's basically a language bug.
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.
7171
7272That said, it would be best to minimize * needlessly* relying on properties of
7373concrete safe code. Bugs happen! Of course, I must reinforce that this is only
7474a concern for Unsafe code. Safe code can blindly trust anyone and everyone
7575as far as basic memory-safety is concerned.
7676
7777On the other hand, safe traits are free to declare arbitrary contracts, but because
78- implementing them is Safe, Unsafe can't trust those contracts to actually
78+ implementing them is safe, unsafe code can't trust those contracts to actually
7979be upheld. This is different from the concrete case because * anyone* can
8080randomly implement the interface. There is something fundamentally different
81- about trusting a * particular* piece of code to be correct, and trusting * all the
81+ about trusting a particular piece of code to be correct, and trusting * all the
8282code that will ever be written* to be correct.
8383
8484For instance Rust has ` PartialOrd ` and ` Ord ` traits to try to differentiate
8585between 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 * really * wants Ord data. For instance, a sorted map like BTreeMap
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
8888* doesn't even make sense* for partially ordered types. If you claim to implement
8989Ord for a type, but don't actually provide a proper total ordering, BTreeMap will
9090get * really confused* and start making a total mess of itself. Data that is
9191inserted may be impossible to find!
9292
9393But 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 memory or unallocated memory. In fact, BTreeMap
94+ completely garbage Ord implementation, it will still do something * safe* . You
95+ won't start reading uninitialized or unallocated memory. In fact, BTreeMap
9696manages to not actually lose any of your data. When the map is dropped, all the
9797destructors will be successfully called! Hooray!
9898
99- However BTreeMap is implemented using a modest spoonful of Unsafe (most collections
100- are). That means that it is not necessarily * trivially true* that a bad Ord
101- implementation will make BTreeMap behave safely. Unsafe must be sure not to rely
102- on Ord * where safety is at stake* . Ord is provided by Safe , and safety is not
103- Safe 's responsibility to uphold.
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.
104104
105- But wouldn't it be grand if there was some way for Unsafe to trust * some* trait
105+ But wouldn't it be grand if there was some way for Unsafe to trust some trait
106106contracts * somewhere* ? This is the problem that unsafe traits tackle: by marking
107- * the trait itself* as unsafe * to implement* , Unsafe can trust the implementation
107+ * the trait itself* as unsafe to implement, unsafe code can trust the implementation
108108to uphold the trait's contract. Although the trait implementation may be
109109incorrect in arbitrary other ways.
110110
@@ -126,7 +126,7 @@ But it's probably not the implementation you want.
126126
127127Rust has traditionally avoided making traits unsafe because it makes Unsafe
128128pervasive, which is not desirable. Send and Sync are unsafe is because thread
129- safety is a * fundamental property* that Unsafe cannot possibly hope to defend
129+ safety is a * fundamental property* that unsafe code cannot possibly hope to defend
130130against in the same way it would defend against a bad Ord implementation. The
131131only way to possibly defend against thread-unsafety would be to * not use
132132threading at all* . Making every load and store atomic isn't even sufficient,
@@ -135,10 +135,10 @@ in memory. For instance, the pointer and capacity of a Vec must be in sync.
135135
136136Even concurrent paradigms that are traditionally regarded as Totally Safe like
137137message 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
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
140140unsafe to implement. To help obviate the pervasive unsafety that this would
141- introduce, Send (resp. Sync) is * automatically* derived for all types composed only
141+ introduce, Send (resp. Sync) is automatically derived for all types composed only
142142of Send (resp. Sync) values. 99% of types are Send and Sync, and 99% of those
143143never actually say it (the remaining 1% is overwhelmingly synchronization
144144primitives).
0 commit comments