Skip to content

Commit

Permalink
Merge pull request rust-lang#28 from Gankro/cleanup
Browse files Browse the repository at this point in the history
Cleanup the first chapter
  • Loading branch information
steveklabnik authored Aug 8, 2017
2 parents f570bcb + a080854 commit a4322cc
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 168 deletions.
35 changes: 19 additions & 16 deletions src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#### The Dark Arts of Advanced and Unsafe Rust Programming

# NOTE: This is a draft document, and may contain serious errors
# NOTE: This is a draft document that discusses several unstable aspects of Rust, and may contain serious errors or outdated information.

> Instead of the programs I had hoped for, there came only a shuddering blackness
and ineffable loneliness; and I saw at last a fearful truth which no one had
Expand All @@ -19,20 +19,23 @@ infinitesimal fragments of despair.

Should you wish a long and happy career of writing Rust programs, you should
turn back now and forget you ever saw this book. It is not necessary. However
if you intend to write unsafe code -- or just want to dig into the guts of the
language -- this book contains invaluable information.

Unlike [The Book][trpl] we will be assuming considerable prior knowledge. In
particular, you should be comfortable with basic systems programming and Rust.
If you don't feel comfortable with these topics, you should consider [reading
The Book][trpl] first. Though we will not be assuming that you have, and will
take care to occasionally give a refresher on the basics where appropriate. You
can skip straight to this book if you want; just know that we won't be
explaining everything from the ground up.

To be clear, this book goes into deep detail. We're going to dig into
exception-safety, pointer aliasing, memory models, and even some type-theory.
We will also be spending a lot of time talking about the different kinds
of safety and guarantees.
if you intend to write unsafe code — or just want to dig into the guts of the
language — this book contains lots of useful information.

Unlike *[The Rust Programming Language][trpl]*, we will be assuming considerable
prior knowledge. In particular, you should be comfortable with basic systems
programming and Rust. If you don't feel comfortable with these topics, you
should consider [reading The Book][trpl] first. That said, we won't assume you
have read it, and we will take care to occasionally give a refresher on the
basics where appropriate. You can skip straight to this book if you want;
just know that we won't be explaining everything from the ground up.

We're going to dig into exception-safety, pointer aliasing, memory models,
compiler and hardware implementation details, and even some type-theory.
Much text will be devoted to exotic corner cases that no one *should* ever have
to care about, but suddenly become important because we wrote `unsafe`.

We will also be spending a lot of time talking about the different kinds of
safety and guarantees that programs could care about.

[trpl]: ../book/index.html
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* [Meet Safe and Unsafe](meet-safe-and-unsafe.md)
* [How Safe and Unsafe Interact](safe-unsafe-meaning.md)
* [What Unsafe Can Do](what-unsafe-does.md)
* [Working with Unsafe](working-with-unsafe.md)
* [Data Layout](data.md)
* [repr(Rust)](repr-rust.md)
Expand Down
130 changes: 49 additions & 81 deletions src/meet-safe-and-unsafe.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,51 @@
# Meet Safe and Unsafe

![safe and unsafe](img/safeandunsafe.svg)
![safe and unsafe](img/safeandunsafe.svg)

Programmers in safe "high-level" languages face a fundamental dilemma. On one
hand, it would be *really* great to just say what you want and not worry about
how it's done. On the other hand, that can lead to unacceptably poor
performance. It may be necessary to drop down to less clear or idiomatic
practices to get the performance characteristics you want. Or maybe you just
throw up your hands in disgust and decide to shell out to an implementation in
a less sugary-wonderful *unsafe* language.
It would be great to not have to worry about low-level implementation details.
Who could possibly care how much space the empty tuple occupies? Sadly, it
sometimes matters and we need to worry about it. The most common reason
developers start to care about implementation details is performance, but more
importantly, these details can become a matter of correctness when interfacing
directly with hardware, operating systems, or other languages.

Worse, when you want to talk directly to the operating system, you *have* to
talk to an unsafe language: *C*. C is ever-present and unavoidable. It's the
lingua-franca of the programming world.
Even other safe languages generally expose C interfaces for the world at large!
Regardless of why you're doing it, as soon as your program starts talking to
C it stops being safe.
When implementation details start to matter in a safe programming language,
programmers usually have three options:

With that said, Rust is *totally* a safe programming language.
* fiddle with the code to encourage the compiler/runtime to perform an optimization
* adopt a more unidiomatic or cumbersome design to get the desired implementation
* rewrite the implementation in a language that lets you deal with those details

Well, Rust *has* a safe programming language. Let's step back a bit.
For that last option, the language programmers tend to use is *C*. This is often
necessary to interface with systems that only declare a C interface.

Rust can be thought of as being composed of two programming languages: *Safe
Rust* and *Unsafe Rust*. Safe Rust is For Reals Totally Safe. Unsafe Rust,
unsurprisingly, is *not* For Reals Totally Safe. In fact, Unsafe Rust lets you
do some really, *really* unsafe things.
Unfortunately, C is incredibly unsafe to use (sometimes for good reason),
and this unsafety is magnified when trying to interoperate with another
language. Care must be taken to ensure C and the other language agree on
what's happening, and that they don't step on each other's toes.

So what does this have to do with Rust?

Well, unlike C, Rust is a safe programming language.

But, like C, Rust is an unsafe programming language.

More accurately, Rust *contains* both a safe and unsafe programming language.

Rust can be thought of as a combination of two programming languages: *Safe
Rust* and *Unsafe Rust*. Conveniently, these names mean exactly what they say:
Safe Rust is Safe. Unsafe Rust is, well, not. In fact, Unsafe Rust lets us
do some *really* unsafe things. Things the Rust authors will implore you not to
do, but we'll do anyway.

Safe Rust is the *true* Rust programming language. If all you do is write Safe
Rust, you will never have to worry about type-safety or memory-safety. You will
never endure a null or dangling pointer, or any of that Undefined Behavior
nonsense.

*That's totally awesome.*
never endure a dangling pointer, a use-after-free, or any other kind of
Undefined Behavior.

The standard library also gives you enough utilities out-of-the-box that you'll
be able to write awesome high-performance applications and libraries in pure
idiomatic Safe Rust.
The standard library also gives you enough utilities out of the box that you'll
be able to write high-performance applications and libraries in pure idiomatic
Safe Rust.

But maybe you want to talk to another language. Maybe you're writing a
low-level abstraction not exposed by the standard library. Maybe you're
Expand All @@ -44,57 +54,15 @@ need to do something the type-system doesn't understand and just *frob some dang
bits*. Maybe you need Unsafe Rust.

Unsafe Rust is exactly like Safe Rust with all the same rules and semantics.
However Unsafe Rust lets you do some *extra* things that are Definitely Not Safe.

The only things that are different in Unsafe Rust are that you can:

* Dereference raw pointers
* Call `unsafe` functions (including C functions, intrinsics, and the raw allocator)
* Implement `unsafe` traits
* Mutate statics

That's it. The reason these operations are relegated to Unsafe is that misusing
any of these things will cause the ever dreaded Undefined Behavior. Invoking
Undefined Behavior gives the compiler full rights to do arbitrarily bad things
to your program. You definitely *should not* invoke Undefined Behavior.

Unlike C, Undefined Behavior is pretty limited in scope in Rust. All the core
language cares about is preventing the following things:

* Dereferencing null or dangling pointers
* Reading [uninitialized memory]
* Breaking the [pointer aliasing rules]
* Producing invalid primitive values:
* dangling/null references
* a `bool` that isn't 0 or 1
* an undefined `enum` discriminant
* a `char` outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF]
* A non-utf8 `str`
* Unwinding into another language
* Causing a [data race][race]

That's it. That's all the causes of Undefined Behavior baked into Rust. Of
course, unsafe functions and traits are free to declare arbitrary other
constraints that a program must maintain to avoid Undefined Behavior. However,
generally violations of these constraints will just transitively lead to one of
the above problems. Some additional constraints may also derive from compiler
intrinsics that make special assumptions about how code can be optimized.

Rust is otherwise quite permissive with respect to other dubious operations.
Rust considers it "safe" to:

* Deadlock
* Have a [race condition][race]
* Leak memory
* Fail to call destructors
* Overflow integers
* Abort the program
* Delete the production database

However any program that actually manages to do such a thing is *probably*
incorrect. Rust provides lots of tools to make these things rare, but
these problems are considered impractical to categorically prevent.

[pointer aliasing rules]: references.html
[uninitialized memory]: uninitialized.html
[race]: races.html
It just lets you do some *extra* things that are Definitely Not Safe
(which we will define in the next section).

The value of this separation is that we gain the benefits of using an unsafe
language like C — low level control over implementation details — without most
of the problems that come with trying to integrate it with a completely
different safe language.

There are still some problems — most notably, we must become aware of properties
that the type system assumes and audit them in any code that interacts with
Unsafe Rust. That's the purpose of this book: to teach you about these assumptions
and how to manage them.
Loading

0 comments on commit a4322cc

Please sign in to comment.