about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/doc/trpl/SUMMARY.md2
-rw-r--r--src/doc/trpl/raw-pointers.md122
-rw-r--r--src/doc/trpl/unsafe-code.md101
3 files changed, 124 insertions, 101 deletions
diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md
index ec886899e6f..a179f8fa55e 100644
--- a/src/doc/trpl/SUMMARY.md
+++ b/src/doc/trpl/SUMMARY.md
@@ -54,7 +54,7 @@
     * [Unsized Types](unsized-types.md)
     * [Deref coercions](deref-coercions.md)
     * [Macros](macros.md)
-    * [`unsafe` Code](unsafe-code.md)
+    * [Raw Pointers](raw-pointers.md)
 * [Nightly Rust](nightly-rust.md)
     * [Compiler Plugins](compiler-plugins.md)
     * [Inline Assembly](inline-assembly.md)
diff --git a/src/doc/trpl/raw-pointers.md b/src/doc/trpl/raw-pointers.md
new file mode 100644
index 00000000000..ab6ff18501e
--- /dev/null
+++ b/src/doc/trpl/raw-pointers.md
@@ -0,0 +1,122 @@
+% Raw Pointers
+
+Rust has a number of different smart pointer types in its standard library, but
+there are two types that are extra-special. Much of Rust’s safety comes from
+compile-time checks, but raw pointers don’t have such guarantees, and are
+[unsafe][unsafe] to use.
+
+`*const T` and `*mut T` are called ‘raw pointers’ in Rust. Sometimes, when
+writing certain kinds of libraries, you’ll need to get around Rust’s safety
+guarantees for some reason. In this case, you can use raw pointers to implement
+your library, while exposing a safe interface for your users. For example, `*`
+pointers are allowed to alias, allowing them to be used to write
+shared-ownership types, and even thread-safe shared memory types (the `Rc<T>`
+and `Arc<T>` types are both implemented entirely in Rust).
+
+Here are some things to remember about raw pointers that are different than
+other pointer types. They:
+
+- are not guaranteed to point to valid memory and are not even
+  guaranteed to be non-null (unlike both `Box` and `&`);
+- do not have any automatic clean-up, unlike `Box`, and so require
+  manual resource management;
+- are plain-old-data, that is, they don't move ownership, again unlike
+  `Box`, hence the Rust compiler cannot protect against bugs like
+  use-after-free;
+- lack any form of lifetimes, unlike `&`, and so the compiler cannot
+  reason about dangling pointers; and
+- have no guarantees about aliasing or mutability other than mutation
+  not being allowed directly through a `*const T`.
+
+# Basics
+
+Creating a raw pointer is perfectly safe:
+
+```rust
+let x = 5;
+let raw = &x as *const i32;
+
+let mut y = 10;
+let raw_mut = &mut y as *mut i32;
+```
+
+However, dereferencing one is not. This won’t work:
+
+```rust,ignore
+let x = 5;
+let raw = &x as *const i32;
+
+println!("raw points at {}", *raw);
+```
+
+It gives this error:
+
+```text
+error: dereference of unsafe pointer requires unsafe function or block [E0133]
+     println!("raw points at{}", *raw);
+                                 ^~~~
+```
+
+When you dereference a raw pointer, you’re taking responsibility that it’s not
+pointing somewhere that would be incorrect. As such, you need `unsafe`:
+
+```rust
+let x = 5;
+let raw = &x as *const i32;
+
+let points_at = unsafe { *raw };
+
+println!("raw points at {}", points_at);
+```
+
+For more operations on raw pointers, see [their API documentation][rawapi].
+
+[unsafe]: unsafe.html
+[rawapi]: ../std/primitive.pointer.html
+
+# FFI
+
+Raw pointers are useful for FFI: Rust’s `*const T` and `*mut T` are similar to
+C’s `const T*` and `T*`, respectfully. For more about this use, consult the
+[FFI chapter][ffi].
+
+[ffi]: ffi.md
+
+# References and raw pointers
+
+At runtime, a raw pointer `*` and a reference pointing to the same piece of
+data have an identical representation. In fact, an `&T` reference will
+implicitly coerce to an `*const T` raw pointer in safe code and similarly for
+the `mut` variants (both coercions can be performed explicitly with,
+respectively, `value as *const T` and `value as *mut T`).
+
+Going the opposite direction, from `*const` to a reference `&`, is not safe. A
+`&T` is always valid, and so, at a minimum, the raw pointer `*const T` has to
+point to a valid instance of type `T`. Furthermore, the resulting pointer must
+satisfy the aliasing and mutability laws of references. The compiler assumes
+these properties are true for any references, no matter how they are created,
+and so any conversion from raw pointers is asserting that they hold. The
+programmer *must* guarantee this.
+
+The recommended method for the conversion is
+
+```rust
+let i: u32 = 1;
+
+// explicit cast
+let p_imm: *const u32 = &i as *const u32;
+let mut m: u32 = 2;
+
+// implicit coercion
+let p_mut: *mut u32 = &mut m;
+
+unsafe {
+    let ref_imm: &u32 = &*p_imm;
+    let ref_mut: &mut u32 = &mut *p_mut;
+}
+```
+
+The `&*x` dereferencing style is preferred to using a `transmute`. The latter
+is far more powerful than necessary, and the more restricted operation is
+harder to use incorrectly; for example, it requires that `x` is a pointer
+(unlike `transmute`).
diff --git a/src/doc/trpl/unsafe-code.md b/src/doc/trpl/unsafe-code.md
index b641f2b104a..dd166034b54 100644
--- a/src/doc/trpl/unsafe-code.md
+++ b/src/doc/trpl/unsafe-code.md
@@ -1,82 +1,4 @@
-% Unsafe Code
-
-# 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.
-
-Rust provides an escape hatch in the form of the `unsafe { ... }`
-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)
-- calling a function via FFI ([covered by the FFI guide](ffi.html))
-- casting between types bitwise (`transmute`, aka "reinterpret cast")
-- [inline assembly](#inline-assembly)
-
-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
-code base; preferably by using the bare minimum `unsafe` blocks to
-build safe interfaces.
-
-> **Note**: the low-level details of the Rust language are still in
-> flux, and there is no guarantee of stability or backwards
-> compatibility. In particular, there may be changes that do not cause
-> compilation errors, but do cause semantic changes (such as invoking
-> undefined behaviour). As such, extreme care is required.
-
-# Pointers
-
-## References
-
-One of Rust's biggest features is memory safety.  This is achieved in
-part via [the ownership system](ownership.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 interfaces (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
-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 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.
-
-Using `unsafe` code to incorrectly circumvent and violate these
-restrictions is undefined behaviour. For example, the following
-creates two aliasing `&mut` pointers, and is invalid.
-
-```
-use std::mem;
-let mut x: u8 = 1;
-
-let ref_1: &mut u8 = &mut x;
-let ref_2: &mut u8 = unsafe { mem::transmute(&mut *ref_1) };
-
-// oops, ref_1 and ref_2 point to the same piece of data (x) and are
-// both usable
-*ref_1 = 10;
-*ref_2 = 20;
-```
-
-## Raw pointers
+% Raw Pointers
 
 Rust offers two additional pointer types (*raw pointers*), written as
 `*const T` and `*mut T`. They're an approximation of C's `const T*` and `T*`
@@ -160,24 +82,3 @@ The `&*x` dereferencing style is preferred to using a `transmute`.
 The latter is far more powerful than necessary, and the more
 restricted operation is harder to use incorrectly; for example, it
 requires that `x` is a pointer (unlike `transmute`).
-
-
-
-## Making the unsafe safe(r)
-
-There are various ways to expose a safe interface around some unsafe
-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: 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
-  that clean-up is always run, even when the thread panics.
-- ensure that any data stored behind a raw pointer is destroyed at the
-  appropriate time.