From 30ab859c734c85879d713899134ffa264dad5a38 Mon Sep 17 00:00:00 2001 From: Zooko Wilcox-O'Hearn Date: Mon, 12 May 2014 15:38:50 +0000 Subject: [PATCH 1/2] Optimize out exhortations about being careful. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yes, it is important to be careful, but repeated emphasis about it is probably not helpful — it starts to sound like you came for a tutorial but found a finger-wagging lecture. Even after I removed a few of these comments, there are still several left in the text. That's probably fine! A couple of mentions of how this is dangerous and you ought to be careful may be a good reminder to the reader. Note: this patch doesn't do any reflowing of text, so that you can more easily see the semantic content of this change. I'll follow this up with a patch that reflows the paragraphs that I touched. --- src/doc/guide-unsafe.md | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/doc/guide-unsafe.md b/src/doc/guide-unsafe.md index d78e2103daca1..bc40b72cd1c23 100644 --- a/src/doc/guide-unsafe.md +++ b/src/doc/guide-unsafe.md @@ -3,13 +3,12 @@ # Introduction Rust aims to provide safe abstractions over the low-level details of -the CPU and operating system, but sometimes one is forced to drop down -and write code at that level (those abstractions have to be created -somehow). This guide aims to provide an overview of the dangers and +the CPU and operating system, but sometimes one needs to drop down +and write code at that level. This guide aims to provide an overview of the dangers and power one gets with Rust's unsafe subset. Rust provides an escape hatch in the form of the `unsafe { ... }` -block which allows the programmer to dodge some of the compilers +block which allows the programmer to dodge some of the compiler's checks and do a wide range of operations, such as: - dereferencing [raw pointers](#raw-pointers) @@ -18,12 +17,12 @@ checks and do a wide range of operations, such as: - [inline assembly](#inline-assembly) Note that an `unsafe` block does not relax the rules about lifetimes -of `&` and the freezing of borrowed data, it just allows the use of -additional techniques for skirting the compiler's watchful eye. Any +of `&` and the freezing of borrowed data. + +Any use of `unsafe` is the programmer saying "I know more than you" to the compiler, and, as such, the programmer should be very sure that they -actually do know more about why that piece of code is valid. - +actually do know more about why that piece of code is valid. In general, one should try to minimize the amount of unsafe code in a code base; preferably by using the bare minimum `unsafe` blocks to build safe interfaces. @@ -38,15 +37,15 @@ build safe interfaces. ## References -One of Rust's biggest goals as a language is ensuring memory safety, -achieved in part via [the lifetime system](guide-lifetimes.html) which -every `&` references has associated with it. This system is how the +One of Rust's biggest features is memory safety. +This is achieved in part via [the lifetime system](guide-lifetimes.html), +which is how the compiler can guarantee that every `&` reference is always valid, and, for example, never pointing to freed memory. -These restrictions on `&` have huge advantages. However, there's no -free lunch club. For example, `&` isn't a valid replacement for C's -pointers, and so cannot be used for FFI, in general. Additionally, +These restrictions on `&` have huge advantages. However, they also +constrain how we can use them. For example, `&` doesn't behave identically to C's +pointers, and so cannot be used for pointers in foreign function interface (FFI). Additionally, both immutable (`&`) and mutable (`&mut`) references have some aliasing and freezing guarantees, required for memory safety. @@ -56,7 +55,7 @@ standard library types, e.g. `Cell` and `RefCell`, that provide inner mutability by replacing compile time guarantees with dynamic checks at runtime. -An `&mut` reference has a stronger requirement: when an object has an +An `&mut` reference has a different constraint: when an object has an `&mut T` pointing into it, then that `&mut` reference must be the only such usable path to that object in the whole program. That is, an `&mut` cannot alias with any other references. @@ -106,7 +105,7 @@ offered by the Rust language and libraries. For example, they Fortunately, they come with a redeeming feature: the weaker guarantees mean weaker restrictions. The missing restrictions make raw pointers -appropriate as a building block for (carefully!) implementing things +appropriate as a building block for implementing things like smart pointers and vectors inside libraries. For example, `*` pointers are allowed to alias, allowing them to be used to write shared-ownership types like reference counted and garbage collected @@ -117,8 +116,8 @@ There are two things that you are required to be careful about (i.e. require an `unsafe { ... }` block) with raw pointers: - dereferencing: they can have any value: so possible results include - a crash, a read of uninitialised memory, a use-after-free, or - reading data as normal (and one hopes happens). + a crash, a read of uninitialised memory, a use-after-free, or + reading data as normal. - pointer arithmetic via the `offset` [intrinsic](#intrinsics) (or `.offset` method): this intrinsic uses so-called "in-bounds" arithmetic, that is, it is only defined behaviour if the result is @@ -177,9 +176,10 @@ code: - store pointers privately (i.e. not in public fields of public structs), so that you can see and control all reads and writes to the pointer in one place. -- use `assert!()` a lot: once you've thrown away the protection of the - compiler & type-system via `unsafe { ... }` you're left with just - your wits and your `assert!()`s, any bug is potentially exploitable. +- use `assert!()` a lot: since you can't rely on the protection of the + compiler & type-system to ensure that your `unsafe` code is correct + at compile-time, use `assert!()` to verify that it is doing the right + thing at run-time. - implement the `Drop` for resource clean-up via a destructor, and use RAII (Resource Acquisition Is Initialization). This reduces the need for any manual memory management by users, and automatically ensures From 284945481d4027c5b596aec51fd20e3c6ec549d1 Mon Sep 17 00:00:00 2001 From: Zooko Wilcox-O'Hearn Date: Mon, 12 May 2014 17:40:15 +0000 Subject: [PATCH 2/2] reflow to fill-column 70 using emacs's text-reflowing capabilities --- src/doc/guide-unsafe.md | 56 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/src/doc/guide-unsafe.md b/src/doc/guide-unsafe.md index bc40b72cd1c23..a7d093c7257a8 100644 --- a/src/doc/guide-unsafe.md +++ b/src/doc/guide-unsafe.md @@ -3,9 +3,9 @@ # Introduction Rust aims to provide safe abstractions over the low-level details of -the CPU and operating system, but sometimes one needs to drop down -and write code at that level. This guide aims to provide an overview of the dangers and -power one gets with Rust's unsafe subset. +the CPU and operating system, but sometimes one needs to drop down and +write code at that level. This guide aims to provide an overview of +the dangers and power one gets with Rust's unsafe subset. Rust provides an escape hatch in the form of the `unsafe { ... }` block which allows the programmer to dodge some of the compiler's @@ -19,11 +19,10 @@ checks and do a wide range of operations, such as: Note that an `unsafe` block does not relax the rules about lifetimes of `&` and the freezing of borrowed data. -Any -use of `unsafe` is the programmer saying "I know more than you" to the -compiler, and, as such, the programmer should be very sure that they -actually do know more about why that piece of code is valid. -In general, one should try to minimize the amount of unsafe code in a +Any use of `unsafe` is the programmer saying "I know more than you" to +the compiler, and, as such, the programmer should be very sure that +they actually do know more about why that piece of code is valid. In +general, one should try to minimize the amount of unsafe code in a code base; preferably by using the bare minimum `unsafe` blocks to build safe interfaces. @@ -37,17 +36,17 @@ build safe interfaces. ## References -One of Rust's biggest features is memory safety. -This is achieved in part via [the lifetime system](guide-lifetimes.html), -which is how the +One of Rust's biggest features is memory safety. This is achieved in +part via [the lifetime system](guide-lifetimes.html), which is how the compiler can guarantee that every `&` reference is always valid, and, for example, never pointing to freed memory. These restrictions on `&` have huge advantages. However, they also -constrain how we can use them. For example, `&` doesn't behave identically to C's -pointers, and so cannot be used for pointers in foreign function interface (FFI). Additionally, -both immutable (`&`) and mutable (`&mut`) references have some -aliasing and freezing guarantees, required for memory safety. +constrain how we can use them. For example, `&` doesn't behave +identically to C's pointers, and so cannot be used for pointers in +foreign function interface (FFI). Additionally, both immutable (`&`) +and mutable (`&mut`) references have some aliasing and freezing +guarantees, required for memory safety. In particular, if you have an `&T` reference, then the `T` must not be modified through that reference or any other reference. There are some @@ -105,18 +104,18 @@ offered by the Rust language and libraries. For example, they Fortunately, they come with a redeeming feature: the weaker guarantees mean weaker restrictions. The missing restrictions make raw pointers -appropriate as a building block for implementing things -like smart pointers and vectors inside libraries. For example, `*` -pointers are allowed to alias, allowing them to be used to write -shared-ownership types like reference counted and garbage collected -pointers, and even thread-safe shared memory types (`Rc` and the `Arc` -types are both implemented entirely in Rust). +appropriate as a building block for implementing things like smart +pointers and vectors inside libraries. For example, `*` pointers are +allowed to alias, allowing them to be used to write shared-ownership +types like reference counted and garbage collected pointers, and even +thread-safe shared memory types (`Rc` and the `Arc` types are both +implemented entirely in Rust). There are two things that you are required to be careful about (i.e. require an `unsafe { ... }` block) with raw pointers: - dereferencing: they can have any value: so possible results include - a crash, a read of uninitialised memory, a use-after-free, or + a crash, a read of uninitialised memory, a use-after-free, or reading data as normal. - pointer arithmetic via the `offset` [intrinsic](#intrinsics) (or `.offset` method): this intrinsic uses so-called "in-bounds" @@ -178,8 +177,8 @@ code: the pointer in one place. - use `assert!()` a lot: since you can't rely on the protection of the compiler & type-system to ensure that your `unsafe` code is correct - at compile-time, use `assert!()` to verify that it is doing the right - thing at run-time. + at compile-time, use `assert!()` to verify that it is doing the + right thing at run-time. - implement the `Drop` for resource clean-up via a destructor, and use RAII (Resource Acquisition Is Initialization). This reduces the need for any manual memory management by users, and automatically ensures @@ -298,8 +297,8 @@ asm!(assembly template Any use of `asm` is feature gated (requires `#![feature(asm)]` on the crate to allow) and of course requires an `unsafe` block. -> **Note**: the examples here are given in x86/x86-64 assembly, but all -> platforms are supported. +> **Note**: the examples here are given in x86/x86-64 assembly, but +> all platforms are supported. ## Assembly template @@ -497,7 +496,7 @@ detects that it will overflow its stack. The example above uses the > parts of the language may never be full specified and so details may > differ wildly between implementations (and even versions of `rustc` > itself). -> +> > Furthermore, this is just an overview; the best form of > documentation for specific instances of these features are their > definitions and uses in `std`. @@ -584,8 +583,7 @@ fn main(_argc: int, _argv: **u8) -> int { ``` Note the use of `abort`: the `exchange_malloc` lang item is assumed to -return a valid pointer, and so needs to do the check -internally. +return a valid pointer, and so needs to do the check internally. Other features provided by lang items include: