Skip to content

Commit 554efc0

Browse files
committed
last of the emphasis cleanup
1 parent 7b33a1e commit 554efc0

12 files changed

+89
-84
lines changed

src/doc/tarpl/races.md

+9-7
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ it's impossible to alias a mutable reference, so it's impossible to perform a
1212
data race. Interior mutability makes this more complicated, which is largely why
1313
we have the Send and Sync traits (see below).
1414

15-
However Rust *does not* prevent general race conditions. This is
16-
pretty fundamentally impossible, and probably honestly undesirable. Your hardware
17-
is racy, your OS is racy, the other programs on your computer are racy, and the
18-
world this all runs in is racy. Any system that could genuinely claim to prevent
19-
*all* race conditions would be pretty awful to use, if not just incorrect.
15+
**However Rust does not prevent general race conditions.**
16+
17+
This is pretty fundamentally impossible, and probably honestly undesirable. Your
18+
hardware is racy, your OS is racy, the other programs on your computer are racy,
19+
and the world this all runs in is racy. Any system that could genuinely claim to
20+
prevent *all* race conditions would be pretty awful to use, if not just
21+
incorrect.
2022

2123
So it's perfectly "fine" for a Safe Rust program to get deadlocked or do
2224
something incredibly stupid with incorrect synchronization. Obviously such a
@@ -46,7 +48,7 @@ thread::spawn(move || {
4648
});
4749
4850
// Index with the value loaded from the atomic. This is safe because we
49-
// read the atomic memory only once, and then pass a *copy* of that value
51+
// read the atomic memory only once, and then pass a copy of that value
5052
// to the Vec's indexing implementation. This indexing will be correctly
5153
// bounds checked, and there's no chance of the value getting changed
5254
// in the middle. However our program may panic if the thread we spawned
@@ -75,7 +77,7 @@ thread::spawn(move || {
7577
7678
if idx.load(Ordering::SeqCst) < data.len() {
7779
unsafe {
78-
// Incorrectly loading the idx *after* we did the bounds check.
80+
// Incorrectly loading the idx after we did the bounds check.
7981
// It could have changed. This is a race condition, *and dangerous*
8082
// because we decided to do `get_unchecked`, which is `unsafe`.
8183
println!("{}", data.get_unchecked(idx.load(Ordering::SeqCst)));

src/doc/tarpl/repr-rust.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ struct B {
7070
Rust *does* guarantee that two instances of A have their data laid out in
7171
exactly the same way. However Rust *does not* guarantee that an instance of A
7272
has the same field ordering or padding as an instance of B (in practice there's
73-
no *particular* reason why they wouldn't, other than that its not currently
73+
no particular reason why they wouldn't, other than that its not currently
7474
guaranteed).
7575

7676
With A and B as written, this is basically nonsensical, but several other
@@ -88,9 +88,9 @@ struct Foo<T, U> {
8888
```
8989

9090
Now consider the monomorphizations of `Foo<u32, u16>` and `Foo<u16, u32>`. If
91-
Rust lays out the fields in the order specified, we expect it to *pad* the
92-
values in the struct to satisfy their *alignment* requirements. So if Rust
93-
didn't reorder fields, we would expect Rust to produce the following:
91+
Rust lays out the fields in the order specified, we expect it to pad the
92+
values in the struct to satisfy their alignment requirements. So if Rust
93+
didn't reorder fields, we would expect it to produce the following:
9494

9595
```rust,ignore
9696
struct Foo<u16, u32> {
@@ -112,7 +112,7 @@ The latter case quite simply wastes space. An optimal use of space therefore
112112
requires different monomorphizations to have *different field orderings*.
113113

114114
**Note: this is a hypothetical optimization that is not yet implemented in Rust
115-
**1.0
115+
1.0**
116116

117117
Enums make this consideration even more complicated. Naively, an enum such as:
118118

@@ -128,8 +128,8 @@ would be laid out as:
128128

129129
```rust
130130
struct FooRepr {
131-
data: u64, // this is *really* either a u64, u32, or u8 based on `tag`
132-
tag: u8, // 0 = A, 1 = B, 2 = C
131+
data: u64, // this is either a u64, u32, or u8 based on `tag`
132+
tag: u8, // 0 = A, 1 = B, 2 = C
133133
}
134134
```
135135

src/doc/tarpl/safe-unsafe-meaning.md

+25-25
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ So what's the relationship between Safe and Unsafe Rust? How do they interact?
55
Rust models the separation between Safe and Unsafe Rust with the `unsafe`
66
keyword, which can be thought as a sort of *foreign function interface* (FFI)
77
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
8+
is a safe language: all the scary unsafe bits are relegated exclusively to FFI
99
*just like every other safe language*.
1010

1111
However 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
6262
Behaviour.**
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

7272
That said, it would be best to minimize *needlessly* relying on properties of
7373
concrete safe code. Bugs happen! Of course, I must reinforce that this is only
7474
a concern for Unsafe code. Safe code can blindly trust anyone and everyone
7575
as far as basic memory-safety is concerned.
7676

7777
On 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
7979
be upheld. This is different from the concrete case because *anyone* can
8080
randomly 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
8282
code that will ever be written* to be correct.
8383

8484
For instance Rust has `PartialOrd` and `Ord` traits to try to differentiate
8585
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 *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
8989
Ord for a type, but don't actually provide a proper total ordering, BTreeMap will
9090
get *really confused* and start making a total mess of itself. Data that is
9191
inserted may be impossible to find!
9292

9393
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 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
9696
manages to not actually lose any of your data. When the map is dropped, all the
9797
destructors 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
106106
contracts *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
108108
to uphold the trait's contract. Although the trait implementation may be
109109
incorrect in arbitrary other ways.
110110

@@ -126,7 +126,7 @@ But it's probably not the implementation you want.
126126

127127
Rust has traditionally avoided making traits unsafe because it makes Unsafe
128128
pervasive, 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
130130
against in the same way it would defend against a bad Ord implementation. The
131131
only way to possibly defend against thread-unsafety would be to *not use
132132
threading 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

136136
Even concurrent paradigms that are traditionally regarded as Totally Safe like
137137
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
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
140140
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
141+
introduce, Send (resp. Sync) is automatically derived for all types composed only
142142
of Send (resp. Sync) values. 99% of types are Send and Sync, and 99% of those
143143
never actually say it (the remaining 1% is overwhelmingly synchronization
144144
primitives).

src/doc/tarpl/send-and-sync.md

+15-14
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,19 @@ captures this with through the `Send` and `Sync` traits.
88
* A type is Send if it is safe to send it to another thread. A type is Sync if
99
* it is safe to share between threads (`&T` is Send).
1010

11-
Send and Sync are *very* fundamental to Rust's concurrency story. As such, a
11+
Send and Sync are fundamental to Rust's concurrency story. As such, a
1212
substantial amount of special tooling exists to make them work right. First and
13-
foremost, they're *unsafe traits*. This means that they are unsafe *to
14-
implement*, and other unsafe code can *trust* that they are correctly
13+
foremost, they're [unsafe traits][]. This means that they are unsafe to
14+
implement, and other unsafe code can that they are correctly
1515
implemented. Since they're *marker traits* (they have no associated items like
1616
methods), correctly implemented simply means that they have the intrinsic
1717
properties an implementor should have. Incorrectly implementing Send or Sync can
1818
cause Undefined Behaviour.
1919

20-
Send and Sync are also what Rust calls *opt-in builtin traits*. This means that,
21-
unlike every other trait, they are *automatically* derived: if a type is
22-
composed entirely of Send or Sync types, then it is Send or Sync. Almost all
23-
primitives are Send and Sync, and as a consequence pretty much all types you'll
24-
ever interact with are Send and Sync.
20+
Send and Sync are also automatically derived traits. This means that, unlike
21+
every other trait, if a type is composed entirely of Send or Sync types, then it
22+
is Send or Sync. Almost all primitives are Send and Sync, and as a consequence
23+
pretty much all types you'll ever interact with are Send and Sync.
2524

2625
Major exceptions include:
2726

@@ -37,13 +36,12 @@ sense, one could argue that it would be "fine" for them to be marked as thread
3736
safe.
3837

3938
However it's important that they aren't thread safe to prevent types that
40-
*contain them* from being automatically marked as thread safe. These types have
39+
contain them from being automatically marked as thread safe. These types have
4140
non-trivial untracked ownership, and it's unlikely that their author was
4241
necessarily thinking hard about thread safety. In the case of Rc, we have a nice
43-
example of a type that contains a `*mut` that is *definitely* not thread safe.
42+
example of a type that contains a `*mut` that is definitely not thread safe.
4443

45-
Types that aren't automatically derived can *opt-in* to Send and Sync by simply
46-
implementing them:
44+
Types that aren't automatically derived can simply implement them if desired:
4745

4846
```rust
4947
struct MyBox(*mut u8);
@@ -52,12 +50,13 @@ unsafe impl Send for MyBox {}
5250
unsafe impl Sync for MyBox {}
5351
```
5452

55-
In the *incredibly rare* case that a type is *inappropriately* automatically
56-
derived to be Send or Sync, then one can also *unimplement* Send and Sync:
53+
In the *incredibly rare* case that a type is inappropriately automatically
54+
derived to be Send or Sync, then one can also unimplement Send and Sync:
5755

5856
```rust
5957
#![feature(optin_builtin_traits)]
6058

59+
// I have some magic semantics for some synchronization primitive!
6160
struct SpecialThreadToken(u8);
6261

6362
impl !Send for SpecialThreadToken {}
@@ -77,3 +76,5 @@ largely behave like an `&` or `&mut` into the collection.
7776

7877
TODO: better explain what can or can't be Send or Sync. Sufficient to appeal
7978
only to data races?
79+
80+
[unsafe traits]: safe-unsafe-meaning.html

src/doc/tarpl/subtyping.md

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
% Subtyping and Variance
22

33
Although Rust doesn't have any notion of structural inheritance, it *does*
4-
include subtyping. In Rust, subtyping derives entirely from *lifetimes*. Since
4+
include subtyping. In Rust, subtyping derives entirely from lifetimes. Since
55
lifetimes are scopes, we can partially order them based on the *contains*
66
(outlives) relationship. We can even express this as a generic bound.
77

8-
Subtyping on lifetimes in terms of that relationship: if `'a: 'b` ("a contains
8+
Subtyping on lifetimes is in terms of that relationship: if `'a: 'b` ("a contains
99
b" or "a outlives b"), then `'a` is a subtype of `'b`. This is a large source of
1010
confusion, because it seems intuitively backwards to many: the bigger scope is a
11-
*sub type* of the smaller scope.
11+
*subtype* of the smaller scope.
1212

1313
This does in fact make sense, though. The intuitive reason for this is that if
1414
you expect an `&'a u8`, then it's totally fine for me to hand you an `&'static
@@ -72,7 +72,7 @@ to be able to pass `&&'static str` where an `&&'a str` is expected. The
7272
additional level of indirection does not change the desire to be able to pass
7373
longer lived things where shorted lived things are expected.
7474

75-
However this logic *does not* apply to `&mut`. To see why `&mut` should
75+
However this logic doesn't apply to `&mut`. To see why `&mut` should
7676
be invariant over T, consider the following code:
7777

7878
```rust,ignore
@@ -109,7 +109,7 @@ between `'a` and T is that `'a` is a property of the reference itself,
109109
while T is something the reference is borrowing. If you change T's type, then
110110
the source still remembers the original type. However if you change the
111111
lifetime's type, no one but the reference knows this information, so it's fine.
112-
Put another way, `&'a mut T` owns `'a`, but only *borrows* T.
112+
Put another way: `&'a mut T` owns `'a`, but only *borrows* T.
113113

114114
`Box` and `Vec` are interesting cases because they're variant, but you can
115115
definitely store values in them! This is where Rust gets really clever: it's
@@ -118,15 +118,15 @@ in them *via a mutable reference*! The mutable reference makes the whole type
118118
invariant, and therefore prevents you from smuggling a short-lived type into
119119
them.
120120

121-
Being variant *does* allows `Box` and `Vec` to be weakened when shared
121+
Being variant allows `Box` and `Vec` to be weakened when shared
122122
immutably. So you can pass a `&Box<&'static str>` where a `&Box<&'a str>` is
123123
expected.
124124

125125
However what should happen when passing *by-value* is less obvious. It turns out
126126
that, yes, you can use subtyping when passing by-value. That is, this works:
127127

128128
```rust
129-
fn get_box<'a>(str: &'a u8) -> Box<&'a str> {
129+
fn get_box<'a>(str: &'a str) -> Box<&'a str> {
130130
// string literals are `&'static str`s
131131
Box::new("hello")
132132
}
@@ -150,7 +150,7 @@ signature:
150150
fn foo(&'a str) -> usize;
151151
```
152152

153-
This signature claims that it can handle any `&str` that lives *at least* as
153+
This signature claims that it can handle any `&str` that lives at least as
154154
long as `'a`. Now if this signature was variant over `&'a str`, that
155155
would mean
156156

@@ -159,10 +159,12 @@ fn foo(&'static str) -> usize;
159159
```
160160

161161
could be provided in its place, as it would be a subtype. However this function
162-
has a *stronger* requirement: it says that it can *only* handle `&'static str`s,
163-
and nothing else. Therefore functions are not variant over their arguments.
162+
has a stronger requirement: it says that it can only handle `&'static str`s,
163+
and nothing else. Giving `&'a str`s to it would be unsound, as it's free to
164+
assume that what it's given lives forever. Therefore functions are not variant
165+
over their arguments.
164166

165-
To see why `Fn(T) -> U` should be *variant* over U, consider the following
167+
To see why `Fn(T) -> U` should be variant over U, consider the following
166168
function signature:
167169

168170
```rust,ignore
@@ -177,7 +179,7 @@ therefore completely reasonable to provide
177179
fn foo(usize) -> &'static str;
178180
```
179181

180-
in its place. Therefore functions *are* variant over their return type.
182+
in its place. Therefore functions are variant over their return type.
181183

182184
`*const` has the exact same semantics as `&`, so variance follows. `*mut` on the
183185
other hand can dereference to an `&mut` whether shared or not, so it is marked

src/doc/tarpl/unwinding.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ panics can only be caught by the parent thread. This means catching a panic
3131
requires spinning up an entire OS thread! This unfortunately stands in conflict
3232
to Rust's philosophy of zero-cost abstractions.
3333

34-
There is an *unstable* API called `catch_panic` that enables catching a panic
34+
There is an unstable API called `catch_panic` that enables catching a panic
3535
without spawning a thread. Still, we would encourage you to only do this
3636
sparingly. In particular, Rust's current unwinding implementation is heavily
3737
optimized for the "doesn't unwind" case. If a program doesn't unwind, there
3838
should be no runtime cost for the program being *ready* to unwind. As a
39-
consequence, *actually* unwinding will be more expensive than in e.g. Java.
39+
consequence, actually unwinding will be more expensive than in e.g. Java.
4040
Don't build your programs to unwind under normal circumstances. Ideally, you
4141
should only panic for programming errors or *extreme* problems.
4242

0 commit comments

Comments
 (0)