From 89df25f400844092e2f667f954e84f839e3731bc Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 8 Jun 2015 09:37:34 -0700 Subject: [PATCH 001/104] first commit --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000000..4227beb19de1 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# turpl From cc5b4d314cef29aa94c5ab508f13726d934ba142 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 8 Jun 2015 09:41:58 -0700 Subject: [PATCH 002/104] add md files --- lifetimes.md | 13 ++++ raii.md | 179 +++++++++++++++++++++++++++++++++++++++++++++++ uninitialized.md | 179 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 371 insertions(+) create mode 100644 lifetimes.md create mode 100644 raii.md create mode 100644 uninitialized.md diff --git a/lifetimes.md b/lifetimes.md new file mode 100644 index 000000000000..5730192b6a3f --- /dev/null +++ b/lifetimes.md @@ -0,0 +1,13 @@ +% Advanced Lifetimes + +Lifetimes are the breakout feature of Rust. + +# Safe Rust + +* no aliasing of &mut + +# Unsafe Rust + +* Splitting lifetimes into disjoint regions +* Creating lifetimes from raw pointers +* \ No newline at end of file diff --git a/raii.md b/raii.md new file mode 100644 index 000000000000..13a2bdf8fff7 --- /dev/null +++ b/raii.md @@ -0,0 +1,179 @@ +% The Perils Of RAII + +Ownership Based Resource Management (AKA RAII: Resource Acquisition is Initialization) is +something you'll interact with a lot in Rust. Especially if you use the standard library. + +Roughly speaking the pattern is as follows: to acquire a resource, you create an object that +manages it. To release the resource, you simply destroy the object, and it cleans up the +resource for you. The most common "resource" +this pattern manages is simply *memory*. `Box`, `Rc`, and basically everything in +`std::collections` is a convenience to enable correctly managing memory. This is particularly +important in Rust because we have no pervasive GC to rely on for memory management. Which is the +point, really: Rust is about control. However we are not limited to just memory. +Pretty much every other system resource like a thread, file, or socket is exposed through +this kind of API. + +So, how does RAII work in Rust? Unlike C++, Rust does not come with a slew on builtin +kinds of constructor. There are no Copy, Default, Assignment, Move, or whatever constructors. +This largely has to do with Rust's philosophy of being explicit. + +Move constructors are meaningless in Rust because we don't enable types to "care" about their +location in memory. Every type must be ready for it to be blindly memcopied to somewhere else +in memory. This means pure on-the-stack-but-still-movable intrusive linked lists are simply +not happening in Rust (safely). + +Assignment and copy constructors similarly don't exist because move semantics are the *default* +in rust. At most `x = y` just moves the bits of y into the x variable. Rust does provide two +facilities for going back to C++'s copy-oriented semantics: `Copy` and `Clone`. Clone is our +moral equivalent of copy constructor, but it's never implicitly invoked. You have to explicitly +call `clone` on an element you want to be cloned. Copy is a special case of Clone where the +implementation is just "duplicate the bitwise representation". Copy types *are* implicitely +cloned whenever they're moved, but because of the definition of Copy this just means *not* +treating the old copy as uninitialized; a no-op. + +While Rust provides a `Default` trait for specifying the moral equivalent of a default +constructor, it's incredibly rare for this trait to be used. This is because variables +aren't implicitely initialized (see [working with uninitialized memory][uninit] for details). +Default is basically only useful for generic programming. + +More often than not, in a concrete case a type will provide a static `new` method for any +kind of "default" constructor. This has no relation to `new` in other languages and has no +special meaning. It's just a naming convention. + +What the language *does* provide is full-blown automatic destructors through the `Drop` trait, +which provides the following method: + +```rust +fn drop(&mut self); +``` + +This method gives the type time to somehow finish what it was doing. **After `drop` is run, +Rust will recursively try to drop all of the fields of the `self` struct**. This is a +convenience feature so that you don't have to write "destructor boilerplate" dropping +children. **There is no way to prevent this in Rust 1.0**. Also note that `&mut self` means +that even if you *could* supress recursive Drop, Rust will prevent you from e.g. moving fields +out of self. For most types, this is totally fine: they own all their data, there's no +additional state passed into drop to try to send it to, and `self` is about to be marked as +uninitialized (and therefore inaccessible). + +For instance, a custom implementation of `Box` might write `Drop` like this: + +```rust +struct Box{ ptr: *mut T } + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + (*self.ptr).drop(); + heap::deallocate(self.ptr); + } + } +} +``` + +and this works fine because when Rust goes to drop the `ptr` field it just sees a *mut that +has no actual `Drop` implementation. Similarly nothing can use-after-free the `ptr` because +the Box is completely gone. + +However this wouldn't work: + +```rust +struct Box{ ptr: *mut T } + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + (*self.ptr).drop(); + heap::deallocate(self.ptr); + } + } +} + +struct SuperBox { box: Box } + +impl Drop for SuperBox { + fn drop(&mut self) { + unsafe { + // Hyper-optimized: deallocate the box's contents for it + // without `drop`ing the contents + heap::deallocate(self.box.ptr); + } + } +} +``` + +because after we deallocate the `box`'s ptr in SuperBox's destructor, Rust will +happily proceed to tell the box to Drop itself and everything will blow up with +use-after-frees and double-frees. + +Note that the recursive drop behaviour applies to *all* structs and enums +regardless of whether they implement Drop. Therefore something like + +```rust +struct Boxy { + data1: Box, + data2: Box, + info: u32, +} +``` + +will have its data1 and data2's fields destructors whenever it "would" be +dropped, even though it itself doesn't implement Drop. We say that such a type +*needs Drop*, even though it is not itself Drop. + +Similarly, + +```rust +enum Link { + Next(Box), + None, +} +``` + +will have its inner Box field dropped *if and only if* a value stores the Next variant. + +In general this works really nice because you don't need to worry about adding/removing +dtors when you refactor your data layout. Still there's certainly many valid usecases for +needing to do trickier things with destructors. + +The classic safe solution to blocking recursive drop semantics and allowing moving out +of Self is to use an Option: + +```rust +struct Box{ ptr: *mut T } + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + (*self.ptr).drop(); + heap::deallocate(self.ptr); + } + } +} + +struct SuperBox { box: Option> } + +impl Drop for SuperBox { + fn drop(&mut self) { + unsafe { + // Hyper-optimized: deallocate the box's contents for it + // without `drop`ing the contents. Need to set the `box` + // fields as `None` to prevent Rust from trying to Drop it. + heap::deallocate(self.box.take().unwrap().ptr); + } + } +} +``` + +However this has fairly odd semantics: you're saying that a field that *should* always be Some +may be None, just because that happens in the dtor. Of course this conversely makes a lot of sense: +you can call arbitrary methods on self during the destructor, and this should prevent you from +ever doing so after deinitializing the field. Not that it will prevent you from producing any other +arbitrarily invalid state in there. + +On balance this is an ok choice. Certainly if you're just getting started. + +In the future, we expect there to be a first-class way to announce that a field +should be automatically dropped. + +[uninit]: \ No newline at end of file diff --git a/uninitialized.md b/uninitialized.md new file mode 100644 index 000000000000..89d0a93f6385 --- /dev/null +++ b/uninitialized.md @@ -0,0 +1,179 @@ +% Working With Uninitialized Memory + +All runtime-allocated memory in a Rust program begins its life as *uninitialized*. In this state the value of the memory is an indeterminate pile of bits that may or may not even reflect a valid state for the type that is supposed to inhabit that location of memory. Attempting to interpret this memory as a value of *any* type will cause Undefined Behaviour. Do Not Do This. + +Like C, all stack variables in Rust begin their life as uninitialized until a value is explicitly assigned to them. Unlike C, Rust statically prevents you from ever reading them until you do: + +```rust +fn main() { + let x: i32; + println!("{}", x); +} +``` + +```text +src/main.rs:3:20: 3:21 error: use of possibly uninitialized variable: `x` +src/main.rs:3 println!("{}", x); + ^ +``` + +This is based off of a basic branch analysis: every branch must assign a value to `x` before it +is first used. Interestingly, Rust doesn't require the variable to be mutable to perform a delayed initialization if every branch assigns exactly once. However the analysis does not take advantage of constant analysis or anything like that. So this compiles: + +```rust +fn main() { + let x: i32; + let y: i32; + + y = 1; + + if true { + x = 1; + } else { + x = 2; + } + + println!("{} {}", x, y); +} +``` + +but this doesn't: + +```rust +fn main() { + let x: i32; + if true { + x = 1; + } + println!("{}", x); +} +``` + +```text +src/main.rs:6:17: 6:18 error: use of possibly uninitialized variable: `x` +src/main.rs:6 println!("{}", x); +``` + +while this does: + +```rust +fn main() { + let x: i32; + if true { + x = 1; + println!("{}", x); + } + // Don't care that there are branches where it's not initialized + // since we don't use the value in those branches +} +``` + +If a value is moved out of a variable, that variable becomes logically uninitialized if the type +of the value isn't Copy. That is: + +```rust +fn main() { + let x = 0; + let y = Box::new(0); + let z1 = x; // x is still valid because i32 is Copy + let z2 = y; // y has once more become logically uninitialized, since Box is not Copy +} +``` + +However reassigning `y` in this example *would* require `y` to be marked as mutable, as a +Safe Rust program could observe that the value of `y` changed. Otherwise the variable is +exactly like new. + +This raises an interesting question with respect to `Drop`: where does Rust +try to call the destructor of a variable that is conditionally initialized? +It turns out that Rust actually tracks whether a type should be dropped or not *at runtime*. As a +variable becomes initialized and uninitialized, a *drop flag* for that variable is set and unset. +When a variable goes out of scope or is assigned it evaluates whether the current value of the +variable should be dropped. Of course, static analysis can remove these checks. If the compiler +can prove that a value is guaranteed to be either initialized or not, then it can theoretically +generate more efficient code! As such it may be desirable to structure code to have *static drop +semantics* when possible. + +As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a secret field of any type +that implements Drop. The language sets the drop flag by overwriting the entire struct with a +particular value. This is pretty obviously Not The Fastest and causes a bunch of trouble with +optimizing code. As such work is currently under way to move the flags out onto the stack frame +where they more reasonably belong. Unfortunately this work will take some time as it requires +fairly substantial changes to the compiler. + +So in general, Rust programs don't need to worry about uninitialized values on the stack for +correctness. Although they might care for performance. Thankfully, Rust makes it easy to take +control here! Uninitialized values are there, and Safe Rust lets you work with them, but you're +never in trouble. + +One interesting exception to this rule is working with arrays. Safe Rust doesn't permit you to +partially initialize an array. When you initialize an array, you can either set every value to the +same thing with `let x = [val; N]`, or you can specify each member individually with +`let x = [val1, val2, val3]`. Unfortunately this is pretty rigid, especially if you need +to initialize your array in a more incremental or dynamic way. + +Unsafe Rust gives us a powerful tool to handle this problem: `std::mem::uninitialized`. +This function pretends to return a value when really it does nothing at all. Using it, we can +convince Rust that we have initialized a variable, allowing us to do trickier things with +conditional and incremental initialization. + +Unfortunately, this raises a tricky problem. Assignment has a different meaning to Rust based on +whether it believes that a variable is initialized or not. If it's uninitialized, then Rust will +semantically just memcopy the bits over the uninit ones, and do nothing else. However if Rust +believes a value to be initialized, it will try to `Drop` the old value! Since we've tricked Rust +into believing that the value is initialized, we can no longer safely use normal assignment. + +This is also a problem if you're working with a raw system allocator, which of course returns a +pointer to uninitialized memory. + +To handle this, we must use the `std::ptr` module. In particular, it provides three functions that +allow us to assign bytes to a location in memory without evaluating the old value: `write`, `copy`, and `copy_nonoverlapping`. + +* `ptr::write(ptr, val)` takes a `val` and moves it into the address pointed to by `ptr`. +* `ptr::copy(src, dest, count)` copies the bits that `count` T's would occupy from src to dest. (this is equivalent to memmove -- note that the argument order is reversed!) +* `ptr::copy_nonoverlapping(src, dest, count)` does what `copy` does, but a little faster on the +assumption that the two ranges of memory don't overlap. (this is equivalent to memcopy -- note that the argument order is reversed!) + +It should go without saying that these functions, if misused, will cause serious havoc or just +straight up Undefined Behaviour. The only things that these functions *themselves* require is that +the locations you want to read and write are allocated. However the ways writing arbitrary bit +patterns to arbitrary locations of memory can break things are basically uncountable! + +Putting this all together, we get the following: + +```rust +fn main() { + use std::mem; + + // size of the array is hard-coded but easy to change. This means we can't + // use [a, b, c] syntax to initialize the array, though! + const SIZE = 10; + + let x: [Box; SIZE]; + + unsafe { + // convince Rust that x is Totally Initialized + x = mem::uninitialized(); + for i in 0..SIZE { + // very carefully overwrite each index without reading it + ptr::write(&mut x[i], Box::new(i)); + } + } + + println!("{}", x); +} +``` + +It's worth noting that you don't need to worry about ptr::write-style shenanigans with +Plain Old Data (POD; types which don't implement Drop, nor contain Drop types), +because Rust knows not to try to Drop them. Similarly you should be able to assign the POD +fields of partially initialized structs directly. + +However when working with uninitialized memory you need to be ever vigilant for Rust trying to +Drop values you make like this before they're fully initialized. So every control path through +that variable's scope must initialize the value before it ends. *This includes code panicking*. +Again, POD types need not worry. + +And that's about it for working with uninitialized memory! Basically nothing anywhere expects +to be handed uninitialized memory, so if you're going to pass it around at all, be sure to be +*really* careful. From f2a37fce151c2eeef1edea7001c34b2588e80f5c Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 8 Jun 2015 09:57:05 -0700 Subject: [PATCH 003/104] blurp --- .gitignore | 1 + conversions.md | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 .gitignore create mode 100644 conversions.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..0b84df0f0253 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.html \ No newline at end of file diff --git a/conversions.md b/conversions.md new file mode 100644 index 000000000000..b4bde01f5ae7 --- /dev/null +++ b/conversions.md @@ -0,0 +1,12 @@ +% Type Conversions + +# Safe Rust + +* Coercions +* Casts +* Conversion Traits (Into/As/...) + +# Unsafe Rust + +* raw ptr casts +* mem::transmute From 39c047317f39df2b0f55da10f276b88826f54d3b Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 10 Jun 2015 13:57:00 -0700 Subject: [PATCH 004/104] progress --- conversions.md | 70 ++++++++++++++ data.md | 254 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 324 insertions(+) create mode 100644 data.md diff --git a/conversions.md b/conversions.md index b4bde01f5ae7..2fd750bb6649 100644 --- a/conversions.md +++ b/conversions.md @@ -1,7 +1,77 @@ % Type Conversions +At the end of the day, everything is just a pile of bits somewhere, and type systems +are just there to help us use those bits right. Needing to reinterpret those piles +of bits as different types is a common problem and Rust consequently gives you +several ways to do that. + # Safe Rust +First we'll look at the ways that *Safe Rust* gives you to reinterpret values. The +most trivial way to do this is to just destructure a value into its constituent +parts and then build a new type out of them. e.g. + +```rust +struct Foo { + x: u32, + y: u16, +} + +struct Bar { + a: u32, + b: u16, +} + +fn reinterpret(foo: Foo) -> Bar { + let Foo { x, y } = foo; + Bar { a: x, b: y } +} +``` + +But this is, at best, annoying to do. For common conversions, rust provides +more ergonomic alternatives. + +## Auto-Deref + +Deref is a trait that allows you to overload the unary `*` to specify a type +you dereference to. This is largely only intended to be implemented by pointer +types like `&`, `Box`, and `Rc`. The dot operator will automatically perform +automatic dereferencing, so that foo.bar() will work uniformly on `Foo`, `&Foo`, `&&Foo`, +`&Rc>>` and so-on. Search bottoms out on the *first* match, +so implementing methods on pointers is generally to be avoided, as it will shadow +"actual" methods. + +## Coercions + +Types can implicitly be coerced to change in certain contexts. These changes are generally +just *weakening* of types, largely focused around pointers. They mostly exist to make +Rust "just work" in more cases. For instance +`&mut T` coerces to `&T`, and `&T` coerces to `*const T`. The most useful coercion you will +actually think about it is probably the general *Deref Coercion*: `&T` coerces to `&U` when +`T: Deref`. This enables us to pass an `&String` where an `&str` is expected, for instance. + +## Casts + +Casts are a superset of coercions: every coercion can be explicitly invoked via a cast, +but some changes require a cast. These "true casts" are generally regarded as dangerous or +problematic actions. The set of true casts is actually quite small, and once again revolves +largely around pointers. However it also introduces the primary mechanism to convert between +numeric types. + +* rawptr -> rawptr (e.g. `*mut T as *const T` or `*mut T as *mut U`) +* rawptr <-> usize (e.g. `*mut T as usize` or `usize as *mut T`) +* primitive -> primitive (e.g. `u32 as u8` or `u8 as u32`) +* c-like enum -> integer/bool (e.g. `DaysOfWeek as u8`) +* `u8` -> `char` + + +## Conversion Traits + +For full formal specification of all the kinds of coercions and coercion sites, see: +https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md + + + * Coercions * Casts * Conversion Traits (Into/As/...) diff --git a/data.md b/data.md new file mode 100644 index 000000000000..6fa63568862c --- /dev/null +++ b/data.md @@ -0,0 +1,254 @@ +% Data Representation in Rust + +Low-level programming cares a lot about data layout. It's a big deal. It also pervasively +influences the rest of the language, so we're going to start by digging into how data is +represented in Rust. + +# The `rust` repr + +Rust gives you the following ways to lay out composite data: + +* structs (named product types) +* tuples (anonymous product types) +* arrays (homogeneous product types) +* enums (named sum types -- tagged unions) + +For all these, individual fields are aligned to their preferred alignment. +For primitives this is equal to +their size. For instance, a u32 will be aligned to a multiple of 32 bits, and a u16 will +be aligned to a multiple of 16 bits. Composite structures will have their size rounded +up to be a multiple of the highest alignment required by their fields, and an alignment +requirement equal to the highest alignment required by their fields. So for instance, + +```rust +struct A { + a: u8, + c: u64, + b: u32, +} +``` + +will have a size that is a multiple of 64-bits, and 64-bit alignment. + +There is *no indirection* for these types; all data is stored contiguously as you would +expect in C. However with the exception of arrays, the layout of data is not by +default specified in Rust. Given the two following struct definitions: + +```rust +struct A { + a: i32, + b: u64, +} + +struct B { + x: i32, + b: u64, +} +``` + +Rust *does* guarantee that two instances of A have their data laid out in exactly +the same way. However Rust *does not* guarantee that an instance of A has the same +field ordering or padding as an instance of B (in practice there's no *particular* +reason why they wouldn't, other than that its not currently guaranteed). + +With A and B as written, this is basically nonsensical, but several other features +of Rust make it desirable for the language to play with data layout in complex ways. + +For instance, consider this struct: + +```rust +struct Foo { + count: u16, + data1: T, + data2: U, +} +``` + +Now consider the monomorphizations of `Foo` and `Foo`. If Rust lays out the +fields in the order specified, we expect it to *pad* the values in the struct to satisfy +their *alignment* requirements. So if Rust didn't reorder fields, we would expect Rust to +produce the following: + +```rust +struct Foo { + count: u16, + data1: u16, + data2: u32, +} + +struct Foo { + count: u16, + _pad1: u16, + data1: u32, + data2: u16, + _pad2: u16, +} +``` + +The former case quite simply wastes space. An optimal use of space therefore requires +different monomorphizations to *have different field orderings*. + +**Note: this is a hypothetical optimization that is not yet implemented in Rust 1.0.0** + +Enums make this consideration even more complicated. Naively, an enum such as: + +```rust +enum Foo { + A(u32), + B(u64), + C(u8), +} +``` + +would be laid out as: + +```rust +struct FooRepr { + data: u64, // this is *really* either a u64, u32, or u8 based on `tag` + tag: u8, // 0 = A, 1 = B, 2 = C +} +``` + +And indeed this is approximately how it would be laid out in general +(modulo the size and position of `tag`). However there are several cases where +such a representation is ineffiecient. The classic case of this is Rust's +"null pointer optimization". Given a pointer that is known to not be null +(e.g. `&u32`), an enum can *store* a discriminant bit *inside* the pointer +by using null as a special value. The net result is that +`sizeof(Option<&T>) == sizeof<&T>` + +There are many types in Rust that are, or contain, "not null" pointers such as `Box`, `Vec`, +`String`, `&T`, and `&mut T`. Similarly, one can imagine nested enums pooling their tags into +a single descriminant, as they are by definition known to have a limited range of valid values. +In principle enums can use fairly elaborate algorithms to cache bits throughout nested types +with special constrained representations. As such it is *especially* desirable that we leave +enum layout unspecified today. + +# Dynamically Sized Types (DSTs) + +Rust also supports types without a statically known size. On the surface, +this is a bit nonsensical: Rust must know the size of something in order to +work with it. DSTs are generally produced as views, or through type-erasure +of types that *do* have a known size. Due to their lack of a statically known +size, these types can only exist *behind* some kind of pointer. They consequently +produce a *fat* pointer consisting of the pointer and the information that +*completes* them. + +For instance, the slice type, `[T]`, is some statically unknown number of elements +stored contiguously. `&[T]` consequently consists of a `(&T, usize)` pair that specifies +where the slice starts, and how many elements it contains. Similarly Trait Objects +support interface-oriented type erasure through a `(data_ptr, vtable_ptr)` pair. + +Structs can actually store a single DST directly as their last field, but this +makes them a DST as well: + +```rust +// Can't be stored on the stack directly +struct Foo { + info: u32, + data: [u8], +} +``` + +# Zero Sized Types (ZSTs) + +Rust actually allows types to be specified that occupy *no* space: + +```rust +struct Foo; // No fields = no size +enum Bar; // No variants = no size + +// All fields have no size = no size +struct Baz { + foo: Foo, + bar: Bar, + qux: (), // empty tuple has no size +} +``` + +On their own, ZSTs are, for obvious reasons, pretty useless. However +as with many curious layout choices in Rust, their potential is realized in a generic +context. + +Rust largely understands that any operation that produces or stores a ZST +can be reduced to a no-op. For instance, a `HashSet` can be effeciently implemented +as a thin wrapper around `HashMap` because all the operations `HashMap` normally +does to store and retrieve keys will be completely stripped in monomorphization. + +Similarly `Result<(), ()>` and `Option<()>` are effectively just fancy `bool`s. + +Safe code need not worry about ZSTs, but *unsafe* code must be careful about the +consequence of types with no size. In particular, pointer offsets are no-ops, and +standard allocators (including jemalloc, the one used by Rust) generally consider +passing in `0` as Undefined Behaviour. + +# Drop Flags + +For unfortunate legacy implementation reasons, Rust as of 1.0.0 will do a nasty trick to +any type that implements the `Drop` trait (has a destructor): it will insert a secret field +in the type. That is, + +```rust +struct Foo { + a: u32, + b: u32, +} + +impl Drop for Foo { + fn drop(&mut self) { } +} +``` + +will cause Foo to secretly become: + +```rust +struct Foo { + a: u32, + b: u32, + _drop_flag: u8, +} +``` + +For details as to *why* this is done, and how to make it not happen, check out +[SOME OTHER SECTION]. + +# Alternative representations + +Rust allows you to specify alternative data layout strategies from the default Rust +one. + +# repr(C) + +This is the most important `repr`. It has fairly simple intent: do what C does. +The order, size, and alignment of fields is exactly what you would expect from +C or C++. Any type you expect to pass through an FFI boundary should have `repr(C)`, +as C is the lingua-franca of the programming world. However this is also necessary +to soundly do more elaborate tricks with data layout such as reintepretting values +as a different type. + +However, the interaction with Rust's more exotic data layout features must be kept +in mind. Due to its dual purpose as a "for FFI" and "for layout control", repr(C) +can be applied to types that will be nonsensical or problematic if passed through +the FFI boundary. + +* ZSTs are still zero-sized, even though this is not a standard behaviour +in C, and is explicitly contrary to the behaviour of an empty type in C++, which +still consumes a byte of space. + +* DSTs are not a concept in C + +* **The drop flag will still be added** + +* This is equivalent to repr(u32) for enums (see below) + +# repr(packed) + +`repr(packed)` forces rust to strip any padding it would normally apply. +This may improve the memory footprint of a type, but will have negative +side-effects from "field access is heavily penalized" to "completely breaks +everything" based on target platform. + +# repr(u8), repr(u16), repr(u32), repr(u64) + +These specify the size to make a c-like enum (one which has no values in its variants). + From 3318e3d8edd4336021f4314a25618e77061f2684 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 10 Jun 2015 14:08:03 -0700 Subject: [PATCH 005/104] progress --- conversions.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/conversions.md b/conversions.md index 2fd750bb6649..753a01416aab 100644 --- a/conversions.md +++ b/conversions.md @@ -54,15 +54,27 @@ actually think about it is probably the general *Deref Coercion*: `&T` coerces t Casts are a superset of coercions: every coercion can be explicitly invoked via a cast, but some changes require a cast. These "true casts" are generally regarded as dangerous or -problematic actions. The set of true casts is actually quite small, and once again revolves -largely around pointers. However it also introduces the primary mechanism to convert between -numeric types. +problematic actions. True casts revolves around raw pointers and the primitive numeric +types. Here's an exhaustive list of all the true casts: * rawptr -> rawptr (e.g. `*mut T as *const T` or `*mut T as *mut U`) * rawptr <-> usize (e.g. `*mut T as usize` or `usize as *mut T`) -* primitive -> primitive (e.g. `u32 as u8` or `u8 as u32`) -* c-like enum -> integer/bool (e.g. `DaysOfWeek as u8`) +* number -> number (e.g. `u32 as i8` or `i16 as f64`) +* c-like enum -> integer/bool (e.g. `DaysOfWeek as u32`) * `u8` -> `char` +* something about arrays? + +For number -> number casts, there are quite a few cases to consider: + +* unsigned to bigger unsigned will zero-extend losslessly +* unsigned to smaller unsigned will truncate via wrapping +* signed to unsigned will ... TODO rest of this list + +The casts involving rawptrs also allow us to completely bypass type-safety +by re-interpretting a pointer of T to a pointer of U for arbitrary types, as +well as interpret integers as addresses. However it is impossible to actually +*capitalize* on this violation in Safe Rust, because derefencing a raw ptr is +`unsafe`. ## Conversion Traits From f8be0737ea47a41097bba940ce5f9f9527fb2087 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 18 Jun 2015 21:04:48 -0700 Subject: [PATCH 006/104] progress --- concurrency.md | 186 +++++++++++++++++++ conversions.md | 39 ++-- intro.md | 151 ++++++++++++++++ lifetimes.md | 470 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 823 insertions(+), 23 deletions(-) create mode 100644 concurrency.md create mode 100644 intro.md diff --git a/concurrency.md b/concurrency.md new file mode 100644 index 000000000000..c600644ba63e --- /dev/null +++ b/concurrency.md @@ -0,0 +1,186 @@ +% Concurrency and Paralellism + +```Not sure if I want this +Safe Rust features *a ton* of tooling to make concurrency and parallelism totally +safe, easy, and fearless. This is a case where we'll really just +[defer to TRPL][trpl-conc] for the basics. + +TL;DR: The `Send` and `Sync` traits in conjunction with Rust's ownership model and +normal generic bounds make using concurrent APIs really easy and painless for +a user of Safe Rust. +``` + +## Data Races and Race Conditions + +Safe Rust guarantees an absence of data races, which are defined as: + +* two or more threads concurrently accessing a location of memory +* one of them is a write +* one of them is unsynchronized + +A data race has Undefined Behaviour, and is therefore impossible to perform +in Safe Rust. Data races are *mostly* prevented through rust's ownership system: +it's impossible to alias a mutable reference, so it's impossible to perform a +data race. Interior mutability makes this more complicated, which is largely why +we have the Send and Sync traits (see below). + +However Rust *does not* prevent general race conditions. This is +pretty fundamentally impossible, and probably honestly undesirable. Your hardware +is racy, your OS is racy, the other programs on your computer are racy, and the +world this all runs in is racy. Any system that could genuinely claim to prevent +*all* race conditions would be pretty awful to use, if not just incorrect. + +So it's perfectly "fine" for a Safe Rust program to get deadlocked or do +something incredibly stupid with incorrect synchronization. Obviously such a +program isn't very good, but Rust can only hold your hand so far. Still, a +race condition can't violate memory safety in a Rust program on +its own. Only in conjunction with some other unsafe code can a race condition +actually violate memory safety. For instance: + +```rust +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; + +let data = vec![1, 2, 3, 4]; +// Arc so that the memory the AtomicUsize is stored in still exists for +// the other thread to increment, even if we completely finish executing +// before it. Rust won't compile the program without it, because of the +// lifetime requirements of thread::spawn! +let idx = Arc::new(AtomicUsize::new(0)); +let other_idx = idx.clone(); + +// `move` captures other_idx by-value, moving it into this thread +thread::spawn(move || { + // It's ok to mutate idx because this value + // is an atomic, so it can't cause a Data Race. + other_idx.fetch_add(10, Ordering::SeqCst); +}); + +// Index with the value loaded from the atomic. This is safe because we +// read the atomic memory only once, and then pass a *copy* of that value +// to the Vec's indexing implementation. This indexing will be correctly +// bounds checked, and there's no chance of the value getting changed +// in the middle. However our program may panic if the thread we spawned +// managed to increment before this ran. A race condition because correct +// program execution (panicing is rarely correct) depends on order of +// thread execution. +println!("{}", data[idx.load(Ordering::SeqCst)]); + +if idx.load(Ordering::SeqCst) < data.len() { + unsafe { + // Incorrectly loading the idx *after* we did the bounds check. + // It could have changed. This is a race condition, *and dangerous* + // because we decided to do `get_unchecked`, which is `unsafe`. + println!("{}", data.get_unchecked(idx.load(Ordering::SeqCst))); + } +} +``` + +## Send and Sync + +Not everything obeys inherited mutability, though. Some types allow you to multiply +alias a location in memory while mutating it. Unless these types use synchronization +to manage this access, they are absolutely not thread safe. Rust captures this with +through the `Send` and `Sync` traits. + +* A type is Send if it is safe to send it to another thread. +* A type is Sync if it is safe to share between threads (`&T` is Send). + +Send and Sync are *very* fundamental to Rust's concurrency story. As such, a +substantial amount of special tooling exists to make them work right. First and +foremost, they're *unsafe traits*. This means that they are unsafe *to implement*, +and other unsafe code can *trust* that they are correctly implemented. Since +they're *marker traits* (they have no associated items like methods), correctly +implemented simply means that they have the intrinsic properties an implementor +should have. Incorrectly implementing Send or Sync can cause Undefined Behaviour. + +Send and Sync are also what Rust calls *opt-in builtin traits*. +This means that, unlike every other trait, they are *automatically* derived: +if a type is composed entirely of Send or Sync types, then it is Send or Sync. +Almost all primitives are Send and Sync, and as a consequence pretty much +all types you'll ever interact with are Send and Sync. + +Major exceptions include: +* raw pointers are neither Send nor Sync (because they have no safety guards) +* `UnsafeCell` isn't Sync (and therefore `Cell` and `RefCell` aren't) +* `Rc` isn't Send or Sync (because the refcount is shared and unsynchronized) + +`Rc` and `UnsafeCell` are very fundamentally not thread-safe: they enable +unsynchronized shared mutable state. However raw pointers are, strictly speaking, +marked as thread-unsafe as more of a *lint*. Doing anything useful +with a raw pointer requires dereferencing it, which is already unsafe. In that +sense, one could argue that it would be "fine" for them to be marked as thread safe. + +However it's important that they aren't thread safe to prevent types that +*contain them* from being automatically marked as thread safe. These types have +non-trivial untracked ownership, and it's unlikely that their author was +necessarily thinking hard about thread safety. In the case of Rc, we have a nice +example of a type that contains a `*mut` that is *definitely* not thread safe. + +Types that aren't automatically derived can *opt-in* to Send and Sync by simply +implementing them: + +```rust +struct MyBox(*mut u8); + +unsafe impl Send for MyBox {} +unsafe impl Sync for MyBox {} +``` + +In the *incredibly rare* case that a type is *inappropriately* automatically +derived to be Send or Sync, then one can also *unimplement* Send and Sync: + +```rust +struct SpecialThreadToken(u8); + +impl !Send for SpecialThreadToken {} +impl !Sync for SpecialThreadToken {} +``` + +Note that *in and of itself* it is impossible to incorrectly derive Send and Sync. +Only types that are ascribed special meaning by other unsafe code can possible cause +trouble by being incorrectly Send or Sync. + +Most uses of raw pointers should be encapsulated behind a sufficient abstraction +that Send and Sync can be derived. For instance all of Rust's standard +collections are Send and Sync (when they contain Send and Sync types) +in spite of their pervasive use raw pointers to +manage allocations and complex ownership. Similarly, most iterators into these +collections are Send and Sync because they largely behave like an `&` or `&mut` +into the collection. + +TODO: better explain what can or can't be Send or Sync. Sufficient to appeal +only to data races? + +## Atomics + +Rust pretty blatantly just inherits LLVM's model for atomics, which in turn is +largely based off of the C11 model for atomics. This is not due these models +being particularly excellent or easy to understand. Indeed, these models are +quite complex and are known to have several flaws. Rather, it is a pragmatic +concession to the fact that *everyone* is pretty bad at modeling atomics. At very +least, we can benefit from existing tooling and research around C's model. + +Trying to fully explain these models is fairly hopeless, so we're just going to +drop that problem in LLVM's lap. + +## Actually Doing Things Concurrently + +Rust as a language doesn't *really* have an opinion on how to do concurrency or +parallelism. The standard library exposes OS threads and blocking sys-calls +because *everyone* has those and they're uniform enough that you can provide +an abstraction over them in a relatively uncontroversial way. Message passing, +green threads, and async APIs are all diverse enough that any abstraction over +them tends to involve trade-offs that we weren't willing to commit to for 1.0. + +However Rust's current design is setup so that you can set up your own +concurrent paradigm or library as you see fit. Just require the right +lifetimes and Send and Sync where appropriate and everything should Just Work +with everyone else's stuff. + + + + +[llvm-conc]: http://llvm.org/docs/Atomics.html +[trpl-conc]: https://doc.rust-lang.org/book/concurrency.html diff --git a/conversions.md b/conversions.md index 753a01416aab..4fe86284a31e 100644 --- a/conversions.md +++ b/conversions.md @@ -13,18 +13,18 @@ parts and then build a new type out of them. e.g. ```rust struct Foo { - x: u32, - y: u16, + x: u32, + y: u16, } struct Bar { - a: u32, - b: u16, + a: u32, + b: u16, } fn reinterpret(foo: Foo) -> Bar { - let Foo { x, y } = foo; - Bar { a: x, b: y } + let Foo { x, y } = foo; + Bar { a: x, b: y } } ``` @@ -57,18 +57,27 @@ but some changes require a cast. These "true casts" are generally regarded as da problematic actions. True casts revolves around raw pointers and the primitive numeric types. Here's an exhaustive list of all the true casts: -* rawptr -> rawptr (e.g. `*mut T as *const T` or `*mut T as *mut U`) -* rawptr <-> usize (e.g. `*mut T as usize` or `usize as *mut T`) -* number -> number (e.g. `u32 as i8` or `i16 as f64`) -* c-like enum -> integer/bool (e.g. `DaysOfWeek as u32`) -* `u8` -> `char` -* something about arrays? +TODO: gank the RFC for sweet casts For number -> number casts, there are quite a few cases to consider: -* unsigned to bigger unsigned will zero-extend losslessly -* unsigned to smaller unsigned will truncate via wrapping -* signed to unsigned will ... TODO rest of this list +* casting between two integers of the same size (e.g. i32 -> u32) is a no-op +* casting from a smaller integer to a bigger integer (e.g. u32 -> u8) will truncate +* casting from a larger integer to a smaller integer (e.g. u8 -> u32) will + * zero-extend if unsigned + * sign-extend if signed +* casting from a float to an integer will round the float towards zero. + * **NOTE: currently this will cause Undefined Behaviour if the rounded + value cannot be represented by the target integer type**. This is a bug + and will be fixed. +* casting from an integer to float will produce the floating point representation + of the integer, rounded if necessary (rounding strategy unspecified). +* casting from an f32 to an f64 is perfect and lossless. +* casting from an f64 to an f32 will produce the closest possible value + (rounding strategy unspecified). + * **NOTE: currently this will cause Undefined Behaviour if the value + is finite but larger or smaller than the largest or smallest finite + value representable by f32**. This is a bug and will be fixed. The casts involving rawptrs also allow us to completely bypass type-safety by re-interpretting a pointer of T to a pointer of U for arbitrary types, as diff --git a/intro.md b/intro.md new file mode 100644 index 000000000000..bc0f6483baa4 --- /dev/null +++ b/intro.md @@ -0,0 +1,151 @@ +% The Unsafe Rust Programming Language + +This document seeks to complement [The Rust Programming Language][] (TRPL). +Where TRPL introduces the language and teaches the basics, TURPL dives deep into +the specification of the language, and all the nasty bits necessary to write +Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know +the basics of the language and systems programming. We will not explain the +stack or heap, we will not explain the syntax. + +## A Tale Of Two Languages + +Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust. +Any time someone opines the guarantees of Rust, they are almost surely talking about +Safe Rust. However Safe Rust is not sufficient to write every program. For that, +we need the Unsafe Rust superset. + +Most fundamentally, writing bindings to other languages +(such as the C exposed by your operating system) is never going to be safe. Rust +can't control what other languages do to program execution! However Unsafe Rust is +also necessary to construct fundamental abstractions where the type system is not +sufficient to automatically prove what you're doing is sound. + +Indeed, the Rust standard library is implemented in Rust, and it makes substantial +use of Unsafe Rust for implementing IO, memory allocation, collections, +synchronization, and other low-level computational primitives. + +Upon hearing this, many wonder why they would not simply just use C or C++ in place of +Rust (or just use a "real" safe language). If we're going to do unsafe things, why not +lean on these much more established languages? + +The most important difference between C++ and Rust is a matter of defaults: +Rust is 100% safe by default. Even when you *opt out* of safety in Rust, it is a modular +action. In deciding to work with unchecked uninitialized memory, this does not +suddenly make dangling or null pointers a problem. When using unchecked indexing on `x`, +one does not have to suddenly worry about indexing out of bounds on `y`. + +C and C++, by contrast, have pervasive unsafety baked into the language. Even the +modern best practices like `unique_ptr` have various safety pitfalls. + +It should also be noted that writing Unsafe Rust should be regarded as an exceptional +action. Unsafe Rust is often the domain of *fundamental libraries*. Anything that needs +to make FFI bindings or define core abstractions. These fundamental libraries then expose +a *safe* interface for intermediate libraries and applications to build upon. And these +safe interfaces make an important promise: if your application segfaults, it's not your +fault. *They* have a bug. + +And really, how is that different from *any* safe language? Python, Ruby, and Java libraries +can internally do all sorts of nasty things. The languages themselves are no +different. Safe languages regularly have bugs that cause critical vulnerabilities. +The fact that Rust is written with a healthy spoonful of Unsafe Rust is no different. +However it *does* mean that Rust doesn't need to fall back to the pervasive unsafety of +C to do the nasty things that need to get done. + +## What does `unsafe` mean? + +Rust tries to model memory safety through the `unsafe` keyword. Interestingly, +the meaning of `unsafe` largely revolves around what +its *absence* means. If the `unsafe` keyword is absent from a program, it should +not be possible to violate memory safety under *any* conditions. The presence +of `unsafe` means that there are conditions under which this code *could* +violate memory safety. + +To be more concrete, Rust cares about preventing the following things: + +* Dereferencing null/dangling pointers +* Reading uninitialized memory +* Breaking the pointer aliasing rules (TBD) (llvm rules + noalias on &mut and & w/o UnsafeCell) +* Invoking Undefined Behaviour (in e.g. compiler intrinsics) +* Producing invalid primitive values: + * dangling/null references + * a `bool` that isn't 0 or 1 + * an undefined `enum` discriminant + * a `char` larger than char::MAX + * A non-utf8 `str` +* Unwinding into an FFI function +* Causing a data race + +However libraries are free to declare arbitrary requirements if they could transitively +cause memory safety issues. However Rust is otherwise quite permisive with respect to +other dubious operations. Rust considers it "safe" to: + +* Deadlock +* Leak memory +* Fail to call destructors +* Access private fields +* Overflow integers +* Delete the production database + +However any program that does such a thing is *probably* incorrect. Rust just isn't +interested in modeling these problems, as they are much harder to prevent in general, +and it's basically impossible to prevent incorrect programs from getting written. + +Their are several places `unsafe` can appear in Rust today, which can largely be +grouped into two categories: + +* There are unchecked contracts here. To declare you understand this, I require +you to write `unsafe` elsewhere: + * On functions, `unsafe` is declaring the function to be unsafe to call. Users + of the function must check the documentation to determine what this means, + and then have to write `unsafe` somewhere to identify that they're aware of + the danger. + * On trait declarations, `unsafe` is declaring that *implementing* the trait + is an unsafe operation, as it has contracts that other unsafe code is free to + trust blindly. + +* I am declaring that I have, to the best of my knowledge, adhered to the +unchecked contracts: + * On trait implementations, `unsafe` is declaring that the contract of the + `unsafe` trait has been upheld. + * On blocks, `unsafe` is declaring any unsafety from an unsafe + operation to be handled, and therefore the parent function is safe. + +There is also `#[unsafe_no_drop_flag]`, which is a special case that exists for +historical reasons and is in the process of being phased out. See the section on +destructors for details. + +Some examples of unsafe functions: + +* `slice::get_unchecked` will perform unchecked indexing, allowing memory +safety to be freely violated. +* `ptr::offset` in an intrinsic that invokes Undefined Behaviour if it is +not "in bounds" as defined by LLVM (see the lifetimes section for details). +* `mem::transmute` reinterprets some value as having the given type, +bypassing type safety in arbitrary ways. (see the conversions section for details) +* All FFI functions are `unsafe` because they can do arbitrary things. +C being an obvious culprit, but generally any language can do something +that Rust isn't happy about. (see the FFI section for details) + +As of Rust 1.0 there are exactly two unsafe traits: + +* `Send` is a marker trait (it has no actual API) that promises implementors +are safe to send to another thread. +* `Sync` is a marker trait that promises that threads can safely share +implementors through a shared reference. + +All other traits that declare any kind of contract *really* can't be trusted +to adhere to their contract when memory-safety is at stake. For instance Rust has +`PartialOrd` and `Ord` to differentiate between types which can "just" be +compared and those that implement a total ordering. However you can't actually +trust an implementor of `Ord` to actually provide a total ordering if failing to +do so causes you to e.g. index out of bounds. But if it just makes your program +do a stupid thing, then it's "fine" to rely on `Ord`. + +The reason this is the case is that `Ord` is safe to implement, and it should be +impossible for bad *safe* code to violate memory safety. Rust has traditionally +avoided making traits unsafe because it makes `unsafe` pervasive in the language, +which is not desirable. The only reason `Send` and `Sync` are unsafe is because +thread safety is a sort of fundamental thing that a program can't really guard +against locally (even by-value message passing still requires a notion Send). + + diff --git a/lifetimes.md b/lifetimes.md index 5730192b6a3f..42304681c206 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -1,13 +1,467 @@ -% Advanced Lifetimes +% Ownership -Lifetimes are the breakout feature of Rust. +Ownership is the breakout feature of Rust. It allows Rust to be completely +memory-safe and efficient, while avoiding garbage collection. Before getting +into the ownership system in detail, we will consider a simple but *fundamental* +language-design problem. -# Safe Rust -* no aliasing of &mut -# Unsafe Rust +## The Tagged Union Problem + +The core of the lifetime and mutability system derives from a simple problem: +internal pointers to tagged unions. For instance, consider the following code: + +```rust +enum Foo { + A(u32), + B(f64), +} + +let mut x = B(2.0); +if let B(ref mut y) = x { + *x = A(7); + // OH NO! a u32 has been interpretted as an f64! Type-safety hole! + // (this does not actually compile) + println!("{}", y); + +} +``` + +The problem here is an intersection of 3 choices: + +* data in a tagged union is inline with the tag +* tagged unions are mutable +* being able to take a pointer into a tagged union + +Remove *any* of these 3 and the problem goes away. Traditionally, functional +languages have avoided this problem by removing the mutable +option. This means that they can in principle keep their data inline (ghc has +a pragma for this). A garbage collected imperative language like Java could alternatively +solve this problem by just keeping all variants elsewhere, so that changing the +variant of a tagged union just overwrites a pointer, and anyone with an outstanding +pointer to the inner data is unaffected thanks to The Magic Of Garbage Collection. + +Rust, by contrast, takes a subtler approach. Rust allows mutation, +allows pointers to inner data, and its enums have their data allocated inline. +However it prevents anything from being mutated while there are outstanding +pointers to it! And this is all done at compile time. + +Interestingly, Rust's `std::cell` module exposes two types that offer an alternative +approach to this problem: + +* The `Cell` type allows mutation of aliased data, but +instead forbids internal pointers to that data. The only way to read or write +a Cell is to copy the bits in or out. + +* The `RefCell` type allows mutation of aliased data *and* internal pointers, but +manages this through *runtime* checks. It is effectively a thread-unsafe +read-write lock. + + + +## Lifetimes + +Rust's static checks are managed by the *borrow checker* (borrowck), which tracks +mutability and outstanding loans. This analysis can in principle be done without +any help locally. However as soon as data starts crossing the function boundary, +we have some serious trouble. In principle, borrowck could be a massive +whole-program analysis engine to handle this problem, but this would be an +atrocious solution. It would be terribly slow, and errors would be horribly +non-local. + +Instead, Rust tracks ownership through *lifetimes*. Every single reference and value +in Rust is tagged with a lifetime that indicates the scope it is valid for. +Rust has two kinds of reference: + +* Shared reference: `&` +* Mutable reference: `&mut` + +The main rules are as follows: + +* A shared reference can be aliased +* A mutable reference cannot be aliased +* A reference cannot outlive its referrent (`&'a T -> T: 'a`) + +However non-mutable variables have some special rules: + +* You cannot mutate or mutably borrow a non-mut variable, + +Only variables marked as mutable can be borrowed mutably, though this is little +more than a local lint against incorrect usage of a value. + + + + +## Weird Lifetimes + +Almost always, the mutability of a lifetime can be derived from the mutability +of the reference it is attached to. However this is not necessarily the case. +For instance in the following code: + +```rust +fn foo<'a>(input: &'a mut u8) -> &'a u8 { &* input } +``` + +One would expect the output of foo to be an immutable lifetime. However we have +derived it from the input, which is a mutable lifetime. So although we have a +shared reference, it will have the much more limited aliasing rules of a mutable +reference. As a consequence, there is no expressive benefit in a method that +mutates returning a shared reference. + + + + +## Lifetime Elision + +In order to make common patterns more ergonomic, Rust allows lifetimes to be +*elided* in function, impl, and type signatures. + +A *lifetime position* is anywhere you can write a lifetime in a type: + +```rust +&'a T +&'a mut T +T<'a> +``` + +Lifetime positions can appear as either "input" or "output": + +* For `fn` definitions, input refers to the types of the formal arguments + in the `fn` definition, while output refers to + result types. So `fn foo(s: &str) -> (&str, &str)` has elided one lifetime in + input position and two lifetimes in output position. + Note that the input positions of a `fn` method definition do not + include the lifetimes that occur in the method's `impl` header + (nor lifetimes that occur in the trait header, for a default method). + +* In the future, it should be possible to elide `impl` headers in the same manner. + +Elision rules are as follows: + +* Each elided lifetime in input position becomes a distinct lifetime + parameter. + +* If there is exactly one input lifetime position (elided or not), that lifetime + is assigned to *all* elided output lifetimes. + +* If there are multiple input lifetime positions, but one of them is `&self` or + `&mut self`, the lifetime of `self` is assigned to *all* elided output lifetimes. + +* Otherwise, it is an error to elide an output lifetime. + +Examples: + +```rust +fn print(s: &str); // elided +fn print<'a>(s: &'a str); // expanded + +fn debug(lvl: uint, s: &str); // elided +fn debug<'a>(lvl: uint, s: &'a str); // expanded + +fn substr(s: &str, until: uint) -> &str; // elided +fn substr<'a>(s: &'a str, until: uint) -> &'a str; // expanded + +fn get_str() -> &str; // ILLEGAL + +fn frob(s: &str, t: &str) -> &str; // ILLEGAL + +fn get_mut(&mut self) -> &mut T; // elided +fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded + +fn args(&mut self, args: &[T]) -> &mut Command // elided +fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded + +fn new(buf: &mut [u8]) -> BufWriter; // elided +fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded + +``` + + + +## Unbounded Lifetimes + +Unsafe code can often end up producing references or lifetimes out of thin air. +Such lifetimes come into the world as *unbounded*. The most common source of this +is derefencing a raw pointer, which produces a reference with an unbounded lifetime. +Such a lifetime becomes as big as context demands. This is in fact more powerful +than simply becoming `'static`, because for instance `&'static &'a T` +will fail to typecheck, but the unbound lifetime will perfectly mold into +`&'a &'a T` as needed. However for most intents and purposes, such an unbounded +lifetime can be regarded as `'static`. + +Almost no reference is `'static`, so this is probably wrong. `transmute` and +`transmute_copy` are the two other primary offenders. One should endeavour to +bound an unbounded lifetime as quick as possible, especially across function +boundaries. + +Given a function, any output lifetimes that don't derive from inputs are +unbounded. For instance: + +``` +fn get_str<'a>() -> &'a str; +``` + +will produce an `&str` with an unbounded lifetime. The easiest way to avoid +unbounded lifetimes is to use lifetime elision at the function boundary. +If an output lifetime is elided, then it *must* be bounded by an input lifetime. +Of course, it might be bounded by the *wrong* lifetime, but this will usually +just cause a compiler error, rather than allow memory safety to be trivially +violated. + +Within a function, bounding lifetimes is more error-prone. The safest route +is to just use a small function to ensure the lifetime is bound. However if +this is unacceptable, the reference can be placed in a location with a specific +lifetime. Unfortunately it's impossible to name all lifetimes involved in a +function. To get around this, you can in principle use `copy_lifetime`, though +these are unstable due to their awkward nature and questionable utility. + + + + +## Subtyping and Variance + +Although Rust doesn't have any notion of inheritance, it *does* include subtyping. +In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes are derived +from scopes, we can partially order them based on an *outlives* relationship. We +can even express this as a generic bound: `T: 'a` specifies that `T` *outlives* `'a`. + +We can then define subtyping on lifetimes in terms of lifetimes: `'a : 'b` implies +`'a <: b` -- if `'a' outlives `'b`, then `'a` is a subtype of `'b`. This is a very +large source of confusion, because a bigger scope is a *sub type* of a smaller scope. +This does in fact make sense. The intuitive reason for this is that if you expect an +`&'a u8`, then it's totally fine for me to hand you an `&'static u8`, in the same way +that if you expect an Animal in Java, it's totally fine for me to hand you a Cat. + +Variance is where things get really harsh. + +Variance is a property that *type constructors* have. A type constructor in Rust +is a generic type with unbound arguments. For instance `Vec` is a type constructor +that takes a `T` and returns a `Vec`. `&` and `&mut` are type constructors that +take a lifetime and a type. + +A type constructor's *variance* is how the subtypes of its inputs affects the +subtypes of its outputs. There are three kinds of variance: + +* F is *covariant* if `T <: U` implies `F <: F` +* F is *contravariant* if `T <: U` implies `F <: F` +* F is *invariant* otherwise (no subtyping relation can be derived) + +Some important variances: + +* `&` is covariant (as is *const by metaphor) +* `&mut` is invariant (as is *mut by metaphor) +* `Fn(T)` is contravariant with respect to `T` +* `Box`, `Vec`, and all other collections are covariant +* `UnsafeCell`, `Cell`, `RefCell`, `Mutex` and all "interior mutability" + types are invariant + +To understand why these variances are correct and desirable, we will consider several +examples. We have already covered why `&` should be covariant. + +To see why `&mut` should be invariant, consider the following code: + +```rust +fn main() { + let mut forever_str: &'static str = "hello"; + { + let string = String::from("world"); + overwrite(&mut forever_str, &mut &*string); + } + println!("{}", forever_str); +} + +fn overwrite(input: &mut T, new: &mut T) { + *input = *new; +} +``` + +The signature of `overwrite` is clearly valid: it takes mutable references to two values +of the same type, and replaces one with the other. We have seen already that `&` is +covariant, and `'static` is a subtype of *any* `'a', so `&'static str` is a +subtype of `&'a str`. Therefore, if `&mut` was +*also* covariant, then the lifetime of the `&'static str` would successfully be +"shrunk" down to the shorter lifetime of the string, and `replace` would be +called successfully. The string would subsequently be dropped, and `forever_str` +would point to freed memory when we print it! + +Therefore `&mut` should be invariant. This is the general theme of covariance vs +invariance: if covariance would allow you to *store* a short-lived value in a +longer-lived slot, then you must be invariant. + +`Box` and `Vec` are interesting cases because they're covariant, but you can +definitely store values in them! This is fine because *you can only store values +in them through a mutable reference*! The mutable reference makes the whole type +invariant, and therefore prevents you from getting in trouble. + +Being covariant allows them to be covariant when shared immutably (so you can pass +a `&Box<&'static str>` where a `&Box<&'a str>` is expected). It also allows you to +forever weaken the type by moving it into a weaker slot. That is, you can do: + +```rust +fn get_box<'a>(&'a u8) -> Box<&'a str> { + Box::new("hello") +} +``` + +which is fine because unlike the mutable borrow case, there's no one else who +"remembers" the old lifetime in the box. + +The variance of the cell types similarly follows. `&` is like an `&mut` for a +cell, because you can still store values in them through an `&`. Therefore cells +must be invariant to avoid lifetime smuggling. + +`Fn` is the most confusing case, largely because contravariance is easily the +most confusing kind of variance, and basically never comes up. To understand it, +consider a function that *takes* a function `len` that takes a function `F`. + +```rust +fn len(func: F) -> usize + where F: Fn(&'static str) -> usize +{ + func("hello") +} +``` + +We require that F is a Fn that can take an `&'static str` and print a usize. Now +say we have a function that can take an `&'a str` (for *some* 'a). Such a function actually +accepts *more* inputs, since `&'static str` is a subtype of `&'a str`. Therefore +`len` should happily accept such a function! + +So a `Fn(&'a str)` is a subtype of a `Fn(&'static str)` because +`&'static str` is a subtype of `&'a str`. Exactly contravariance. + +The variance of `*const` and `*mut` is basically arbitrary as they're not at all +type or memory safe, so their variance is determined in analogy to & and &mut +respectively. + + + + +## PhantomData and PhantomFn + +This is all well and good for the types the standard library provides, but +how is variance determined for type that *you* define? The variance of a type +over its generic arguments is determined by how they're stored. + +```rust +struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { + a: &'a A, // covariant over 'a and A + b: &'b mut B, // invariant over 'b and B + c: *const C, // covariant over C + d: *mut D, // invariant over D + e: Vec, // covariant over E + f: Cell, // invariant over F + g: G // covariant over G + h1: H // would also be covariant over H except... + h2: Cell // invariant over H, because invariance wins +} +``` + +However when working with unsafe code, we can often end up in a situation where +types or lifetimes are logically associated with a struct, but not actually +reachable. This most commonly occurs with lifetimes. For instance, the `Iter` +for `&'a [T]` is (approximately) defined as follows: + +``` +pub struct Iter<'a, T: 'a> { + ptr: *const T, + end: *const T, +} +``` + +However because `'a` is unused within the struct's body, it's *unbound*. +Because of the troubles this has historically caused, unbound lifetimes and +types are *illegal* in struct definitions. Therefore we must somehow refer +to these types in the body. + +We do this using *PhantomData*, which is a special marker type. PhantomData +consumes no space, but simulates a field of the given type for the purpose of +variance. This was deemed to be less error-prone than explicitly telling the +type-system the kind of variance that you want. + +Iter logically contains `&'a T`, so this is exactly what we tell +the PhantomData to simulate: + +``` +pub struct Iter<'a, T: 'a> { + ptr: *const T, + end: *const T, + _marker: marker::PhantomData<&'a T>, +} +``` + + +## Splitting Lifetimes + +The mutual exclusion property of mutable references can be very limiting when +working with a composite structure. Borrowck understands some basic stuff, but +will fall over pretty easily. Borrowck understands structs sufficiently to +understand that it's possible to borrow disjoint fields of a struct simultaneously. +So this works today: + +```rust +struct Foo { + a: i32, + b: i32, + c: i32, +} + +let mut x = Foo {a: 0, b: 0, c: 0}; +let a = &mut x.a; +let b = &mut x.b; +let c = &x.c; +*b += 1; +let c2 = &x.c; +*a += 10; +println!("{} {} {} {}", a, b, c, c2); +``` + +However borrowck doesn't understand arrays or slices in any way, so this doesn't +work: + +```rust +let x = [1, 2, 3]; +let a = &mut x[0]; +let b = &mut x[1]; +println!("{} {}", a, b); +``` + +```text +:3:18: 3:22 error: cannot borrow immutable indexed content `x[..]` as mutable +:3 let a = &mut x[0]; + ^~~~ +:4:18: 4:22 error: cannot borrow immutable indexed content `x[..]` as mutable +:4 let b = &mut x[1]; + ^~~~ +error: aborting due to 2 previous errors +``` + +While it was plausible that borrowck could understand this simple case, it's +pretty clearly hopeless for borrowck to understand disjointness in general +container types like a tree, especially if distinct keys actually *do* map +to the same value. + +In order to "teach" borrowck that what we're doing is ok, we need to drop down +to unsafe code. For instance, mutable slices expose a `split_at_mut` function that +consumes the slice and returns *two* mutable slices. One for everything to the +left of the index, and one for everything to the right. Intuitively we know this +is safe because the slices don't alias. However the implementation requires some +unsafety: + +```rust +fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + unsafe { + let self2: &mut [T] = mem::transmute_copy(&self); + + (ops::IndexMut::index_mut(self, ops::RangeTo { end: mid } ), + ops::IndexMut::index_mut(self2, ops::RangeFrom { start: mid } )) + } +} +``` + +This is pretty plainly dangerous. We use transmute to duplicate the slice with an +*unbounded* lifetime, so that it + + -* Splitting lifetimes into disjoint regions -* Creating lifetimes from raw pointers -* \ No newline at end of file From 3be2643cb2a64f2667fc187ed9899f291714e85a Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 18 Jun 2015 21:11:00 -0700 Subject: [PATCH 007/104] stub out more stuff --- ffi.md | 0 intro.md | 11 +++++++++++ no_std.md | 0 3 files changed, 11 insertions(+) create mode 100644 ffi.md create mode 100644 no_std.md diff --git a/ffi.md b/ffi.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/intro.md b/intro.md index bc0f6483baa4..cb644c515f2e 100644 --- a/intro.md +++ b/intro.md @@ -7,6 +7,17 @@ Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know the basics of the language and systems programming. We will not explain the stack or heap, we will not explain the syntax. +## Sections + +* [Data Layout](data.html) +* [Ownership and Lifetimes](lifetimes.html) +* [Conversions](conversions.html) +* [Uninitialized Memory](uninitialized.html) +* [Ownership-oriented resource management (RAII)](raii.html) +* [Concurrency](concurrency.html) +* [Interfacing with other languages (FFI)](ffi.html) +* [Eliminating the Runtime (no_std)](no_std.html) + ## A Tale Of Two Languages Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust. diff --git a/no_std.md b/no_std.md new file mode 100644 index 000000000000..e69de29bb2d1 From 02134464b0ac3cb64e221fd008b8b9e6bad1d932 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 19 Jun 2015 10:52:41 -0700 Subject: [PATCH 008/104] progress --- ffi.md | 45 +++++++++++++++++++++++++ lifetimes.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++--- no_std.md | 2 ++ 3 files changed, 135 insertions(+), 5 deletions(-) diff --git a/ffi.md b/ffi.md index e69de29bb2d1..668befb4bf5f 100644 --- a/ffi.md +++ b/ffi.md @@ -0,0 +1,45 @@ +% Interfacing with other Languages (FFI) + +*Obviously* we'd all love to live in a **glorious** world where everything is +written in Rust, Rust, and More Rust. Tragically, programs have been written +in Not Rust for over 50 years. Crufty enterprises are doomed to +support ancient code bases, and greybeard programmers stuck in their ways +*insist* on writing programs in other languages, even to this day! + +In all seriousness, there's a myriad of reasons for your codebase to be a +hybrid of different languages, and Rust is well-designed to interface with +all of them as painlessly as possible. It does this through the tried and +true strategy of all languages: pretend to be C, and understand C. + +Thanks to Rust's minimal runtime and C-like semantics, this is about as +painless as FFI with C++. Obviously, most of Rust's features are completely +incompatible with other languages: tagged unions, zero-sized-types, dynamically- +sized types, destructors, methods, traits, references, and lifetimes are all +concepts that you won't be able to expose or accept in your foreign function +interface. + +All mapping through C will give you is functions, structs, globals, raw pointers, +and C-like enums. That's it. Rust's default data layouts are also incompatible +with the C layout. See [the section on data layout][data.html] for details. +Long story short: mark FFI structs and enums with `#[repr(C)]`, mark FFI +functions as `extern`. + +## Runtime + +Rust's runtime is sufficiently minimal that it requires *no* special handling. +You don't need to set anything up. You don't need to tear anything down. +Awesome. + +The only runtime detail you *really* need to worry about is unwinding. Rust's +unwinding model is not defined to be incompatible with any particular language. +That means that if you call Rust from another language and it unwinds into the +calling language, this will cause Undefined Behaviour. Similarly, if another +language unwinds into Rust, it will also cause Undefined Behaviour. + +Rust can't really do anything about other languages unwinding into it (FFI is unsafe +for a reason!), but you can be a good FFI citizen by catching panics in any +FFI functions you export. Rust provides `thread::catch_panic` for exactly this. +Unfortunately, this API is still unstable. + +## libc + diff --git a/lifetimes.md b/lifetimes.md index 42304681c206..ebb74bd299b4 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -60,6 +60,7 @@ read-write lock. + ## Lifetimes Rust's static checks are managed by the *borrow checker* (borrowck), which tracks @@ -219,6 +220,77 @@ these are unstable due to their awkward nature and questionable utility. + +## Higher-Rank Lifetimes + +Generics in Rust generally allow types to be instantiated with arbitrary +associated lifetimes, but this fixes the lifetimes they work with once +instantiated. For almost all types, this is exactly the desired behaviour. +For example slice::Iter can work with arbitrary lifetimes, determined by the +slice that instantiates it. However *once* Iter is instantiated the lifetimes +it works with cannot be changed. It returns references that live for some +particular `'a`. + +However some types are more flexible than this. In particular, a single +instantiation of a function can process arbitrary lifetimes: + +```rust +fn identity(input: &u8) -> &u8 { input } +``` + +What is *the* lifetime that identity works with? There is none. If you think +this is "cheating" because functions are statically instantiated, then you need +only consider the equivalent closure: + +```rust +let identity = |input: &u8| input; +``` + +These functions are *higher ranked* over the lifetimes they work with. This means +that they're generic over what they handle *after instantiation*. For most things +this would pose a massive problem, but because lifetimes don't *exist* at runtime, +this is really just a compile-time mechanism. The Fn traits contain sugar that +allows higher-rank lifetimes to simply be expressed by simply omitting lifetimes: + + +```rust +fn main() { + foo(|input| input); +} + +fn foo(f: F) + // F is higher-ranked over the lifetime these references have + where F: Fn(&u8) -> &u8 +{ + f(&0); + f(&1); +} +``` + +The desugaring of this is actually unstable: + +``` +#![feature(unboxed_closures)] + +fn main() { + foo(|input| input); +} + +fn foo(f: F) + where F: for<'a> Fn<(&'a u8,), Output=&'a u8> +{ + f(&0); + f(&1); +} +``` + +`for<'a>` is how we declare a higher-ranked lifetime. Unfortunately higher-ranked +lifetimes are still fairly new, and are missing a few features to make them +maximally useful outside of the Fn traits. + + + + ## Subtyping and Variance Although Rust doesn't have any notion of inheritance, it *does* include subtyping. @@ -227,12 +299,15 @@ from scopes, we can partially order them based on an *outlives* relationship. We can even express this as a generic bound: `T: 'a` specifies that `T` *outlives* `'a`. We can then define subtyping on lifetimes in terms of lifetimes: `'a : 'b` implies -`'a <: b` -- if `'a' outlives `'b`, then `'a` is a subtype of `'b`. This is a very +`'a <: b` -- if `'a` outlives `'b`, then `'a` is a subtype of `'b`. This is a very large source of confusion, because a bigger scope is a *sub type* of a smaller scope. This does in fact make sense. The intuitive reason for this is that if you expect an `&'a u8`, then it's totally fine for me to hand you an `&'static u8`, in the same way that if you expect an Animal in Java, it's totally fine for me to hand you a Cat. +(Note, the subtyping relationship and typed-ness of lifetimes is a fairly arbitrary +construct that some disagree with. I just find that it simplifies this analysis.) + Variance is where things get really harsh. Variance is a property that *type constructors* have. A type constructor in Rust @@ -278,7 +353,7 @@ fn overwrite(input: &mut T, new: &mut T) { The signature of `overwrite` is clearly valid: it takes mutable references to two values of the same type, and replaces one with the other. We have seen already that `&` is -covariant, and `'static` is a subtype of *any* `'a', so `&'static str` is a +covariant, and `'static` is a subtype of *any* `'a`, so `&'static str` is a subtype of `&'a str`. Therefore, if `&mut` was *also* covariant, then the lifetime of the `&'static str` would successfully be "shrunk" down to the shorter lifetime of the string, and `replace` would be @@ -341,8 +416,16 @@ respectively. ## PhantomData and PhantomFn This is all well and good for the types the standard library provides, but -how is variance determined for type that *you* define? The variance of a type -over its generic arguments is determined by how they're stored. +how is variance determined for type that *you* define? A struct is, informally +speaking, covariant over all its fields (and an enum over its variants). This +basically means that it inherits the variance of its fields. If a struct `Foo` +has a generic argument `A` that is used in a field `a`, then Foo's variance +over `A` is exactly `a`'s variance. However this is complicated if `A` is used +in multiple fields. + +* If all uses of A are covariant, then Foo is covariant over A +* If all uses of A are contravariant, then Foo is contravariant over A +* Otherwise, Foo is invariant over A ```rust struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { @@ -360,7 +443,7 @@ struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { However when working with unsafe code, we can often end up in a situation where types or lifetimes are logically associated with a struct, but not actually -reachable. This most commonly occurs with lifetimes. For instance, the `Iter` +part of a field. This most commonly occurs with lifetimes. For instance, the `Iter` for `&'a [T]` is (approximately) defined as follows: ``` diff --git a/no_std.md b/no_std.md index e69de29bb2d1..8da5b78cadb4 100644 --- a/no_std.md +++ b/no_std.md @@ -0,0 +1,2 @@ +% Eliminating the Runtime (no_std) + From 74b398b93d647237acbc1c738e55e47ec13ea7b2 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 19 Jun 2015 14:23:41 -0700 Subject: [PATCH 009/104] progress on lifetimes --- lifetimes.md | 134 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 121 insertions(+), 13 deletions(-) diff --git a/lifetimes.md b/lifetimes.md index ebb74bd299b4..84bc7e2ef594 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -1,4 +1,4 @@ -% Ownership +% Ownership and Lifetimes Ownership is the breakout feature of Rust. It allows Rust to be completely memory-safe and efficient, while avoiding garbage collection. Before getting @@ -58,6 +58,13 @@ a Cell is to copy the bits in or out. manages this through *runtime* checks. It is effectively a thread-unsafe read-write lock. +For more details see Dan Grossman's Existential Types for Imperative Languages: +* [paper][grossman-paper] (Advanced) +* [slides][grossman-slides] (Simple) + +[grossman-paper]: http://homes.cs.washington.edu/~djg/papers/exists_imp.pdf +[grossman-slides]: https://homes.cs.washington.edu/~djg/slides/esop02_talk.pdf + @@ -96,19 +103,49 @@ more than a local lint against incorrect usage of a value. ## Weird Lifetimes -Almost always, the mutability of a lifetime can be derived from the mutability -of the reference it is attached to. However this is not necessarily the case. -For instance in the following code: +Given the following code: ```rust -fn foo<'a>(input: &'a mut u8) -> &'a u8 { &* input } +struct Foo; + +impl Foo { + fn mutate_and_share(&mut self) -> &Self { &*self } + fn share(&self) {} +} + +fn main() { + let mut foo = Foo; + let loan = foo.mutate_and_share(); + foo.share(); +} ``` -One would expect the output of foo to be an immutable lifetime. However we have -derived it from the input, which is a mutable lifetime. So although we have a -shared reference, it will have the much more limited aliasing rules of a mutable -reference. As a consequence, there is no expressive benefit in a method that -mutates returning a shared reference. +One might expect it to compile. We call `mutate_and_share`, which mutably borrows +`foo` *temporarily*, but then returns *only* a shared reference. Therefore we +would expect `foo.share()` to succeed as `foo` shouldn't be mutably borrowed. + +However when we try to compile it: + +```text +:11:5: 11:8 error: cannot borrow `foo` as immutable because it is also borrowed as mutable +:11 foo.share(); + ^~~ +:10:16: 10:19 note: previous borrow of `foo` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foo` until the borrow ends +:10 let loan = foo.mutate_and_share(); + ^~~ +:12:2: 12:2 note: previous borrow ends here +:8 fn main() { +:9 let mut foo = Foo; +:10 let loan = foo.mutate_and_share(); +:11 foo.share(); +:12 } + ^ +``` + +What happened? Well, the lifetime of `loan` is derived from a *mutable* borrow. +This makes the type system believe that `foo` is mutably borrowed as long as +`loan` exists, even though it's a shared reference. To my knowledge, this is not +a bug. @@ -413,7 +450,7 @@ respectively. -## PhantomData and PhantomFn +## PhantomData This is all well and good for the types the standard library provides, but how is variance determined for type that *you* define? A struct is, informally @@ -475,6 +512,8 @@ pub struct Iter<'a, T: 'a> { ``` + + ## Splitting Lifetimes The mutual exclusion property of mutable references can be very limiting when @@ -544,7 +583,76 @@ fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { ``` This is pretty plainly dangerous. We use transmute to duplicate the slice with an -*unbounded* lifetime, so that it - +*unbounded* lifetime, so that it can be treated as disjoint from the other until +we unify them when we return. + +However more subtle is how iterators that yield mutable references work. +The iterator trait is defined as follows: + +```rust +trait Iterator { + type Item; + + fn next(&mut self) -> Option; +} +``` + +Given this definition, Self::Item has *no* connection to `self`. This means +that we can call `next` several times in a row, and hold onto all the results +*concurrently*. This is perfectly fine for by-value iterators, which have exactly +these semantics. It's also actually fine for shared references, as it's perfectly +fine to grab a huge pile of shared references to the same thing (although the +iterator needs to be a separate object from the thing being shared). But mutable +references make this a mess. At first glance, they might seem completely +incompatible with this API, as it would produce multiple mutable references to +the same object! + +However it actually *does* work, exactly because iterators are one-shot objects. +Everything an IterMut yields will be yielded *at most* once, so we don't *actually* +ever yield multiple mutable references to the same piece of data. + +In general all mutable iterators require *some* unsafe code *somewhere*, though. +Whether it's raw pointers, or safely composing on top of *another* IterMut. + +For instance, VecDeque's IterMut: + +```rust +pub struct IterMut<'a, T:'a> { + // The whole backing array. Some of these indices are initialized! + ring: &'a mut [T], + tail: usize, + head: usize, +} + +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + fn next(&mut self) -> Option<&'a mut T> { + if self.tail == self.head { + return None; + } + let tail = self.tail; + self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); + + unsafe { + // might as well do unchecked indexing since wrap_index has us + // in-bounds, and many of the "middle" indices are uninitialized + // anyway. + let elem = self.ring.get_unchecked_mut(tail); + + // round-trip through a raw pointer to unbound the lifetime from + // ourselves + Some(&mut *(elem as *mut _)) + } + } +} +``` + +A very subtle but interesting detail in this design is that it *relies on +privacy to be sound*. Borrowck works on some very simple rules. One of those rules +is that if we have a live &mut Foo and Foo contains an &mut Bar, then that &mut +Bar is *also* live. Since IterMut is always live when `next` can be called, if +`ring` were public then we could mutate `ring` while outstanding mutable borrows +to it exist! From c3c9d9140530a9709449fd32e830bf88f567845c Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 19 Jun 2015 14:51:27 -0700 Subject: [PATCH 010/104] progress --- lifetimes.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/lifetimes.md b/lifetimes.md index 84bc7e2ef594..02e307d57fc6 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -447,15 +447,9 @@ The variance of `*const` and `*mut` is basically arbitrary as they're not at all type or memory safe, so their variance is determined in analogy to & and &mut respectively. - - - -## PhantomData - This is all well and good for the types the standard library provides, but -how is variance determined for type that *you* define? A struct is, informally -speaking, covariant over all its fields (and an enum over its variants). This -basically means that it inherits the variance of its fields. If a struct `Foo` +how is variance determined for type that *you* define? A struct informally +speaking inherits the variance of its fields. If a struct `Foo` has a generic argument `A` that is used in a field `a`, then Foo's variance over `A` is exactly `a`'s variance. However this is complicated if `A` is used in multiple fields. @@ -478,6 +472,17 @@ struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { } ``` + + + +## Dropck + +TODO + + +## PhantomData + + However when working with unsafe code, we can often end up in a situation where types or lifetimes are logically associated with a struct, but not actually part of a field. This most commonly occurs with lifetimes. For instance, the `Iter` @@ -511,6 +516,8 @@ pub struct Iter<'a, T: 'a> { } ``` +However PhantomData is also necessary to signal important information to +*dropck*. (TODO) From fabbd4e8630ca1087fb69dca978ab7916d2d1adf Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 19 Jun 2015 15:41:39 -0700 Subject: [PATCH 011/104] progress --- lifetimes.md | 58 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/lifetimes.md b/lifetimes.md index 02e307d57fc6..159a3b00074f 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -474,16 +474,9 @@ struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { - -## Dropck - -TODO - - ## PhantomData - -However when working with unsafe code, we can often end up in a situation where +When working with unsafe code, we can often end up in a situation where types or lifetimes are logically associated with a struct, but not actually part of a field. This most commonly occurs with lifetimes. For instance, the `Iter` for `&'a [T]` is (approximately) defined as follows: @@ -498,7 +491,8 @@ pub struct Iter<'a, T: 'a> { However because `'a` is unused within the struct's body, it's *unbound*. Because of the troubles this has historically caused, unbound lifetimes and types are *illegal* in struct definitions. Therefore we must somehow refer -to these types in the body. +to these types in the body. Correctly doing this is necessary to have +correct variance and drop checking. We do this using *PhantomData*, which is a special marker type. PhantomData consumes no space, but simulates a field of the given type for the purpose of @@ -516,8 +510,50 @@ pub struct Iter<'a, T: 'a> { } ``` -However PhantomData is also necessary to signal important information to -*dropck*. (TODO) + + + +## Dropck + +When a type is going out of scope, Rust will try to Drop it. Drop executes +arbitrary code, and in fact allows us to "smuggle" arbitrary code execution +into many places. As such additional soundness checks (dropck) are necessary to +ensure that a type T can be safely instantiated and dropped. It turns out that we +*really* don't need to care about dropck in practice, as it often "just works". + +However the one exception is with PhantomData. Given a struct like Vec: + +``` +struct Vec { + data: *const T, // *const for covariance! + len: usize, + cap: usize, +} +``` + +dropck will generously determine that Vec does not contain any values of +type T. This will unfortunately allow people to construct unsound Drop +implementations that access data that has already been dropped. In order to +tell dropck that we *do* own values of type T and may call destructors of that +type, we must add extra PhantomData: + +``` +struct Vec { + data: *const T, // *const for covariance! + len: usize, + cap: usize, + _marker: marker::PhantomData, +} +``` + +Raw pointers that own an allocation is such a pervasive pattern that the +standard library made a utility for itself called `Unique` which: + +* wraps a `*const T`, +* includes a PhantomData, +* auto-derives Send/Sync as if T was contained +* marks the pointer as NonZero for the null-pointer optimization + From cb4f081b5e8278e0445ae67320fb80d274cd8e11 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 19 Jun 2015 15:42:30 -0700 Subject: [PATCH 012/104] remove ffi and no_std, TRPL's got it --- ffi.md | 45 --------------------------------------------- intro.md | 2 -- no_std.md | 2 -- 3 files changed, 49 deletions(-) delete mode 100644 ffi.md delete mode 100644 no_std.md diff --git a/ffi.md b/ffi.md deleted file mode 100644 index 668befb4bf5f..000000000000 --- a/ffi.md +++ /dev/null @@ -1,45 +0,0 @@ -% Interfacing with other Languages (FFI) - -*Obviously* we'd all love to live in a **glorious** world where everything is -written in Rust, Rust, and More Rust. Tragically, programs have been written -in Not Rust for over 50 years. Crufty enterprises are doomed to -support ancient code bases, and greybeard programmers stuck in their ways -*insist* on writing programs in other languages, even to this day! - -In all seriousness, there's a myriad of reasons for your codebase to be a -hybrid of different languages, and Rust is well-designed to interface with -all of them as painlessly as possible. It does this through the tried and -true strategy of all languages: pretend to be C, and understand C. - -Thanks to Rust's minimal runtime and C-like semantics, this is about as -painless as FFI with C++. Obviously, most of Rust's features are completely -incompatible with other languages: tagged unions, zero-sized-types, dynamically- -sized types, destructors, methods, traits, references, and lifetimes are all -concepts that you won't be able to expose or accept in your foreign function -interface. - -All mapping through C will give you is functions, structs, globals, raw pointers, -and C-like enums. That's it. Rust's default data layouts are also incompatible -with the C layout. See [the section on data layout][data.html] for details. -Long story short: mark FFI structs and enums with `#[repr(C)]`, mark FFI -functions as `extern`. - -## Runtime - -Rust's runtime is sufficiently minimal that it requires *no* special handling. -You don't need to set anything up. You don't need to tear anything down. -Awesome. - -The only runtime detail you *really* need to worry about is unwinding. Rust's -unwinding model is not defined to be incompatible with any particular language. -That means that if you call Rust from another language and it unwinds into the -calling language, this will cause Undefined Behaviour. Similarly, if another -language unwinds into Rust, it will also cause Undefined Behaviour. - -Rust can't really do anything about other languages unwinding into it (FFI is unsafe -for a reason!), but you can be a good FFI citizen by catching panics in any -FFI functions you export. Rust provides `thread::catch_panic` for exactly this. -Unfortunately, this API is still unstable. - -## libc - diff --git a/intro.md b/intro.md index cb644c515f2e..12b105db8067 100644 --- a/intro.md +++ b/intro.md @@ -15,8 +15,6 @@ stack or heap, we will not explain the syntax. * [Uninitialized Memory](uninitialized.html) * [Ownership-oriented resource management (RAII)](raii.html) * [Concurrency](concurrency.html) -* [Interfacing with other languages (FFI)](ffi.html) -* [Eliminating the Runtime (no_std)](no_std.html) ## A Tale Of Two Languages diff --git a/no_std.md b/no_std.md deleted file mode 100644 index 8da5b78cadb4..000000000000 --- a/no_std.md +++ /dev/null @@ -1,2 +0,0 @@ -% Eliminating the Runtime (no_std) - From 7d41c950c4e73dee4d5b44022186aa65e4323375 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 19 Jun 2015 15:45:49 -0700 Subject: [PATCH 013/104] fix data headers --- data.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/data.md b/data.md index 6fa63568862c..9189209db5ee 100644 --- a/data.md +++ b/data.md @@ -4,7 +4,7 @@ Low-level programming cares a lot about data layout. It's a big deal. It also pe influences the rest of the language, so we're going to start by digging into how data is represented in Rust. -# The `rust` repr +## The rust repr Rust gives you the following ways to lay out composite data: @@ -124,7 +124,7 @@ In principle enums can use fairly elaborate algorithms to cache bits throughout with special constrained representations. As such it is *especially* desirable that we leave enum layout unspecified today. -# Dynamically Sized Types (DSTs) +## Dynamically Sized Types (DSTs) Rust also supports types without a statically known size. On the surface, this is a bit nonsensical: Rust must know the size of something in order to @@ -212,12 +212,12 @@ struct Foo { For details as to *why* this is done, and how to make it not happen, check out [SOME OTHER SECTION]. -# Alternative representations +## Alternative representations Rust allows you to specify alternative data layout strategies from the default Rust one. -# repr(C) +### repr(C) This is the most important `repr`. It has fairly simple intent: do what C does. The order, size, and alignment of fields is exactly what you would expect from @@ -241,14 +241,14 @@ still consumes a byte of space. * This is equivalent to repr(u32) for enums (see below) -# repr(packed) +### repr(packed) `repr(packed)` forces rust to strip any padding it would normally apply. This may improve the memory footprint of a type, but will have negative side-effects from "field access is heavily penalized" to "completely breaks everything" based on target platform. -# repr(u8), repr(u16), repr(u32), repr(u64) +### repr(u8), repr(u16), repr(u32), repr(u64) These specify the size to make a c-like enum (one which has no values in its variants). From edb29ec53db18b8f119154a1b51009f35eeeeeb2 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 19 Jun 2015 15:52:21 -0700 Subject: [PATCH 014/104] futz with headers more --- concurrency.md | 25 +++++++++++++------------ data.md | 30 ++++++++++++++++++++++++------ intro.md | 15 ++++++++++++--- lifetimes.md | 20 ++++++++++---------- raii.md | 2 +- 5 files changed, 60 insertions(+), 32 deletions(-) diff --git a/concurrency.md b/concurrency.md index c600644ba63e..a382e4edf54c 100644 --- a/concurrency.md +++ b/concurrency.md @@ -1,16 +1,8 @@ % Concurrency and Paralellism -```Not sure if I want this -Safe Rust features *a ton* of tooling to make concurrency and parallelism totally -safe, easy, and fearless. This is a case where we'll really just -[defer to TRPL][trpl-conc] for the basics. -TL;DR: The `Send` and `Sync` traits in conjunction with Rust's ownership model and -normal generic bounds make using concurrent APIs really easy and painless for -a user of Safe Rust. -``` -## Data Races and Race Conditions +# Data Races and Race Conditions Safe Rust guarantees an absence of data races, which are defined as: @@ -77,7 +69,10 @@ if idx.load(Ordering::SeqCst) < data.len() { } ``` -## Send and Sync + + + +# Send and Sync Not everything obeys inherited mutability, though. Some types allow you to multiply alias a location in memory while mutating it. Unless these types use synchronization @@ -153,7 +148,10 @@ into the collection. TODO: better explain what can or can't be Send or Sync. Sufficient to appeal only to data races? -## Atomics + + + +# Atomics Rust pretty blatantly just inherits LLVM's model for atomics, which in turn is largely based off of the C11 model for atomics. This is not due these models @@ -165,7 +163,10 @@ least, we can benefit from existing tooling and research around C's model. Trying to fully explain these models is fairly hopeless, so we're just going to drop that problem in LLVM's lap. -## Actually Doing Things Concurrently + + + +# Actually Doing Things Concurrently Rust as a language doesn't *really* have an opinion on how to do concurrency or parallelism. The standard library exposes OS threads and blocking sys-calls diff --git a/data.md b/data.md index 9189209db5ee..110084824cfe 100644 --- a/data.md +++ b/data.md @@ -4,7 +4,10 @@ Low-level programming cares a lot about data layout. It's a big deal. It also pe influences the rest of the language, so we're going to start by digging into how data is represented in Rust. -## The rust repr + + + +# The rust repr Rust gives you the following ways to lay out composite data: @@ -124,7 +127,7 @@ In principle enums can use fairly elaborate algorithms to cache bits throughout with special constrained representations. As such it is *especially* desirable that we leave enum layout unspecified today. -## Dynamically Sized Types (DSTs) +# Dynamically Sized Types (DSTs) Rust also supports types without a statically known size. On the surface, this is a bit nonsensical: Rust must know the size of something in order to @@ -150,6 +153,9 @@ struct Foo { } ``` + + + # Zero Sized Types (ZSTs) Rust actually allows types to be specified that occupy *no* space: @@ -182,6 +188,9 @@ consequence of types with no size. In particular, pointer offsets are no-ops, an standard allocators (including jemalloc, the one used by Rust) generally consider passing in `0` as Undefined Behaviour. + + + # Drop Flags For unfortunate legacy implementation reasons, Rust as of 1.0.0 will do a nasty trick to @@ -212,12 +221,17 @@ struct Foo { For details as to *why* this is done, and how to make it not happen, check out [SOME OTHER SECTION]. -## Alternative representations + + + +# Alternative representations Rust allows you to specify alternative data layout strategies from the default Rust one. -### repr(C) + + +## repr(C) This is the most important `repr`. It has fairly simple intent: do what C does. The order, size, and alignment of fields is exactly what you would expect from @@ -241,14 +255,18 @@ still consumes a byte of space. * This is equivalent to repr(u32) for enums (see below) -### repr(packed) + + +## repr(packed) `repr(packed)` forces rust to strip any padding it would normally apply. This may improve the memory footprint of a type, but will have negative side-effects from "field access is heavily penalized" to "completely breaks everything" based on target platform. -### repr(u8), repr(u16), repr(u32), repr(u64) + + +## repr(u8), repr(u16), repr(u32), repr(u64) These specify the size to make a c-like enum (one which has no values in its variants). diff --git a/intro.md b/intro.md index 12b105db8067..7d3036fe5ec4 100644 --- a/intro.md +++ b/intro.md @@ -7,7 +7,10 @@ Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know the basics of the language and systems programming. We will not explain the stack or heap, we will not explain the syntax. -## Sections + + + +# Sections * [Data Layout](data.html) * [Ownership and Lifetimes](lifetimes.html) @@ -16,7 +19,10 @@ stack or heap, we will not explain the syntax. * [Ownership-oriented resource management (RAII)](raii.html) * [Concurrency](concurrency.html) -## A Tale Of Two Languages + + + +# A Tale Of Two Languages Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust. Any time someone opines the guarantees of Rust, they are almost surely talking about @@ -60,7 +66,10 @@ The fact that Rust is written with a healthy spoonful of Unsafe Rust is no diffe However it *does* mean that Rust doesn't need to fall back to the pervasive unsafety of C to do the nasty things that need to get done. -## What does `unsafe` mean? + + + +# What does `unsafe` mean? Rust tries to model memory safety through the `unsafe` keyword. Interestingly, the meaning of `unsafe` largely revolves around what diff --git a/lifetimes.md b/lifetimes.md index 159a3b00074f..4be895ff429b 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -7,7 +7,7 @@ language-design problem. -## The Tagged Union Problem +# The Tagged Union Problem The core of the lifetime and mutability system derives from a simple problem: internal pointers to tagged unions. For instance, consider the following code: @@ -68,7 +68,7 @@ For more details see Dan Grossman's Existential Types for Imperative Languages: -## Lifetimes +# Lifetimes Rust's static checks are managed by the *borrow checker* (borrowck), which tracks mutability and outstanding loans. This analysis can in principle be done without @@ -101,7 +101,7 @@ more than a local lint against incorrect usage of a value. -## Weird Lifetimes +# Weird Lifetimes Given the following code: @@ -150,7 +150,7 @@ a bug. -## Lifetime Elision +# Lifetime Elision In order to make common patterns more ergonomic, Rust allows lifetimes to be *elided* in function, impl, and type signatures. @@ -217,7 +217,7 @@ fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded -## Unbounded Lifetimes +# Unbounded Lifetimes Unsafe code can often end up producing references or lifetimes out of thin air. Such lifetimes come into the world as *unbounded*. The most common source of this @@ -258,7 +258,7 @@ these are unstable due to their awkward nature and questionable utility. -## Higher-Rank Lifetimes +# Higher-Rank Lifetimes Generics in Rust generally allow types to be instantiated with arbitrary associated lifetimes, but this fixes the lifetimes they work with once @@ -328,7 +328,7 @@ maximally useful outside of the Fn traits. -## Subtyping and Variance +# Subtyping and Variance Although Rust doesn't have any notion of inheritance, it *does* include subtyping. In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes are derived @@ -474,7 +474,7 @@ struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { -## PhantomData +# PhantomData When working with unsafe code, we can often end up in a situation where types or lifetimes are logically associated with a struct, but not actually @@ -513,7 +513,7 @@ pub struct Iter<'a, T: 'a> { -## Dropck +# Dropck When a type is going out of scope, Rust will try to Drop it. Drop executes arbitrary code, and in fact allows us to "smuggle" arbitrary code execution @@ -557,7 +557,7 @@ standard library made a utility for itself called `Unique` which: -## Splitting Lifetimes +# Splitting Lifetimes The mutual exclusion property of mutable references can be very limiting when working with a composite structure. Borrowck understands some basic stuff, but diff --git a/raii.md b/raii.md index 13a2bdf8fff7..76363030b848 100644 --- a/raii.md +++ b/raii.md @@ -176,4 +176,4 @@ On balance this is an ok choice. Certainly if you're just getting started. In the future, we expect there to be a first-class way to announce that a field should be automatically dropped. -[uninit]: \ No newline at end of file +[uninit]: uninitialized.html \ No newline at end of file From 8f531d9d7e058222cb13a9987a80431906d524b9 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sat, 20 Jun 2015 14:34:17 -0700 Subject: [PATCH 015/104] progress --- README.md | 4 +- conversions.md | 205 ++++++++++++++++++++++++++++----- intro.md | 164 +++++++++++++++++++++----- raii.md | 305 ++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 593 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 4227beb19de1..e391c9a48ea3 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# turpl +# The Unsafe Rust Programming Language (Book) + +[Start at the intro](http://www.cglab.ca/~abeinges/blah/turpl/intro.html) \ No newline at end of file diff --git a/conversions.md b/conversions.md index 4fe86284a31e..ae3ce9e31255 100644 --- a/conversions.md +++ b/conversions.md @@ -5,8 +5,6 @@ are just there to help us use those bits right. Needing to reinterpret those pil of bits as different types is a common problem and Rust consequently gives you several ways to do that. -# Safe Rust - First we'll look at the ways that *Safe Rust* gives you to reinterpret values. The most trivial way to do this is to just destructure a value into its constituent parts and then build a new type out of them. e.g. @@ -31,42 +29,191 @@ fn reinterpret(foo: Foo) -> Bar { But this is, at best, annoying to do. For common conversions, rust provides more ergonomic alternatives. -## Auto-Deref + + + +# Auto-Deref + +(Maybe nix this in favour of receiver coercions) Deref is a trait that allows you to overload the unary `*` to specify a type you dereference to. This is largely only intended to be implemented by pointer types like `&`, `Box`, and `Rc`. The dot operator will automatically perform -automatic dereferencing, so that foo.bar() will work uniformly on `Foo`, `&Foo`, `&&Foo`, -`&Rc>>` and so-on. Search bottoms out on the *first* match, +automatic dereferencing, so that foo.bar() will work uniformly on `Foo`, `&Foo`, ` +&&Foo`, `&Rc>>` and so-on. Search bottoms out on the *first* match, so implementing methods on pointers is generally to be avoided, as it will shadow "actual" methods. -## Coercions -Types can implicitly be coerced to change in certain contexts. These changes are generally -just *weakening* of types, largely focused around pointers. They mostly exist to make -Rust "just work" in more cases. For instance -`&mut T` coerces to `&T`, and `&T` coerces to `*const T`. The most useful coercion you will -actually think about it is probably the general *Deref Coercion*: `&T` coerces to `&U` when -`T: Deref`. This enables us to pass an `&String` where an `&str` is expected, for instance. -## Casts -Casts are a superset of coercions: every coercion can be explicitly invoked via a cast, -but some changes require a cast. These "true casts" are generally regarded as dangerous or -problematic actions. True casts revolves around raw pointers and the primitive numeric -types. Here's an exhaustive list of all the true casts: +# Coercions -TODO: gank the RFC for sweet casts +Types can implicitly be coerced to change in certain contexts. These changes are +generally just *weakening* of types, largely focused around pointers and lifetimes. +They mostly exist to make Rust "just work" in more cases, and are largely harmless. -For number -> number casts, there are quite a few cases to consider: +Here's all the kinds of coercion: + + +Coercion is allowed between the following types: + +* `T` to `U` if `T` is a [subtype](lifetimes.html#subtyping-and-variance) + of `U` (the 'identity' case); + +* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` + (transitivity case); + +* `&mut T` to `&T`; + +* `*mut T` to `*const T`; + +* `&T` to `*const T`; + +* `&mut T` to `*mut T`; + +* `T` to `U` if `T` implements `CoerceUnsized` (see below) and `T = Foo<...>` + and `U = Foo<...>`; + +* From TyCtor(`T`) to TyCtor(coerce_inner(`T`)); + +where TyCtor(`T`) is one of `&T`, `&mut T`, `*const T`, `*mut T`, or `Box`. +And where coerce_inner is defined as + +* coerce_inner(`[T, ..n]`) = `[T]`; + +* coerce_inner(`T`) = `U` where `T` is a concrete type which implements the + trait `U`; + +* coerce_inner(`T`) = `U` where `T` is a sub-trait of `U`; + +* coerce_inner(`Foo<..., T, ...>`) = `Foo<..., coerce_inner(T), ...>` where + `Foo` is a struct and only the last field has type `T` and `T` is not part of + the type of any other fields; + +* coerce_inner(`(..., T)`) = `(..., coerce_inner(T))`. + +Coercions only occur at a *coercion site*. Exhaustively, the coercion sites +are: + +* In `let` statements where an explicit type is given: in `let _: U = e;`, `e` + is coerced to to have type `U`; + +* In statics and consts, similarly to `let` statements; + +* In argument position for function calls. The value being coerced is the actual + parameter and it is coerced to the type of the formal parameter. For example, + where `foo` is defined as `fn foo(x: U) { ... }` and is called with `foo(e);`, + `e` is coerced to have type `U`; + +* Where a field of a struct or variant is instantiated. E.g., where `struct Foo + { x: U }` and the instantiation is `Foo { x: e }`, `e` is coerced to to have + type `U`; + +* The result of a function, either the final line of a block if it is not semi- + colon terminated or any expression in a `return` statement. For example, for + `fn foo() -> U { e }`, `e` is coerced to to have type `U`; + +If the expression in one of these coercion sites is a coercion-propagating +expression, then the relevant sub-expressions in that expression are also +coercion sites. Propagation recurses from these new coercion sites. Propagating +expressions and their relevant sub-expressions are: + +* array literals, where the array has type `[U, ..n]`, each sub-expression in + the array literal is a coercion site for coercion to type `U`; + +* array literals with repeating syntax, where the array has type `[U, ..n]`, the + repeated sub-expression is a coercion site for coercion to type `U`; + +* tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`, each + sub-expression is a coercion site for the respective type, e.g., the zero-th + sub-expression is a coercion site to `U_0`; + +* the box expression, if the expression has type `Box`, the sub-expression is + a coercion site to `U`; + +* parenthesised sub-expressions (`(e)`), if the expression has type `U`, then + the sub-expression is a coercion site to `U`; + +* blocks, if a block has type `U`, then the last expression in the block (if it + is not semicolon-terminated) is a coercion site to `U`. This includes blocks + which are part of control flow statements, such as `if`/`else`, if the block + has a known type. + + +Note that we do not perform coercions when matching traits (except for +receivers, see below). If there is an impl for some type `U` and `T` coerces to +`U`, that does not constitute an implementation for `T`. For example, the +following will not type check, even though it is OK to coerce `t` to `&T` and +there is an impl for `&T`: + +``` +struct T; +trait Trait {} + +fn foo(t: X) {} + +impl<'a> Trait for &'a T {} + + +fn main() { + let t: &mut T = &mut T; + foo(t); //~ ERROR failed to find an implementation of trait Trait for &mut T +} +``` + +In a cast expression, `e as U`, the compiler will first attempt to coerce `e` to +`U`, only if that fails will the conversion rules for casts (see below) be +applied. + + + + +# Casts + +Casts are a superset of coercions: every coercion can be explicitly invoked via a +cast, but some conversions *require* a cast. These "true casts" are generally regarded +as dangerous or problematic actions. True casts revolve around raw pointers and +the primitive numeric types. True casts aren't checked. + +Here's an exhaustive list of all the true casts: + + * `e` has type `T` and `T` coerces to `U`; *coercion-cast* + * `e` has type `*T`, `U` is `*U_0`, and either `U_0: Sized` or + unsize_kind(`T`) = unsize_kind(`U_0`); *ptr-ptr-cast* + * `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast* + * `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast* + * `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast* + * `e` is a C-like enum and `U` is an integer type; *enum-cast* + * `e` has type `bool` or `char` and `U` is an integer; *prim-int-cast* + * `e` has type `u8` and `U` is `char`; *u8-char-cast* + * `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast* + * `e` is a function pointer type and `U` has type `*T`, + while `T: Sized`; *fptr-ptr-cast* + * `e` is a function pointer type and `U` is an integer; *fptr-addr-cast* + +where `&.T` and `*T` are references of either mutability, +and where unsize_kind(`T`) is the kind of the unsize info +in `T` - the vtable for a trait definition (e.g. `fmt::Display` or +`Iterator`, not `Iterator`) or a length (or `()` if `T: Sized`). + +Note that lengths are not adjusted when casting raw slices - +`T: *const [u16] as *const [u8]` creates a slice that only includes +half of the original memory. + +Casting is not transitive, that is, even if `e as U1 as U2` is a valid +expression, `e as U2` is not necessarily so (in fact it will only be valid if +`U1` coerces to `U2`). + +For numeric casts, there are quite a few cases to consider: * casting between two integers of the same size (e.g. i32 -> u32) is a no-op * casting from a smaller integer to a bigger integer (e.g. u32 -> u8) will truncate * casting from a larger integer to a smaller integer (e.g. u8 -> u32) will - * zero-extend if unsigned - * sign-extend if signed -* casting from a float to an integer will round the float towards zero. + * zero-extend if the target is unsigned + * sign-extend if the target is signed +* casting from a float to an integer will: + * round the float towards zero if finite * **NOTE: currently this will cause Undefined Behaviour if the rounded value cannot be represented by the target integer type**. This is a bug and will be fixed. @@ -86,18 +233,14 @@ well as interpret integers as addresses. However it is impossible to actually `unsafe`. -## Conversion Traits -For full formal specification of all the kinds of coercions and coercion sites, see: -https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md + +# Conversion Traits + +TODO -* Coercions -* Casts -* Conversion Traits (Into/As/...) -# Unsafe Rust +# Transmuting Types -* raw ptr casts -* mem::transmute diff --git a/intro.md b/intro.md index 7d3036fe5ec4..b955d78bd38b 100644 --- a/intro.md +++ b/intro.md @@ -1,6 +1,11 @@ % The Unsafe Rust Programming Language -This document seeks to complement [The Rust Programming Language][] (TRPL). +**This document is about advanced functionality and low-level development practices +in the Rust Programming Language. Most of the things discussed won't matter +to the average Rust programmer. However if you wish to correctly write unsafe +code in Rust, this text contains invaluable information.** + +This document seeks to complement [The Rust Programming Language Book][] (TRPL). Where TRPL introduces the language and teaches the basics, TURPL dives deep into the specification of the language, and all the nasty bits necessary to write Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know @@ -10,7 +15,7 @@ stack or heap, we will not explain the syntax. -# Sections +# Chapters * [Data Layout](data.html) * [Ownership and Lifetimes](lifetimes.html) @@ -48,7 +53,6 @@ Rust is 100% safe by default. Even when you *opt out* of safety in Rust, it is a action. In deciding to work with unchecked uninitialized memory, this does not suddenly make dangling or null pointers a problem. When using unchecked indexing on `x`, one does not have to suddenly worry about indexing out of bounds on `y`. - C and C++, by contrast, have pervasive unsafety baked into the language. Even the modern best practices like `unique_ptr` have various safety pitfalls. @@ -85,17 +89,19 @@ To be more concrete, Rust cares about preventing the following things: * Breaking the pointer aliasing rules (TBD) (llvm rules + noalias on &mut and & w/o UnsafeCell) * Invoking Undefined Behaviour (in e.g. compiler intrinsics) * Producing invalid primitive values: - * dangling/null references - * a `bool` that isn't 0 or 1 - * an undefined `enum` discriminant - * a `char` larger than char::MAX - * A non-utf8 `str` + * dangling/null references + * a `bool` that isn't 0 or 1 + * an undefined `enum` discriminant + * a `char` larger than char::MAX + * A non-utf8 `str` * Unwinding into an FFI function * Causing a data race -However libraries are free to declare arbitrary requirements if they could transitively -cause memory safety issues. However Rust is otherwise quite permisive with respect to -other dubious operations. Rust considers it "safe" to: +That's it. That's all the Undefined Behaviour in Rust. Libraries are free to +declare arbitrary requirements if they could transitively cause memory safety +issues, but it all boils down to the above actions. Rust is otherwise +quite permisive with respect to other dubious operations. Rust considers it +"safe" to: * Deadlock * Leak memory @@ -106,27 +112,27 @@ other dubious operations. Rust considers it "safe" to: However any program that does such a thing is *probably* incorrect. Rust just isn't interested in modeling these problems, as they are much harder to prevent in general, -and it's basically impossible to prevent incorrect programs from getting written. +and it's literally impossible to prevent incorrect programs from getting written. -Their are several places `unsafe` can appear in Rust today, which can largely be +There are several places `unsafe` can appear in Rust today, which can largely be grouped into two categories: * There are unchecked contracts here. To declare you understand this, I require you to write `unsafe` elsewhere: * On functions, `unsafe` is declaring the function to be unsafe to call. Users - of the function must check the documentation to determine what this means, - and then have to write `unsafe` somewhere to identify that they're aware of + of the function must check the documentation to determine what this means, + and then have to write `unsafe` somewhere to identify that they're aware of the danger. * On trait declarations, `unsafe` is declaring that *implementing* the trait - is an unsafe operation, as it has contracts that other unsafe code is free to - trust blindly. + is an unsafe operation, as it has contracts that other unsafe code is free to + trust blindly. * I am declaring that I have, to the best of my knowledge, adhered to the unchecked contracts: * On trait implementations, `unsafe` is declaring that the contract of the - `unsafe` trait has been upheld. + `unsafe` trait has been upheld. * On blocks, `unsafe` is declaring any unsafety from an unsafe - operation to be handled, and therefore the parent function is safe. + operation within to be handled, and therefore the parent function is safe. There is also `#[unsafe_no_drop_flag]`, which is a special case that exists for historical reasons and is in the process of being phased out. See the section on @@ -135,21 +141,21 @@ destructors for details. Some examples of unsafe functions: * `slice::get_unchecked` will perform unchecked indexing, allowing memory -safety to be freely violated. + safety to be freely violated. * `ptr::offset` in an intrinsic that invokes Undefined Behaviour if it is -not "in bounds" as defined by LLVM (see the lifetimes section for details). + not "in bounds" as defined by LLVM (see the lifetimes section for details). * `mem::transmute` reinterprets some value as having the given type, -bypassing type safety in arbitrary ways. (see the conversions section for details) + bypassing type safety in arbitrary ways. (see the conversions section for details) * All FFI functions are `unsafe` because they can do arbitrary things. -C being an obvious culprit, but generally any language can do something -that Rust isn't happy about. (see the FFI section for details) + C being an obvious culprit, but generally any language can do something + that Rust isn't happy about. (see the FFI section for details) As of Rust 1.0 there are exactly two unsafe traits: * `Send` is a marker trait (it has no actual API) that promises implementors -are safe to send to another thread. + are safe to send to another thread. * `Sync` is a marker trait that promises that threads can safely share -implementors through a shared reference. + implementors through a shared reference. All other traits that declare any kind of contract *really* can't be trusted to adhere to their contract when memory-safety is at stake. For instance Rust has @@ -167,3 +173,109 @@ thread safety is a sort of fundamental thing that a program can't really guard against locally (even by-value message passing still requires a notion Send). + + +# Working with unsafe + +Rust generally only gives us the tools to talk about safety in a scoped and +binary manner. Unfortunately reality is significantly more complicated than that. +For instance, consider the following toy function: + +```rust +fn do_idx(idx: usize, arr: &[u8]) -> Option { + if idx < arr.len() { + unsafe { + Some(*arr.get_unchecked(idx)) + } + } else { + None + } +} +``` + +Clearly, this function is safe. We check that the index is in bounds, and if it +is, index into the array in an unchecked manner. But even in such a trivial +function, the scope of the unsafe block is questionable. Consider changing the +`<` to a `<=`: + +```rust +fn do_idx(idx: usize, arr: &[u8]) -> Option { + if idx <= arr.len() { + unsafe { + Some(*arr.get_unchecked(idx)) + } + } else { + None + } +} +``` + +This program is now unsound, an yet *we only modified safe code*. This is the +fundamental problem of safety: it's non-local. The soundness of our unsafe +operations necessarily depends on the state established by "safe" operations. +Although safety *is* modular (we *still* don't need to worry about about +unrelated safety issues like uninitialized memory), it quickly contaminates the +surrounding code. + +Trickier than that is when we get into actual statefulness. Consider a simple +implementation of `Vec`: + +```rust +// Note this defintion is insufficient. See the section on lifetimes. +struct Vec { + ptr: *mut T, + len: usize, + cap: usize, +} + +// Note this implementation does not correctly handle zero-sized types. +// We currently live in a nice imaginary world of only postive fixed-size +// types. +impl Vec { + fn new() -> Self { + Vec { ptr: heap::EMPTY, len: 0, cap: 0 } + } + + fn push(&mut self, elem: T) { + if self.len == self.cap { + // not important for this example + self.reallocate(); + } + unsafe { + ptr::write(self.ptr.offset(len as isize), elem); + self.len += 1; + } + } + + fn pop(&mut self) -> Option { + if self.len > 0 { + self.len -= 1; + unsafe { + Some(ptr::read(self.ptr.offset(self.len as isize))) + } + } else { + None + } + } +} +``` + +This code is simple enough to reasonably audit and verify. Now consider +adding the following method: + +```rust + fn make_room(&mut self) { + // grow the capacity + self.cap += 1; + } +``` + +This code is safe, but it is also completely unsound. Changing the capacity +violates the invariants of Vec (that `cap` reflects the allocated space in the +Vec). This is not something the rest of `Vec` can guard against. It *has* to +trust the capacity field because there's no way to verify it. + +`unsafe` does more than pollute a whole function: it pollutes a whole *module*. +Generally, the only bullet-proof way to limit the scope of unsafe code is at the +module boundary with privacy. + diff --git a/raii.md b/raii.md index 76363030b848..679c1dd3d599 100644 --- a/raii.md +++ b/raii.md @@ -13,7 +13,12 @@ point, really: Rust is about control. However we are not limited to just memory. Pretty much every other system resource like a thread, file, or socket is exposed through this kind of API. -So, how does RAII work in Rust? Unlike C++, Rust does not come with a slew on builtin + + + +# Constructors + +Unlike C++, Rust does not come with a slew of builtin kinds of constructor. There are no Copy, Default, Assignment, Move, or whatever constructors. This largely has to do with Rust's philosophy of being explicit. @@ -25,20 +30,26 @@ not happening in Rust (safely). Assignment and copy constructors similarly don't exist because move semantics are the *default* in rust. At most `x = y` just moves the bits of y into the x variable. Rust does provide two facilities for going back to C++'s copy-oriented semantics: `Copy` and `Clone`. Clone is our -moral equivalent of copy constructor, but it's never implicitly invoked. You have to explicitly +moral equivalent of a copy constructor, but it's never implicitly invoked. You have to explicitly call `clone` on an element you want to be cloned. Copy is a special case of Clone where the -implementation is just "duplicate the bitwise representation". Copy types *are* implicitely +implementation is just "copy the bits". Copy types *are* implicitly cloned whenever they're moved, but because of the definition of Copy this just means *not* -treating the old copy as uninitialized; a no-op. +treating the old copy as uninitialized -- a no-op. While Rust provides a `Default` trait for specifying the moral equivalent of a default constructor, it's incredibly rare for this trait to be used. This is because variables -aren't implicitely initialized (see [working with uninitialized memory][uninit] for details). +aren't implicitly initialized (see [working with uninitialized memory][uninit] for details). Default is basically only useful for generic programming. -More often than not, in a concrete case a type will provide a static `new` method for any -kind of "default" constructor. This has no relation to `new` in other languages and has no -special meaning. It's just a naming convention. +In concrete contexts, a type will provide a static `new` method for any +kind of "default" constructor. This has no relation to `new` in other +languages and has no special meaning. It's just a naming convention. + + + + + +# Destructors What the language *does* provide is full-blown automatic destructors through the `Drop` trait, which provides the following method: @@ -49,12 +60,19 @@ fn drop(&mut self); This method gives the type time to somehow finish what it was doing. **After `drop` is run, Rust will recursively try to drop all of the fields of the `self` struct**. This is a -convenience feature so that you don't have to write "destructor boilerplate" dropping -children. **There is no way to prevent this in Rust 1.0**. Also note that `&mut self` means -that even if you *could* supress recursive Drop, Rust will prevent you from e.g. moving fields -out of self. For most types, this is totally fine: they own all their data, there's no -additional state passed into drop to try to send it to, and `self` is about to be marked as -uninitialized (and therefore inaccessible). +convenience feature so that you don't have to write "destructor boilerplate" to drop +children. If a struct has no special logic for being dropped other than dropping its +children, then it means `Drop` doesn't need to be implemented at all! + +**There is no way to prevent this behaviour in Rust 1.0**. + +Note that taking `&mut self` means that even if you *could* suppress recursive Drop, +Rust will prevent you from e.g. moving fields out of self. For most types, this +is totally fine: + +* They own all their data (they don't contain pointers to elsewhere). +* There's no additional state passed into drop to try to send things. +* `self` is about to be marked as uninitialized (and therefore inaccessible). For instance, a custom implementation of `Box` might write `Drop` like this: @@ -73,7 +91,7 @@ impl Drop for Box { and this works fine because when Rust goes to drop the `ptr` field it just sees a *mut that has no actual `Drop` implementation. Similarly nothing can use-after-free the `ptr` because -the Box is completely gone. +the Box is immediately marked as uninitialized. However this wouldn't work: @@ -130,14 +148,14 @@ enum Link { } ``` -will have its inner Box field dropped *if and only if* a value stores the Next variant. +will have its inner Box field dropped *if and only if* an instance stores the Next variant. In general this works really nice because you don't need to worry about adding/removing -dtors when you refactor your data layout. Still there's certainly many valid usecases for +drops when you refactor your data layout. Still there's certainly many valid usecases for needing to do trickier things with destructors. -The classic safe solution to blocking recursive drop semantics and allowing moving out -of Self is to use an Option: +The classic safe solution to overriding recursive drop and allowing moving out +of Self during `drop` is to use an Option: ```rust struct Box{ ptr: *mut T } @@ -158,22 +176,255 @@ impl Drop for SuperBox { unsafe { // Hyper-optimized: deallocate the box's contents for it // without `drop`ing the contents. Need to set the `box` - // fields as `None` to prevent Rust from trying to Drop it. + // field as `None` to prevent Rust from trying to Drop it. heap::deallocate(self.box.take().unwrap().ptr); } } } ``` -However this has fairly odd semantics: you're saying that a field that *should* always be Some -may be None, just because that happens in the dtor. Of course this conversely makes a lot of sense: -you can call arbitrary methods on self during the destructor, and this should prevent you from -ever doing so after deinitializing the field. Not that it will prevent you from producing any other +However this has fairly odd semantics: you're saying that a field that *should* always +be Some may be None, just because that happens in the destructor. Of course this +conversely makes a lot of sense: you can call arbitrary methods on self during +the destructor, and this should prevent you from ever doing so after deinitializing +the field. Not that it will prevent you from producing any other arbitrarily invalid state in there. -On balance this is an ok choice. Certainly if you're just getting started. +On balance this is an ok choice. Certainly what you should reach for by default. +However, in the future we expect there to be a first-class way to announce that +a field shouldn't be automatically dropped. -In the future, we expect there to be a first-class way to announce that a field -should be automatically dropped. + + + +# Leaking + +Ownership based resource management is intended to simplify composition. You +acquire resources when you create the object, and you release the resources +when it gets destroyed. Since destruction is handled for you, it means you +can't forget to release the resources, and it happens as soon as possible! +Surely this is perfect and all of our problems are solved. + +Everything is terrible and we have new and exotic problems to try to solve. + +Many people like to believe that Rust eliminates resource leaks, but this +is absolutely not the case, no matter how you look at it. In the strictest +sense, "leaking" is so abstract as to be unpreventable. It's quite trivial +to initialize a collection at the start of a program, fill it with tons of +objects with destructors, and then enter an infinite event loop that never +refers to it. The collection will sit around uselessly, holding on to its +precious resources until the program terminates (at which point all those +resources would have been reclaimed by the OS anyway). + +We may consider a more restricted form of leak: failing to free memory that +is unreachable. Rust also doesn't prevent this. In fact Rust has a *function +for doing this*: `mem::forget`. This function consumes the value it is passed +*and then doesn't run its destructor*. + +In the past `mem::forget` was marked as unsafe as a sort of lint against using +it, since failing to call a destructor is generally not a well-behaved thing to +do (though useful for some special unsafe code). However this was generally +determined to be an untenable stance to take: there are *many* ways to fail to +call a destructor in safe code. The most famous example is creating a cycle +of reference counted pointers using interior mutability. + +It is reasonable for safe code to assume that destructor leaks do not happen, +as any program that leaks destructors is probably wrong. However *unsafe* code +cannot rely on destructors to be run to be *safe*. For most types this doesn't +matter: if you leak the destructor then the type is *by definition* inaccessible, +so it doesn't matter, right? e.g. if you leak a `Box` then you waste some +memory but that's hardly going to violate memory-safety. + +However where we must be careful with destructor leaks are *proxy* types. +These are types which manage access to a distinct object, but don't actually +own it. Proxy objects are quite rare. Proxy objects you'll need to care about +are even rarer. However we'll focus on two interesting examples in the +standard library: + +* `vec::Drain` +* `Rc` + + + + +## Drain + +`drain` is a collections API that moves data out of the container without +consuming the container. This enables us to reuse the allocation of a `Vec` +after claiming ownership over all of its contents. drain produces an iterator +(Drain) that returns the contents of the Vec by-value. + +Now, consider Drain in the middle of iteration: some values have been moved out, +and others haven't. This means that part of the Vec is now full of logically +uninitialized data! We could backshift all the elements in the Vec every time we +remove a value, but this would have pretty catastrophic performance consequences. + +Instead, we would like Drain to *fix* the Vec's backing storage when it is +dropped. It should run itself to completion, backshift any elements that weren't +removed (drain supports subranges), and then fix Vec's `len`. It's even +unwinding-safe! Easy! + +Now consider the following: + +``` +let mut vec = vec![Box::new(0); 4]; + +{ + // start draining, vec can no longer be accessed + let mut drainer = vec.drain(..); + + // pull out two elements and immediately drop them + drainer.next(); + drainer.next(); + + // get rid of drainer, but don't call its destructor + mem::forget(drainer); +} + +// Oops, vec[0] was dropped, we're reading a pointer into free'd memory! +println!("{}", vec[0]); +``` + +This is pretty clearly Not Good. Unfortunately, we're kind've stuck between +a rock and a hard place: maintaining consistent state at every step has +an enormous cost (and would negate any benefits of the API). Failing to maintain +consistent state gives us Undefined Behaviour in safe code (making the API +unsound). + +So what can we do? Well, we can pick a trivially consistent state: set the Vec's +len to be 0 when we *start* the iteration, and fix it up if necessary in the +destructor. That way, if everything executes like normal we get the desired +behaviour with minimal overhead. But if someone has the *audacity* to mem::forget +us in the middle of the iteration, all that does is *leak even more* (and possibly +leave the Vec in an *unexpected* but consistent state). Since we've +accepted that mem::forget is safe, this is definitely safe. We call leaks causing +more leaks a *leak amplification*. + + + + +## Rc + +Rc is an interesting case because at first glance it doesn't appear to be a +proxy value at all. After all, it manages the data it points to, and dropping +all the Rcs for a value will drop that value. leaking an Rc doesn't seem like +it would be particularly dangerous. It will leave the refcount permanently +incremented and prevent the data from being freed or dropped, but that seems +just like Box, right? + +Nope. + +Let's consider a simplified implementation of Rc: + +```rust +struct Rc { + ptr: *mut RcBox, +} + +struct RcBox { + data: T, + ref_count: usize, +} + +impl Rc { + fn new(data: T) -> Self { + unsafe { + // Wouldn't it be nice if heap::allocate worked like this? + let ptr = heap::allocate>(); + ptr::write(ptr, RcBox { + data: data, + ref_count: 1, + }); + Rc { ptr: ptr } + } + } + + fn clone(&self) -> Self { + unsafe { + (*self.ptr).ref_count += 1; + } + Rc { ptr: self.ptr } + } +} + +impl Drop for Rc { + fn drop(&mut self) { + unsafe { + let inner = &mut ; + (*self.ptr).ref_count -= 1; + if (*self.ptr).ref_count == 0 { + // drop the data and then free it + ptr::read(self.ptr); + heap::deallocate(self.ptr); + } + } + } +} +``` + +This code contains an implicit and subtle assumption: ref_count can fit in a +`usize`, because there can't be more than `usize::MAX` Rcs in memory. However +this itself assumes that the ref_count accurately reflects the number of Rcs +in memory, which we know is false with mem::forget. Using mem::forget we can +overflow the ref_count, and then get it down to 0 with outstanding Rcs. Then we +can happily use-after-free the inner data. Bad Bad Not Good. + +This can be solved by *saturating* the ref_count, which is sound because +decreasing the refcount by `n` still requires `n` Rcs simultaneously living +in memory. + + + + +## thread::scoped + +The thread::scoped API intends to allow threads to be spawned that reference +data on the stack without any synchronization over that data. Usage looked like: + +```rust +let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +{ + let guards = vec![]; + for x in &mut data { + // Move the mutable reference into the closure, and execute + // it on a different thread. The closure has a lifetime bound + // by the lifetime of the mutable reference `x` we store in it. + // The guard that is returned is in turn assigned the lifetime + // of the closure, so it also mutably borrows `data` as `x` did. + // This means we cannot access `data` until the guard goes away. + let guard = thread::scoped(move || { + *x *= 2; + }); + // store the thread's guard for later + guards.push(guard); + } + // All guards are dropped here, forcing the threads to join + // (this thread blocks here until the others terminate). + // Once the threads join, the borrow expires and the data becomes + // accessible again in this thread. +} +// data is definitely mutated here. +``` + +In principle, this totally works! Rust's ownership system perfectly ensures it! +...except it relies on a destructor being called to be safe. + +``` +let mut data = Box::new(0); +{ + let guard = thread::scoped(|| { + // This is at best a data race. At worst, it's *also* a use-after-free. + *data += 1; + }); + // Because the guard is forgotten, expiring the loan without blocking this + // thread. + mem::forget(guard); +} +// So the Box is dropped here while the scoped thread may or may not be trying +// to access it. +``` + +Dang. Here the destructor running was pretty fundamental to the API, and it had +to be scrapped in favour of a completely different design. [uninit]: uninitialized.html \ No newline at end of file From 069681a95327d8b49a26a8fd60aa6a9ecaaf52c4 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sat, 20 Jun 2015 23:15:48 -0700 Subject: [PATCH 016/104] vec exmaple maybe --- conversions.md | 43 +++++++++++---- intro.md | 16 +----- vec.md | 141 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 26 deletions(-) create mode 100644 vec.md diff --git a/conversions.md b/conversions.md index ae3ce9e31255..7467decb490b 100644 --- a/conversions.md +++ b/conversions.md @@ -168,6 +168,8 @@ applied. +TODO: receiver coercions? + # Casts @@ -212,11 +214,10 @@ For numeric casts, there are quite a few cases to consider: * casting from a larger integer to a smaller integer (e.g. u8 -> u32) will * zero-extend if the target is unsigned * sign-extend if the target is signed -* casting from a float to an integer will: - * round the float towards zero if finite +* casting from a float to an integer will round the float towards zero * **NOTE: currently this will cause Undefined Behaviour if the rounded value cannot be represented by the target integer type**. This is a bug - and will be fixed. + and will be fixed. (TODO: figure out what Inf and NaN do) * casting from an integer to float will produce the floating point representation of the integer, rounded if necessary (rounding strategy unspecified). * casting from an f32 to an f64 is perfect and lossless. @@ -226,21 +227,41 @@ For numeric casts, there are quite a few cases to consider: is finite but larger or smaller than the largest or smallest finite value representable by f32**. This is a bug and will be fixed. -The casts involving rawptrs also allow us to completely bypass type-safety -by re-interpretting a pointer of T to a pointer of U for arbitrary types, as -well as interpret integers as addresses. However it is impossible to actually -*capitalize* on this violation in Safe Rust, because derefencing a raw ptr is -`unsafe`. - - # Conversion Traits -TODO +TODO? # Transmuting Types +Get out of our way type system! We're going to reinterpret these bits or die +trying! Even though this book is all about doing things that are unsafe, I really +can't emphasize that you should deeply think about finding Another Way than the +operations covered in this section. This is really, truly, the most horribly +unsafe thing you can do in Rust. The railguards here are dental floss. + +`mem::transmute` takes a value of type `T` and reinterprets it to have +type `U`. The only restriction is that the `T` and `U` are verified to have the +same size. The ways to cause Undefined Behaviour with this are mind boggling. + +* First and foremost, creating an instance of *any* type with an invalid state + is going to cause arbitrary chaos that can't really be predicted. +* Transmute has an overloaded return type. If you do not specify the return type + it may produce a surprising type to satisfy inference. +* Making a primitive with an invalid value is UB +* Transmuting between non-repr(C) types is UB +* Transmuting an & to &mut is UB +* Transmuting to a reference without an explicitly provided lifetime + produces an [unbound lifetime](lifetimes.html#unbounded-lifetimes) + +`mem::transmute_copy` somehow manages to be *even more* wildly unsafe than +this. It copies `size_of` bytes out of an `&T` and interprets them as a `U`. +The size check that `mem::transmute` has is gone (as it may be valid to copy +out a prefix), though it is Undefined Behaviour for `U` to be larger than `T`. + +Also of course you can get most of the functionality of these functions using +pointer casts. diff --git a/intro.md b/intro.md index b955d78bd38b..f380f98a7dc0 100644 --- a/intro.md +++ b/intro.md @@ -23,6 +23,7 @@ stack or heap, we will not explain the syntax. * [Uninitialized Memory](uninitialized.html) * [Ownership-oriented resource management (RAII)](raii.html) * [Concurrency](concurrency.html) +* [Example: Implementing Vec](vec.html) @@ -232,10 +233,6 @@ struct Vec { // We currently live in a nice imaginary world of only postive fixed-size // types. impl Vec { - fn new() -> Self { - Vec { ptr: heap::EMPTY, len: 0, cap: 0 } - } - fn push(&mut self, elem: T) { if self.len == self.cap { // not important for this example @@ -246,17 +243,6 @@ impl Vec { self.len += 1; } } - - fn pop(&mut self) -> Option { - if self.len > 0 { - self.len -= 1; - unsafe { - Some(ptr::read(self.ptr.offset(self.len as isize))) - } - } else { - None - } - } } ``` diff --git a/vec.md b/vec.md new file mode 100644 index 000000000000..116626ffc39e --- /dev/null +++ b/vec.md @@ -0,0 +1,141 @@ +% Example: Implementing Vec + +To bring everything together, we're going to write `std::Vec` from scratch. +Because the all the best tools for writing unsafe code are unstable, this +project will only work on nightly (as of Rust 1.2.0). + +First off, we need to come up with the struct layout. Naively we want this +design: + +``` +struct Vec { + ptr: *mut T, + cap: usize, + len: usize, +} +``` + +And indeed this would compile. Unfortunately, it would be incorrect. The compiler +will give us too strict variance, so e.g. an `&Vec<&'static str>` couldn't be used +where an `&Vec<&'a str>` was expected. More importantly, it will give incorrect +ownership information to dropck, as it will conservatively assume we don't own +any values of type `T`. See [the chapter on ownership and lifetimes] +(lifetimes.html) for details. + +As we saw in the lifetimes chapter, we should use `Unique` in place of `*mut T` +when we have a raw pointer to an allocation we own: + + +``` +#![feature(unique)] + +use std::ptr::Unique; + +pub struct Vec { + ptr: Unique, + cap: usize, + len: usize, +} +``` + +As a recap, Unique is a wrapper around a raw pointer that declares that: + +* We own at least one value of type `T` +* We are Send/Sync iff `T` is Send/Sync +* Our pointer is never null (and therefore `Option` is null-pointer-optimized) + +That last point is subtle. First, it makes `Unique::new` unsafe to call, because +putting `null` inside of it is Undefined Behaviour. It also throws a +wrench in an important feature of Vec (and indeed all of the std collections): +an empty Vec doesn't actually allocate at all. So if we can't allocate, +but also can't put a null pointer in `ptr`, what do we do in +`Vec::new`? Well, we just put some other garbage in there! + +This is perfectly fine because we already have `cap == 0` as our sentinel for no +allocation. We don't even need to handle it specially in almost any code because +we usually need to check if `cap > len` or `len > 0` anyway. The traditional +Rust value to put here is `0x01`. The standard library actually exposes this +as `std::rt::heap::EMPTY`. There are quite a few places where we'll want to use +`heap::EMPTY` because there's no real allocation to talk about but `null` would +make the compiler angry. + +All of the `heap` API is totally unstable under the `alloc` feature, though. +We could trivially define `heap::EMPTY` ourselves, but we'll want the rest of +the `heap` API anyway, so let's just get that dependency over with. + +So: + +```rust +#![feature(alloc)] + +use std::rt::heap::EMPTY; +use std::mem; + +impl Vec { + fn new() -> Self { + assert!(mem::size_of::() != 0, "We're not ready to handle ZSTs"); + unsafe { + // need to cast EMPTY to the actual ptr type we want, let + // inference handle it. + Vec { ptr: Unique::new(heap::EMPTY as *mut _), len: 0, cap: 0 } + } + } +} +``` + +I slipped in that assert there because zero-sized types will require some +special handling throughout our code, and I want to defer the issue for now. +Without this assert, some of our early drafts will do some Very Bad Things. + +Next we need to figure out what to actually do when we *do* want space. For that, +we'll need to use the rest of the heap APIs. These basically allow us to +talk directly to Rust's instance of jemalloc. + +We'll also need a way to handle out-of-memory conditions. The standard library +calls the `abort` intrinsic, but calling intrinsics from normal Rust code is a +pretty bad idea. Unfortunately, the `abort` exposed by the standard library +allocates. Not something we want to do during `oom`! Instead, we'll call +`std::process::exit`. + +```rust +fn oom() { + ::std::process::exit(-9999); +} +``` + +Okay, now we can write growing: + +```rust +fn grow(&mut self) { + unsafe { + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + let new_cap = 2 * self.cap; + let ptr = heap::reallocate(*self.ptr as *mut _, + self.cap * elem_size, + new_cap * elem_size, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom() } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } +} +``` + +There's nothing particularly tricky in here: if we're totally empty, we need +to do a fresh allocation. Otherwise, we need to reallocate the current pointer. +Although we have a subtle bug here with the multiply overflow. + +TODO: rest of this + + From 9c87b1f8dbc3105e3e9338b169d0884ce7a902af Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 21 Jun 2015 15:30:09 +0530 Subject: [PATCH 017/104] fix double "however" --- data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data.md b/data.md index 110084824cfe..1d4365dd7511 100644 --- a/data.md +++ b/data.md @@ -236,7 +236,7 @@ one. This is the most important `repr`. It has fairly simple intent: do what C does. The order, size, and alignment of fields is exactly what you would expect from C or C++. Any type you expect to pass through an FFI boundary should have `repr(C)`, -as C is the lingua-franca of the programming world. However this is also necessary +as C is the lingua-franca of the programming world. This is also necessary to soundly do more elaborate tricks with data layout such as reintepretting values as a different type. From 709641bdf0c8778aab0f02b2f8cf631940fe7cbb Mon Sep 17 00:00:00 2001 From: Benjamin Herr Date: Sun, 21 Jun 2015 16:03:29 +0200 Subject: [PATCH 018/104] Tiny typo of "positive" --- intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intro.md b/intro.md index f380f98a7dc0..939ba4fa2129 100644 --- a/intro.md +++ b/intro.md @@ -230,7 +230,7 @@ struct Vec { } // Note this implementation does not correctly handle zero-sized types. -// We currently live in a nice imaginary world of only postive fixed-size +// We currently live in a nice imaginary world of only positive fixed-size // types. impl Vec { fn push(&mut self, elem: T) { From 74665906ab3f8a2808da7671022ac13f8fa12fbd Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 21 Jun 2015 18:54:41 +0300 Subject: [PATCH 019/104] Fix description of integer conversions --- conversions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/conversions.md b/conversions.md index 7467decb490b..b35409553f74 100644 --- a/conversions.md +++ b/conversions.md @@ -210,10 +210,10 @@ expression, `e as U2` is not necessarily so (in fact it will only be valid if For numeric casts, there are quite a few cases to consider: * casting between two integers of the same size (e.g. i32 -> u32) is a no-op -* casting from a smaller integer to a bigger integer (e.g. u32 -> u8) will truncate -* casting from a larger integer to a smaller integer (e.g. u8 -> u32) will - * zero-extend if the target is unsigned - * sign-extend if the target is signed +* casting from a larger integer to a smaller integer (e.g. u32 -> u8) will truncate +* casting from a smaller integer to a larger integer (e.g. u8 -> u32) will + * zero-extend if the source is unsigned + * sign-extend if the source is signed * casting from a float to an integer will round the float towards zero * **NOTE: currently this will cause Undefined Behaviour if the rounded value cannot be represented by the target integer type**. This is a bug From 8e75c50729b6c0e4a88cdd2ab3a4a242412fda5d Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sun, 21 Jun 2015 09:41:45 -0700 Subject: [PATCH 020/104] community fixups --- data.md | 2 +- lifetimes.md | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/data.md b/data.md index 1d4365dd7511..f9163caa4e00 100644 --- a/data.md +++ b/data.md @@ -88,7 +88,7 @@ struct Foo { } ``` -The former case quite simply wastes space. An optimal use of space therefore requires +The latter case quite simply wastes space. An optimal use of space therefore requires different monomorphizations to *have different field orderings*. **Note: this is a hypothetical optimization that is not yet implemented in Rust 1.0.0** diff --git a/lifetimes.md b/lifetimes.md index 4be895ff429b..d6711e7df41b 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -247,11 +247,11 @@ Of course, it might be bounded by the *wrong* lifetime, but this will usually just cause a compiler error, rather than allow memory safety to be trivially violated. -Within a function, bounding lifetimes is more error-prone. The safest route -is to just use a small function to ensure the lifetime is bound. However if -this is unacceptable, the reference can be placed in a location with a specific -lifetime. Unfortunately it's impossible to name all lifetimes involved in a -function. To get around this, you can in principle use `copy_lifetime`, though +Within a function, bounding lifetimes is more error-prone. The safest and easiest +way to bound a lifetime is to return it from a function with a bound lifetime. +However if this is unacceptable, the reference can be placed in a location with +a specific lifetime. Unfortunately it's impossible to name all lifetimes involved +in a function. To get around this, you can in principle use `copy_lifetime`, though these are unstable due to their awkward nature and questionable utility. @@ -425,7 +425,7 @@ must be invariant to avoid lifetime smuggling. `Fn` is the most confusing case, largely because contravariance is easily the most confusing kind of variance, and basically never comes up. To understand it, -consider a function that *takes* a function `len` that takes a function `F`. +consider a function `len` that takes a function `F`. ```rust fn len(func: F) -> usize @@ -435,8 +435,8 @@ fn len(func: F) -> usize } ``` -We require that F is a Fn that can take an `&'static str` and print a usize. Now -say we have a function that can take an `&'a str` (for *some* 'a). Such a function actually +We require that F is a Fn that can take an `&'static str` and returns a usize. Now +say we have a function that can take an `&'a str` (for *some* `'a`). Such a function actually accepts *more* inputs, since `&'static str` is a subtype of `&'a str`. Therefore `len` should happily accept such a function! @@ -643,8 +643,8 @@ trait Iterator { Given this definition, Self::Item has *no* connection to `self`. This means that we can call `next` several times in a row, and hold onto all the results *concurrently*. This is perfectly fine for by-value iterators, which have exactly -these semantics. It's also actually fine for shared references, as it's perfectly -fine to grab a huge pile of shared references to the same thing (although the +these semantics. It's also actually fine for shared references, as they admit +arbitrarily many references to the same thing (although the iterator needs to be a separate object from the thing being shared). But mutable references make this a mess. At first glance, they might seem completely incompatible with this API, as it would produce multiple mutable references to From bb3231522677c6cd2e3e667f488a06b71f097eb8 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sun, 21 Jun 2015 09:57:44 -0700 Subject: [PATCH 021/104] fix paper link --- lifetimes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lifetimes.md b/lifetimes.md index d6711e7df41b..fe4dc6270e19 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -58,7 +58,8 @@ a Cell is to copy the bits in or out. manages this through *runtime* checks. It is effectively a thread-unsafe read-write lock. -For more details see Dan Grossman's Existential Types for Imperative Languages: +For more details see Dan Grossman's *Existential Types for Imperative Languages*: + * [paper][grossman-paper] (Advanced) * [slides][grossman-slides] (Simple) From e5d39f7abe112cf7a4c73542841fa8c6784297cf Mon Sep 17 00:00:00 2001 From: Benjamin Herr Date: Tue, 23 Jun 2015 14:23:23 +0200 Subject: [PATCH 022/104] extra whitespace to render *-list as list This worked fine on github but isn't displayed as a bulleted list on http://www.cglab.ca/~abeinges/blah/turpl/concurrency.html#send-and-sync --- concurrency.md | 1 + 1 file changed, 1 insertion(+) diff --git a/concurrency.md b/concurrency.md index a382e4edf54c..fc04bd83811a 100644 --- a/concurrency.md +++ b/concurrency.md @@ -97,6 +97,7 @@ Almost all primitives are Send and Sync, and as a consequence pretty much all types you'll ever interact with are Send and Sync. Major exceptions include: + * raw pointers are neither Send nor Sync (because they have no safety guards) * `UnsafeCell` isn't Sync (and therefore `Cell` and `RefCell` aren't) * `Rc` isn't Send or Sync (because the refcount is shared and unsynchronized) From 328737216147b6107d6d28a405e3fd9cd1ded317 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 24 Jun 2015 10:59:30 -0700 Subject: [PATCH 023/104] so much Vec --- vec.md | 709 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 688 insertions(+), 21 deletions(-) diff --git a/vec.md b/vec.md index 116626ffc39e..d38265b429e4 100644 --- a/vec.md +++ b/vec.md @@ -1,17 +1,21 @@ % Example: Implementing Vec +TODO: audit for non-ZST offsets from heap::empty + To bring everything together, we're going to write `std::Vec` from scratch. Because the all the best tools for writing unsafe code are unstable, this project will only work on nightly (as of Rust 1.2.0). +# Layout + First off, we need to come up with the struct layout. Naively we want this design: ``` struct Vec { - ptr: *mut T, - cap: usize, - len: usize, + ptr: *mut T, + cap: usize, + len: usize, } ``` @@ -29,7 +33,7 @@ when we have a raw pointer to an allocation we own: ``` #![feature(unique)] -use std::ptr::Unique; +use std::ptr::{Unique, self}; pub struct Vec { ptr: Unique, @@ -63,6 +67,8 @@ All of the `heap` API is totally unstable under the `alloc` feature, though. We could trivially define `heap::EMPTY` ourselves, but we'll want the rest of the `heap` API anyway, so let's just get that dependency over with. +# Allocating Memory + So: ```rust @@ -72,14 +78,14 @@ use std::rt::heap::EMPTY; use std::mem; impl Vec { - fn new() -> Self { - assert!(mem::size_of::() != 0, "We're not ready to handle ZSTs"); - unsafe { - // need to cast EMPTY to the actual ptr type we want, let - // inference handle it. - Vec { ptr: Unique::new(heap::EMPTY as *mut _), len: 0, cap: 0 } - } - } + fn new() -> Self { + assert!(mem::size_of::() != 0, "We're not ready to handle ZSTs"); + unsafe { + // need to cast EMPTY to the actual ptr type we want, let + // inference handle it. + Vec { ptr: Unique::new(heap::EMPTY as *mut _), len: 0, cap: 0 } + } + } } ``` @@ -103,10 +109,38 @@ fn oom() { } ``` -Okay, now we can write growing: +Okay, now we can write growing. Roughly, we want to have this logic: + +```text +if cap == 0: + allocate() + cap = 1 +else + reallocate + cap *= 2 +``` + +But Rust's only supported allocator API is so low level that we'll need to +do a fair bit of extra work, though. We also need to guard against some special +conditions that can occur with really large allocations. In particular, we index +into arrays using unsigned integers, but `ptr::offset` takes signed integers. This +means Bad Things will happen if we ever manage to grow to contain more than +`isize::MAX` elements. Thankfully, this isn't something we need to worry about +in most cases. + +On 64-bit targets we're artifically limited to only 48-bits, so we'll run out +of memory far before we reach that point. However on 32-bit targets, particularly +those with extensions to use more of the address space, it's theoretically possible +to successfully allocate more than `isize::MAX` bytes of memory. Still, we only +really need to worry about that if we're allocating elements that are a byte large. +Anything else will use up too much space. + +However since this is a tutorial, we're not going to be particularly optimal here, +and just unconditionally check, rather than use clever platform-specific `cfg`s. ```rust fn grow(&mut self) { + // this is all pretty delicate, so let's say it's all unsafe unsafe { let align = mem::min_align_of::(); let elem_size = mem::size_of::(); @@ -115,16 +149,31 @@ fn grow(&mut self) { let ptr = heap::allocate(elem_size, align); (1, ptr) } else { - let new_cap = 2 * self.cap; + // as an invariant, we can assume that `self.cap < isize::MAX`, + // so this doesn't need to be checked. + let new_cap = self.cap * 2; + // Similarly this can't overflow due to previously allocating this + let old_num_bytes = self.cap * elem_size; + + // check that the new allocation doesn't exceed `isize::MAX` at all + // regardless of the actual size of the capacity. This combines the + // `new_cap <= isize::MAX` and `new_num_bytes <= usize::MAX` checks + // we need to make. We lose the ability to allocate e.g. 2/3rds of + // the address space with a single Vec of i16's on 32-bit though. + // Alas, poor Yorick -- I knew him, Horatio. + assert!(old_num_bytes <= (::std::isize::MAX as usize) / 2, + "capacity overflow"); + + let new_num_bytes = old_num_bytes * 2; let ptr = heap::reallocate(*self.ptr as *mut _, - self.cap * elem_size, - new_cap * elem_size, + old_num_bytes, + new_num_bytes, align); (new_cap, ptr) }; // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { oom() } + if ptr.is_null() { oom(); } self.ptr = Unique::new(ptr as *mut _); self.cap = new_cap; @@ -132,10 +181,628 @@ fn grow(&mut self) { } ``` -There's nothing particularly tricky in here: if we're totally empty, we need -to do a fresh allocation. Otherwise, we need to reallocate the current pointer. -Although we have a subtle bug here with the multiply overflow. +Nothing particularly tricky here. Just computing sizes and alignments and doing +some careful multiplication checks. -TODO: rest of this +# Push and Pop + +Alright. We can initialize. We can allocate. Let's actually implement some +functionality! Let's start with `push`. All it needs to do is check if we're +full to grow, unconditionally write to the next index, and then increment our +length. + +To do the write we have to be careful not to evaluate the memory we want to write +to. At worst, it's truly uninitialized memory from the allocator. At best it's the +bits of some old value we popped off. Either way, we can't just index to the memory +and dereference it, because that will evaluate the memory as a valid instance of +T. Worse, `foo[idx] = x` will try to call `drop` on the old value of `foo[idx]`! + +The correct way to do this is with `ptr::write`, which just blindly overwrites the +target address with the bits of the value we provide. No evaluation involved. + +For `push`, if the old len (before push was called) is 0, then we want to write +to the 0th index. So we should offset by the old len. + +```rust +pub fn push(&mut self, elem: T) { + if self.len == self.cap { self.grow(); } + + unsafe { + ptr::write(self.ptr.offset(self.len as isize), elem); + } + + // Can't fail, we'll OOM first. + self.len += 1; +} +``` + +Easy! How about `pop`? Although this time the index we want to access is +initialized, Rust won't just let us dereference the location of memory to move +the value out, because that *would* leave the memory uninitialized! For this we +need `ptr::read`, which just copies out the bits from the target address and +intrprets it as a value of type T. This will leave the memory at this address +*logically* uninitialized, even though there is in fact a perfectly good instance +of T there. + +For `pop`, if the old len is 1, we want to read out of the 0th index. So we +should offset by the *new* len. + +```rust +pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + self.len -= 1; + unsafe { + Some(ptr::read(self.ptr.offset(self.len as isize))) + } + } +} +``` + +# Deallocating + +Next we should implement Drop so that we don't massively leaks tons of resources. +The easiest way is to just call `pop` until it yields None, and then deallocate +our buffer. Note that calling `pop` is uneeded if `T: !Drop`. In theory we can +ask Rust if T needs_drop and omit the calls to `pop`. However in practice LLVM +is *really* good at removing simple side-effect free code like this, so I wouldn't +bother unless you notice it's not being stripped (in this case it is). + +We must not call `heap::deallocate` when `self.cap == 0`, as in this case we haven't +actually allocated any memory. +```rust +impl Drop for Vec { + fn drop(&mut self) { + if self.cap != 0 { + while let Some(_) = self.pop() { } + + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr, num_bytes, align); + } + } + } +} +``` + +# Deref + +Alright! We've got a decent minimal ArrayStack implemented. We can push, we can +pop, and we can clean up after ourselves. However there's a whole mess of functionality +we'd reasonably want. In particular, we have a proper array, but none of the slice +functionality. That's actually pretty easy to solve: we can implement `Deref`. +This will magically make our Vec coerce to and behave like a slice in all sorts of +conditions. + +All we need is `slice::from_raw_parts`. + +```rust +use std::ops::Deref; + +impl Deref for Vec { + type Target = [T]; + fn deref(&self) -> &[T] { + unsafe { + ::std::slice::from_raw_parts(*self.ptr, self.len) + } + } +} +``` + +And let's do DerefMut too: + +```rust +use std::ops::DerefMut; + +impl DerefMut for Vec { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { + ::std::slice::from_raw_parts_mut(*self.ptr, self.len) + } + } +} +``` + +Now we have `len`, `first`, `last`, indexing, slicing, sorting, `iter`, `iter_mut`, +and all other sorts of bells and whistles provided by slice. Sweet! + +# Insert and Remove + +Something *not* provided but slice is `insert` and `remove`, so let's do those next. + +Insert needs to shift all the elements at the target index to the right by one. +To do this we need to use `ptr::copy`, which is our version of C's `memmove`. +This copies some chunk of memory from one location to another, correctly handling +the case where the source and destination overlap (which will definitely happen +here). + +If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]` +using the *old* len. + +```rust +pub fn insert(&mut self, index: usize, elem: T) { + // Note: `<=` because it's valid to insert after everything + // which would be equivalent to push. + assert!(index <= self.len, "index out of bounds"); + if self.cap == self.len { self.grow(); } + + unsafe { + if index < self.len { + // ptr::copy(src, dest, len): "copy from source to dest len elems" + ptr::copy(self.ptr.offset(index as isize), + self.ptr.offset(index as isize + 1), + len - index); + } + ptr::write(self.ptr.offset(index as isize), elem); + self.len += 1; + } +} +``` + +Remove behaves in the opposite manner. We need to shift all the elements from +`[i+1 .. len + 1]` to `[i .. len]` using the *new* len. + +```rust +pub fn remove(&mut self, index: usize) -> T { + // Note: `<` because it's *not* valid to remove after everything + assert!(index < self.len, "index out of bounds"); + unsafe { + self.len -= 1; + let result = ptr::read(self.ptr.offset(index as isize)); + ptr::copy(self.ptr.offset(index as isize + 1), + self.ptr.offset(index as isize), + len - index); + result + } +} +``` + +# IntoIter + +Let's move on to writing iterators. `iter` and `iter_mut` have already been +written for us thanks to The Magic of Deref. However there's two interesting +iterators that Vec provides that slices can't: `into_iter` and `drain`. + +IntoIter consumes the Vec by-value, and can consequently yield its elements +by-value. In order to enable this, IntoIter needs to take control of Vec's +allocation. + +IntoIter needs to be DoubleEnded as well, to enable reading from both ends. +Reading from the back could just be implemented as calling `pop`, but reading +from the front is harder. We could call `remove(0)` but that would be insanely +expensive. Instead we're going to just use ptr::read to copy values out of either +end of the Vec without mutating the buffer at all. + +To do this we're going to use a very common C idiom for array iteration. We'll +make two pointers; one that points to the start of the array, and one that points +to one-element past the end. When we want an element from one end, we'll read out +the value pointed to at that end and move the pointer over by one. When the two +pointers are equal, we know we're done. + +Note that the order of read and offset are reversed for `next` and `next_back` +For `next_back` the pointer is always *after* the element it wants to read next, +while for `next` the pointer is always *at* the element it wants to read next. +To see why this is, consider the case where every element but one has been yielded. + +The array looks like this: + +```text + S E +[X, X, X, O, X, X, X] +``` + +If E pointed directly at the element it wanted to yield next, it would be +indistinguishable from the case where there are no more elements to yield. + +So we're going to use the following struct: + +```rust +struct IntoIter { + buf: Unique, + cap: usize, + start: *const T, + end: *const T, +} +``` + +And initialize it like this: + +```rust +impl Vec { + fn into_iter(self) -> IntoIter { + // Can't destructure Vec since it's Drop + let ptr = self.ptr; + let cap = self.cap; + let len = self.len; + + // Make sure not to drop Vec since that will free the buffer + mem::forget(self); + + unsafe { + IntoIter { + buf: ptr, + cap: cap, + start: *ptr, + end: ptr.offset(len as isize), + } + } + } +} +``` + +Here's iterating forward: + +```rust +impl Iterator for IntoIter { + type Item = T; + fn next(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + let result = ptr::read(self.start); + self.start = self.start.offset(1); + Some(result) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.end as usize - self.start as usize; + (len, Some(len)) + } +} +``` + +And here's iterating backwards. + +```rust +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + self.end = self.end.offset(-1); + Some(ptr::read(self.end)) + } + } + } +} + +Because IntoIter takes ownership of its allocation, it needs to implement Drop +to free it. However it *also* wants to implement Drop to drop any elements it +contains that weren't yielded. + + +```rust +impl Drop for IntoIter { + fn drop(&mut self) { + if self.cap != 0 { + // drop any remaining elements + for _ in &mut *self {} + + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.buf as *mut _, num_bytes, align); + } + } + } +} +``` + +We've actually reached an interesting situation here: we've duplicated the logic +for specifying a buffer and freeing its memory. Now that we've implemented it and +identified *actual* logic duplication, this is a good time to perform some logic +compression. + +We're going to abstract out the `(ptr, cap)` pair and give them the logic for +allocating, growing, and freeing: + +```rust + +struct RawVec { + ptr: Unique, + cap: usize, +} + +impl RawVec { + fn new() -> Self { + assert!(mem::size_of::() != 0, "TODO: implement ZST support"); + unsafe { + RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: 0 } + } + } + + // unchanged from Vec + fn grow(&mut self) { + unsafe { + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + let new_cap = 2 * self.cap; + let ptr = heap::reallocate(*self.ptr as *mut _, + self.cap * elem_size, + new_cap * elem_size, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom() } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } + } +} + + +impl Drop for RawVec { + fn drop(&mut self) { + if self.cap != 0 { + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr as *mut _, num_bytes, align); + } + } + } +} +``` + +And change vec as follows: + +```rust +pub struct Vec { + buf: RawVec, + len: usize, +} + +impl Vec { + fn ptr(&self) -> *mut T { *self.buf.ptr } + + fn cap(&self) -> usize { self.buf.cap } + + pub fn new() -> Self { + Vec { buf: RawVec::new(), len: 0 } + } + + // push/pop/insert/remove largely unchanged: + // * `self.ptr -> self.ptr()` + // * `self.cap -> self.cap()` + // * `self.grow -> self.buf.grow()` +} + +impl Drop for Vec { + fn drop(&mut self) { + while let Some(_) = self.pop() {} + // deallocation is handled by RawVec + } +} +``` + +And finally we can really simplify IntoIter: + +```rust +struct IntoIter { + _buf: RawVec, // we don't actually care about this. Just need it to live. + start: *const T, + end: *const T, +} + +// next and next_back litterally unchanged since they never referred to the buf + +impl Drop for IntoIter { + fn drop(&mut self) { + // only need to ensure all our elements are read; + // buffer will clean itself up afterwards. + for _ in &mut *self {} + } +} + +impl Vec { + pub fn into_iter(self) -> IntoIter { + unsafe { + // need to use ptr::read to unsafely move the buf out since it's + // not Copy. + let buf = ptr::read(&self.buf); + let len = self.len; + mem::forget(self); + + IntoIter { + start: *buf.ptr, + end: buf.ptr.offset(len as isize), + _buf: buf, + } + } + } +} +``` + +Much better. + +# Drain + +Let's move on to Drain. Drain is largely the same as IntoIter, except that +instead of consuming the Vec, it borrows the Vec and leaves its allocation +free. For now we'll only implement the "basic" full-range version. + +```rust,ignore +use std::marker::PhantomData; + +struct Drain<'a, T: 'a> { + vec: PhantomData<&'a mut Vec> + start: *const T, + end: *const T, +} + +impl<'a, T> Iterator for Drain<'a, T> { + type Item = T; + fn next(&mut self) -> Option { + if self.start == self.end { + None +``` + +-- wait, this is seeming familiar. Let's do some more compression. Both +IntoIter and Drain have the exact same structure, let's just factor it out. + +```rust +struct RawValIter { + start: *const T, + end: *const T, +} + +impl RawValIter { + // unsafe to construct because it has no associated lifetimes. + // This is necessary to store a RawValIter in the same struct as + // its actual allocation. OK since it's a private implementation + // detail. + unsafe fn new(slice: &[T]) -> Self { + RawValIter { + start: slice.as_ptr(), + end: slice.as_ptr().offset(slice.len() as isize), + } + } +} + +// Iterator and DoubleEndedIterator impls identical to IntoIter. +``` + +And IntoIter becomes the following: + +``` +pub struct IntoIter { + _buf: RawVec, // we don't actually care about this. Just need it to live. + iter: RawValIter, +} + +impl Iterator for IntoIter { + type Item = T; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +impl Drop for IntoIter { + fn drop(&mut self) { + for _ in &mut self.iter {} + } +} + +impl Vec { + pub fn into_iter(self) -> IntoIter { + unsafe { + let iter = RawValIter::new(&self); + let buf = ptr::read(&self.buf); + mem::forget(self); + + IntoIter { + iter: iter, + _buf: buf, + } + } + } +} +``` + +Note that I've left a few quirks in this design to make upgrading Drain to work +with arbitrary subranges a bit easier. In particular we *could* have RawValIter +drain itself on drop, but that won't work right for a more complex Drain. +We also take a slice to simplify Drain initialization. + +Alright, now Drain is really easy: + +```rust +use std::marker::PhantomData; + +pub struct Drain<'a, T: 'a> { + vec: PhantomData<&'a mut Vec>, + iter: RawValIter, +} + +impl<'a, T> Iterator for Drain<'a, T> { + type Item = T; + fn next(&mut self) -> Option { self.iter.next_back() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +impl<'a, T> DoubleEndedIterator for Drain<'a, T> { + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +impl<'a, T> Drop for Drain<'a, T> { + fn drop(&mut self) { + for _ in &mut self.iter {} + } +} + +impl Vec { + pub fn drain(&mut self) -> Drain { + // this is a mem::forget safety thing. If Drain is forgotten, we just + // leak the whole Vec's contents. Also we need to do this *eventually* + // anyway, so why not do it now? + self.len = 0; + + unsafe { + Drain { + iter: RawValIter::new(&self), + vec: PhantomData, + } + } + } +} +``` + + +# Handling Zero-Sized Types + +It's time. We're going to fight the spectre that is zero-sized types. Safe Rust +*never* needs to care about this, but Vec is very intensive on raw pointers and +raw allocations, which are exactly the *only* two things that care about +zero-sized types. We need to be careful of two things: + +* The raw allocator API has undefined behaviour if you pass in 0 for an + allocation size. +* raw pointer offsets are no-ops for zero-sized types, which will break our + C-style pointer iterator + +Thankfully we abstracted out pointer-iterators and allocating handling into +RawValIter and RawVec respectively. How mysteriously convenient. + + + +## Allocating Zero-Sized Types + +So if the allocator API doesn't support zero-sized allocations, what on earth +do we store as our allocation? Why, `heap::EMPTY` of course! Almost every operation +with a ZST is a no-op since ZSTs have exactly one value, and therefore no state needs +to be considered to store or load them. This actually extends to `ptr::read` and +`ptr::write`: they won't actually look at the pointer at all. As such we *never* need +to change the pointer. + +TODO + +## Iterating Zero-Sized Types + +TODO + +## Advanced Drain + +TODO? Not clear if informative + From af2fd1d53ee2013a8febcef0b064739d1ed7d76e Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 24 Jun 2015 12:15:45 -0700 Subject: [PATCH 024/104] rustbook support --- FiraSans-Medium.woff | Bin 0 -> 89883 bytes FiraSans-Regular.woff | Bin 0 -> 91946 bytes Heuristica-Italic.woff | Bin 0 -> 119956 bytes README.md | 255 +++++++++++++++++++++- SUMMARY.md | 9 + SourceCodePro-Regular.woff | Bin 0 -> 55472 bytes SourceCodePro-Semibold.woff | Bin 0 -> 55360 bytes SourceSerifPro-Bold.woff | Bin 0 -> 48720 bytes SourceSerifPro-Regular.woff | Bin 0 -> 49960 bytes intro.md | 267 ----------------------- rust.css | 407 ++++++++++++++++++++++++++++++++++++ vec.md | 5 +- 12 files changed, 672 insertions(+), 271 deletions(-) create mode 100644 FiraSans-Medium.woff create mode 100644 FiraSans-Regular.woff create mode 100644 Heuristica-Italic.woff create mode 100644 SUMMARY.md create mode 100644 SourceCodePro-Regular.woff create mode 100644 SourceCodePro-Semibold.woff create mode 100644 SourceSerifPro-Bold.woff create mode 100644 SourceSerifPro-Regular.woff delete mode 100644 intro.md create mode 100644 rust.css diff --git a/FiraSans-Medium.woff b/FiraSans-Medium.woff new file mode 100644 index 0000000000000000000000000000000000000000..5627227744ae5b2ffb83e632cb32b237428c8962 GIT binary patch literal 89883 zcmXT-cXMN4WME)mjF)B*W?*1o`XIo-#K6eF7+b@@z&M|QfjNf(3S5Fc-5D5TOBfg! zIG~uxJ-|Phfl>Ma1A{>t14HJWgRZf^-Gf7&7#Mv#7#IXK85oowWs3*9`h)~~Ffed) zfGlEQV5!e~aZtfOSl@_&fk}mdfgzfKfgwSl*jG3?H?e?$LH7m&18Xh=1IMS}k4HI@ z%Ssd&7)&-WFff4Bs_-Z<3ZxaJ=Q1!DdoVCCGBPkQ7PIb}W1gN^T)@C6eTIR7K?ICz z7>v?$D$^JkZ1*rQ9CKn|+_d0@Yn@C+N^S)M15XA6gJJ;#Lmb@ZXb{3^FoO6B!s7A22X5D1z)}-OjQxBe$f2fq|)kfq|o)fkE(%e|xHXPJVJC z1B1yG1_q9&3=AAUVk9ur1&)N?6IpP-VoL4^qa+z`#%xO~t|$XLeEm}k;T4&%aECcl}* z?{3P_VjbFRxH44vsf6jBg{_03w-&ilXDm(e4-3bx>pa^sS z&aW`pp>1T`bHa9?zT~&xDGhrs)d@stF~4Je5nfq8@wwQAX)&Lw7bqJEXf3(A|IBy! zkG0NA_#K~nPt|^u6Uj=QDg6aQw{%wuAa3GFK%=v|*QhxPrB^d%PQ?S>BPe!q##oyfoS zsN1z1N58ATbp^sadv7j!n3mAqnIN?72e(CU?(E_+3FfQaw#nT!D|F9X^ZL5yRI$#} zH^=^$m0Wm|zwz_?mQ{5j$Nsxqoqu(Cp8LmA>+`FFo?REr*FE`r&gbOK<+ulhIP@uU0=>ulypZPbBNkiuY2rHkXtyJyt($aecN* zn)_4RY2O}9zL~yt`KuBhUj0*-K8U>Mzd5gV;=0Z)evgBaA8(s7W9yE|8O zyWUgxUZ>?(!_E0-?>hHxyprp$w`%_C^-s?kyUF!dewR)1SopClK^{$;H_kC)}`_*=BfO|mH!fo>_n2z zr%(F)&&lY?d6oLl$|qIBr~R>-t$#Q4&7$)&f9RP1zj#AAeir{4g=w327ELm_X<5o= zc{%pc9aYKL*0N7qpPjV#YW?4;bLjlJ8Sl&k_u(r#X<9Px z())L;GuIaXF`9QeW$Jv@?g{B#PZv#yDYTzHZmX>Pb$Q+nuf_xLyvwk{lL3jXN~_`=`Cpt9--P8|({Tb=dG*RrB-d zN7_vHJo z)3IGo?oDy<)8>#q`TB~;{<-;|mzpkFD*yZIZ_ziu1xuJdpZCnvc)XMMA8*=z%~P{K zrmYT~SydMG*ZRuImJgcGjNDTL%a2nrG8SN87DdZG3NK;*RZ}e`3oAjj9^% zdoM1X`>gSN-IL$S6Xn$Tu7Cc^zQ_Jdwcd20#n+7tv$jar#ypF85pte2)cX5ueffkp za#^xJyXV|KF*7J_wrr*4O5?@y->%QfvVT*c{%gg7WujhBCz&)>a+S}SRVni;dFJuR zRif_%D$kt!(=`92kb7MD{HbD+K4yW=&zpXEY`vCsb}eh^0_#QGZ+b6Ob{Cia6khXG zMwRvZg65_Pg^P z_Qw|f`@bhF$YXhJ;l!Tn`)>T|n!Co@ZN21)%T4F6pYlmcuX%h5KY z+ z{b}#OV(y(^Ya^%BTg{N2ANo!;@ZHY;`8!wMKD{!T`C;{wr7w@1Gs+O$*?I2_Z{z*Q zT#xLyV$Fc#wab`)sUPz{;QikI_fI?aU#u^j_VormHu{>g_3A3`Cohzq%yl_uqyO}w zl--Iwd94edC_l~L^LgSTu_Z4a2VXfG^2uyp%$&!zV(lwFpR$(!U?w^B+2_lfpFK7{ zllZ>>qkLD@i6n)^!v9;QD4ySa;@LuZr}PHVRobr_UcFxPO8eEC(67@DS6}&6J5#D& z_|rM3`P)NEXSKczo9MD?uj`TH=jOD&vVUdA{XelN@avS@%)1|P|7IwEb8%XS>_+`R zinaHi{#eVe!(e@o;YR8=hv~}}zfiZdeeD0v<=A$g{!`WY&w9-KOO0n%UYx#Sqi{Pz=%uS@d<;{7icYv#*dH}#S<-dDON{GR&S`FmFFaTc`N(O_?P zY(|pc1D0dfr=~phzCZKahbO;9i)MYgV*34(b#CJNwb!bD2C%GUY`nMf^gC(Q54T>- zcV2#K_mOu~T*a(Utg2e}e&T|1&u24uTz@ovlaGHGo4R6&x@G1jf1am-X}zaauLW0p zp6K~;50_T|DOR=@)~kKjN1rtAKWhB)pW(5y<{xd}T$}Z~-{rsfOQ&;suR8C2{W@>G zY4H1ZRr%qk_RcotKmKpO)Qi7~%n?&|ir@L6aF6?n{i}noD%S6?zkNETTKKfP?29>7 zBE?Cp4!q1}zJub(^3#$>Gu~AidTZoV8 zV=vq5^V+t4{x~&^edEKJlXrg{JzN;QP~ES1;km-l_AN?xVphySeB`OfHl<2x&SBnbQ94)hkGEOPd%LG%ahLKw&r2fWqVb_#Av4?x}x%TRG^Y8B_?+g4?!xrNM(1?oGzUY*VRZTUIw z)$El&jZCMm3VGW9boui++yOz`e`h8gSf;|nqW7-o9P5ohk*$Fu|NA#(e);+NxrOJa zHw6|)PCoxpJn2EY()IK6f4Zt_X3bgF?mR0+vu+7z-jfWg1)t(|t~1v?`;^fWA35iU zgz?0O7iH3OJo)!o{_eRcv^3bMN-#e(yKhu6w6_Sth5~`gn@BFms=A5taQTjo30OHM5eOFehgn16ww$|xJ2h$m%!!@DdWD!YaJ)@ zM{ZkvYCUIn_hF~Y54htRU%Cbt^mcr@P@dE^`{m(>!GE5sYJLjYt7+NwkoA$)`@oaS z&wJ`=|IgXFwd>!+WdZa2E_ujL`cc=pqR3{O@OI3}- zUmoq*X{BQQPe#J={Rj2_xst6Z;oqvzbx2c#UG>8H9weZSt2^^PrCnL zu03j*=(2=aAaH8T;x)D=E!U1n2PY^$=(qY&7su{8v0G-3h~{*k%|8~d2)VWF!w;7W zr#ebCFUzb5d?0#n$)4vNvpQXxV&|+sVf(FP;pEjy{Gaqsr@TEN@AGUYx7b*{AI@`~IWz_o8D1Pv4*5n7Q@)kLHuiJNG`_H}}t` z-6hLf&fS|Z-{$OsJtxkTE~#Yv!}-lZq3u$+&YDL%9)$342zk$Tw_Cz3%KcA;-7wM3 z=VZ+WX(ztS$tzC$kj&YJoCQ|F+7hCzd06@xntS%`!7{9^i26X4(&eS=hV8P$-a8h;Ug{Gr<|`^ zP2PLX?##aDyRJFKep)jlVS=aLi4d)Sn$LNDFnh6FH?BVGGCe}*x<@pVeo^3~gX^1T z@y}OkP_pjWEf}{zsW-=oMJ=Le!XAOxLXEEZ&R4CzdoJ-RZ=dvF_k+no)|DoU1x__9 zhAj!L3ViB1StH=`I?WC#!Cz&6JVQi}&wu~M--vt4&y^uXrl&MiH?aM=I4^zHs$8FG zl3N@qMdxg_S#t8P(8*7F=YCI{uTcMV;pOuU_pNq^YyB^L`9*uL@>1r-oy%9+6l~k@ zW_Cy?-+b17{!is{lxzZ;g-SG?g`x$7*l43)X)$AM9DA*l)irxXJ!PjN`OZ z4ffYBoU7Roy`n9Kw~mq?cA2AmJ9qkD-z?i?<9Bz4Huv>6LPCnhf#DZ+ZTa+Ws)nF@q1+PnGe>gT zCa(zSbv)Ks#cAiLJT-o`p5BD%3_KYEd1db(@Xt|YynbA6pXlU;P1$FTW`CSrbWDzQ zp^cQWH)|WC)`=50LOAv$FtXibVHMl(L_y-Uk;sv72KmX=(pm@AE%O>@zc6_qETi?A zPgJ}`E9L4bXNm1zFV~s8=U(LUPCi++{38Dk=1iONgNt0}s(k;TuHR^6Kh$9LWPZ9Dh^g#Vb;wcG!iW%{Cl}A{7D+s#}D18F`9c)LO?|<+{JFm+J`4qCKx>X zxO7F6;%R-+?=K{FJ#tJHc^RlQ_gKkoP5yDHPAhErKYZx_|B&at%9*n4Y-c#uQ}!Y zG*{z?%G{S`-`M6CJr%qg@O{To#vMvaw3>_-O@6Z|fz|YA+*A?MM;{Gq-JOnZIWXV) zxA4`7*nc5bJHyU2DU{s8`?-2)H8@^&iA+~n&#-B$xm9mtw&(`sdiNczyDWCkIi)@SqQ~Up^1qIMRXcxv z-HNCACl*K@{3Takbo1Zp1GNGv&+Se)hKXFgaICoCvv?@x;fQO ze{Ss#&8Kt2rx%L7U2iSm{L@;@tRRlBw?QCDvQ&j*jn`z3e+mTxMYvl zhoj41dntH?oPB-%NAQ#B_Z5vV9{t)-e4M+t>Zp8Dpx}kz5ANRVOP!xyRDW%^?6~~e zbyua%={HP|^8SA+Ra$Gk*rxsu%NhPPyiQhSV$SDCiU3vE*;;~XI#Z6z8m2v~KlJC= zu|>+0yZct1D)3$OU8q@<^^DW%1>JfATP~!9R!B=d5`L%k>@3HGM~?y~l{hT)F)EsO zh~7Co%{_)>RtC`AY8tyOM6<+lpQmh4cW*=(Ex4i9PQF-X> zeZh69lP7bnu?Y7t14DAxph-HDvE>(BbkFzS3uZr8FpzS8_9}x7zuNM=o1j zmV9E&Vd!}1nfRDRGBoyjmVMWrNBt>JJ3NnF>9e=<-(@(R>-yd{pXa*&Vg#6t;)P3( z1RnA;$vAb{)UIXajqa`MxNg3FlYFo2)7CAn2ik0Oy`A@aK0TrMFZjV!xYde(mwr&5^Hy2iDd-iiRHE|>q+j*2bR~;_BvQ^h5p-J_l`(d3~=aV#IuS>03 z*LgSc;YW8FuO|NeP0kP3m9LnzOMk%!r%!X&7%dUEIl253!-E-m5A6e0-yIQL=)Z&e z-K3k0KZ?`qgG#2Zyf2b8L0Bbg2Y+yj=>vb&bK?GoZA@FUqz=wssIkZ{@aEr7oN+ae z_spBpm0f1Yk=8D`V9u%?;cU?OithGiJJ+VpJ>|Ep^Jd|9to2Nf#l+LUe~K+|ZQuU; z3;%rU)}S_Zy&uZWMwb62>t`ei-z$1(=lm`?-AHU!$pYgC{H%#@R&vi3e16JllH&Xt z=ZT+84tB}fx_w%`w$c9K0?lQ=_ugimlBs2-q-ebHZjMVr>+Y~SE=-(;J~w_HxT|u* z`iI$%YYe-60vq4y*4%w1)nw#*z<>S@IVU`&dU9a<%5{@O zv~zEpW$YLGdODjco@*!DW(T{2vuFQV!Et>r+Y-YG?_PmgJ&|6uJ8%TqFmY%3OD{C?_%z24lqrR5>p9!)Yx=-RWhh4qAqo5k+ksxg)Oi-YrG zu2--bZsU7x6__cwXVAL&TOpmtLC4po$ASbzE*-a?%-pKGOo~MM~G;d`47{;`FP2MT4b9oAh+>XX)r@Ow$7F>I!^wuW_L-l9Z zBl!E*Ti84dGc8F!{dtXzvFV57v-Z9JS|@UH<&)4f%{41joz0mXHFT%vZ zrdRZ>*Jp#;v%HEwD_tv4y%KS%e7{w)aY)=OudM5ej~(tFpW?Uk{gdqI*$uo}*|)j` z=bgTP_e8u=O^f}tYn8EAS1v5swMN0ES(mfGCHZZrD({XHJ4yt9Zc%cGy}~>F?u%2u zldd0T5r{YtG(E!jOi+;YTFu=1(>FM^e|(W5>d04a8OCUubdRks`oo*+)*;S!qc!eu z1g_q8iRp&ue62ldKP|qt9gY5G?3p5v+xdr6Qzz>D_m9VWVz2Jkls$FI+dPEXY|4hI zb}GAsi~Rde|Fn=WUch=Px~KP9$n*b9^$%2U#m%{Xc`_$M=k5#_gJjLc zyOy70P_j;+t)0$a@3doHetD&-#EruOP6yuAr-(3Qy+514J#+GY#bzP-dyo0mmV57g zYRBjHNjo@V_nw8u-d4u>FV>jmpY)%xS<{Cj;F#L`tF=)d@_nD^T6{Oie|o`pTImJW z4eV;Yi(c;R+hLI1&iAH?LnA2o)QV|KbPn1b+@77i%E~$G-c{e54tr+JE^pCrP}%;) zD`unO8MZ}jMyDPN$E%(EAok#X;qsuTR}%T=oN35-Y#~)Ia&!8X`Fp%pw2Jy3){)hX z+r0PY?ZY>ha)vt}(R|y-QyLi_UL3aYQC{WeO;OGGgi4tY_J{6Ty}fZI@({P!gJatk9az$IFiAi7u#RcrisPT|MmW#r)7D`; z&SHN0oJ7=YIsZ35QZh4ot}WcIDSdm&ycO+Y$J#DQ^=w@&y5GBF&ed(}ZmjoF?#@uw zy!0pYG}!so?W|H zwd@XdGj8Ag`B!=Nwfaw|H*T2$swU6f(^iMZ?X}29COjPVSAAW-8hYj`o)g*N%pzRA zN7H;=^v|9)_Ad|L+WmEIs(pX<^Ja#Ie{DQob~XR+af&VV&RljXlx_Wr7h)1zMOR9X z2_zPC&i<6KPB8FB#MB23d^4Gxxc!~G_O0J&R=LYqr06!apPrbgj!2WZd z_=TrCwLiLuOjViob!+dBw!LePF`l$gVmQelxN%W_xZMr&A7$JVZ_BLwd7-TIdPr(? ze`u^$4)2HlxK8c!|J@d`Es!_t;&^mhLQ*c8{Vjv~uD~k`SGDW7r zvW!;I(|wUu78)y7P4u1?&OWt%0Z%wfXUOa9=e>+3xoO=Fp)+k=zt;CpUf(EA>-2egY+ags-ipdy>%O}GxNOq=?zbX)P4d#*>E>TA zB=xq~hL^^k+xoyMrZK6gPD*25_p7%J?60c?Dh@I|+nKLnaIk32hUuA!Vt?8sS8tm+ zy==|unRYDF-=-;-hlt%tX<0f)*-mlu3c*&1vw`1DMf`Rg?@~(%4~YujJ|~_*eE;h` zD?f#WbXrHUoL5=q-6L{%vDPE&-;;ltl%B4MR-2L@w`^)<0IRt6<27@*emQ>o`tj@Q zsBrD51$&O~>XiEwbYFk|fpqh8rwdZ=|9 zwx3OFk@}Bq>~|TOTmD3uT%4@Z#&&PLq9JQr>+CF<*$cJYTc%BA5dDgP&&`60&Mn&%b^U3yg5UeruI^iMRE6=xVT%WHjp@IQuP*5PdBieLBlU;W%|9nZ%UK&^P4$9r zaIAS9Re9EzM||JQ@VV#DYoEMu@zKLHp*;&lo8GN1a82;w-RXV3BscW^*4x>a&99e# z%{}{ntBU1~OChY&T5f$=xXycZKq>B}3E#pjRu=9CSu`BP4`;W`p z&h0q(^v2r6rLpU8r9F}Q$eb--b#!Y&u0clX3ndx(uIGzlULK3NlY1a*;i6L6gh_14 zrB`FhV{iA$wq;p_++UY%Z~E2iO&f3frlV8#T5MmNCcr+4%e{S-^!otiQhxd583nGN z1E#Y?O3gaCj{U>7#uHqta#ZJRTETW>;%<+tw`|2-Ytrj4+35WJwM<7Nz9O>kaG^xj zjtJ58t4ixnZhEi3zt-ODtDtVcJ@3nI=PQ@K&ucuheATSg-yZGxG->UvpWLS^^0Lkd zrX6^{bYFPfpW{m}um93_$7}Ay%~K1^u6mv;6L|TAwWvv^qT4F9uRnY zZQDPOS^pHxzZ-ASyzu$yG@e%iYu7-Zr^r7`GcAAZdT@K7Z1-9td|uZE;N(hy-)VRiFF#ks>;?Ce>lA``rz&x zjAp(U%R;ZeV*7DLygHP69O?}_Q|usvNn|1fVo-~ZzzSK(5=yB8971+*UvKXE7a{?yXkg#s>H zolLi8n#_*9zB9o8_`MD9l7oI6<9WMvoiK9{gTMaj*Eie?zt1bI|10?K%io^6M_5W& zCCtu=)|y+_Bt5>e?yZH`8Ew(CT-#qfQ1T6*&LH}O^-j*LnzSKFTFJMxN z*;6yKBlFyNe4jK<`n~Oa*S=6^Z`Ox#atDo1o_4yLR(I8E=VtrN_`b(4eJvN&Jb(Jb zz^*6x_Q9i*_E?_E-t{$|>oyOTG+K0dcV^BC_#zC9*y=iM%u zw8^UkR7d<-{Pp*`fNN$t#rsv8{g}`E;;T;xbltjO@BN+YpC_p7cRYBj`9h@aV%d_m zjkmPto?Wnc-9A-&5AIE~79QL8UEpSs?Ael_&=!da*VoQ{`>K3*L*#4a#im^eK`Pt+ zzq9$b<#td8FB{vxlBGTDJ|9mW6Lz|_Rjz*4(cZrtH)HmfvdHoZWC^m{EN)oW-TP|O zR>!^o^Qqf*O?()Ady4iG=6?z6`Txvpw6CqVn=j3;zWM;?(K5et>{6DB2NLcriQfCT z|NZ@+&lgzq+gC4pTy;JEZqjk?c9w@-_O>6@7pO0M+GW4^%IB5a*Zj^q{kZ@2y3*My z=aWodo0Yve+`Clu-xT>r=QrGtG-xt7>~)vpPo&H>j@OBAFGrL_bS8;iHuW)W@Dn=S?`|0uTdw_Wmracx26BmOgwe!RK1^I=U{^!0ficW*rKJ-BdzXUpTT z%L}b6u3QqVe-Us%*+N8wPjJS28OC+YOl@sxuTF5Oma+b`d~n<2sc^m6Bmbi*ch24K z+1YM?clzauy5J7S{hUI!e*KqS{$x(tV|&t1>Hpu~`~UyDv9&*=@zcKVwO@Qqzr{cH zzZ^ej`r`|qYb+k$+rBP!!cWN$ze~ge_xhu?nN6Ew`h3^TswPE{>e+$N4(AM zr~6)KJSz@#zqLQ_tf2E*>pzh_mWp#TJx~1j`}BSBktvJb%lDngJ9t1;X^C3fmpdXJ z8|q6RGwhq&5Sv^+M|^vav;A&klQgT#kLCAX`gTP9ufr9M+mn6Q_@v9zK@q6@Jdv-oD)Ku4U&h&2J{&Vek66C-79BofjRK|7o$`C*?(s=XWWeeWF%g zd(x=YYWL09`&V~6iaY%9TdcJD4bSX}j%V^F{`z7uZO!i)wVc~Do={=hPyPhh>>q4|YYVYhdQ=CvI7yXQrr#kmOOz$Z3qy5%+qt?B(4&D#H>Izn>6 zr5$BAZoNIREP4N-I{_Cjf3`AuD!F@Q{fp<4&F3Yu9t3>;@yBNV-47;*JW)nr(=sh_u9b@x zS|8fxm9*r}zoguv=QSxm{_U{Yui39r|KZb*)W1x9r43hHzV@re`u%-NYS_O_p@dT=*iyu{MO>*rHSe;PcHtHovJMVn|Yn%?}YsC#(#{J z7fjY|+OOE$By;=w`?(2$zWZL?3|6*quW8DQnsk4Obyd)U&4n^DDs11kEZAJ=z*qHV z_h#lKrIamp^Pewl-cs@F1|M_Ew^vWBcD;=>{}V0zliMzQ=exBscQ4*@uP`#Z+SmCu z|Nly(=WFDteh3|^3=tf zh3}qklu}Q2`)tH$`busF|I>zq(~XDyli%J_Kj67}+LeWK<+dC>_v!Zb{AT;UnprC{ zFWuPY8D=MAF4FVN^!J_5TI(OHRVGXj_E~iB#4hEtX8C7WonoEu3M`nuJu*#hZRCQq z<|zKH+S@xzlk~4$U+;bPltRkUxDAC{-#>Z%xl&4PK3Ay!`QtNdc_y_-ef;{({m14t z{bvvVJa~q?G1>Z7YSo=Ph0KTi&R>3+qQ2&ckMRd#9iy3o7PlBfe(jtu_p9CA%$Di% zazU-CTHC`a#>b-Wp5BowQFAyzxZO%`{rzpvE30DNQbaFTG&RYJwO%Se%zfqS7aQ9h z{|cqj6RbpjePMYq%b&0IK-RjyMRM(_F>X>)TCx!zt2ez)*;aTsV#ngeCvB}J6|tAE zl>ZkMn)&&8>aWMIU*4YmN%ZOaJvD!OD=%2A&-2*&TkFZX|3A0?|MNWm^AG8$1$*|N z_5SidVfC}TpKtD*-Vie!!vf^7EZOg{W3;luI7S=U_eCHe`+RG0FvU)FyrsBh($J7*3@Ti!_yt(_~T zw$(thW$aiul~w8RTf?U z=Z9g{)B33;?Md^`@#{QhF8-W)*T!zIRa~e4!KmaNeXq~#YPs`t%iL|Ry{84Qc>Xn! z_x;Pj?X3S9bHuhv-d<_7evNkZ#(zKhdYDV)i?akyoXy;O?YcV4693j$>(}#Z|5n(z zdNz~7z1kN0+aH(K)>UnLEy#5Kd3#ax{yEFrKU?{ozW(&%!kBG^TeVHNRoC8FefG7< z8uwpEf4!L(uOs%`$iDYAljz@Xk24n^a8Ee0{b$WRKZDbivCE#8TFTe|x&5;=w$9nB zWlmZhi=D55InEVrKjA9(%d+`lJ(U4PGSe{afrjsH)c{(j%T z-`?)r>r5$Q<9cy5^Z#G_|NmQm|N7JNEe@6cBeuWze|zKJcsu{g+Y5JFtl#sb{kdlx zWA@qq8_$6{zX^Z$-O>L40h-pt&dDVnxTN>)W5wZ{kLB-~&Ue+T+^o_ z@}}CC)@(2GiGTI$_a;YYK_4mC|J?0Y@2;!3b#-cFPH3n|+yA}imgzQ&a2+*@_-46u zde%k}!3mXGsTu(b6c%{QoamXBBETZqVl*|fO=+o-zm$x_l?9vvY>LO&4;sv=_T-qr z!GA>E;`^`dvnB4;eo~9y|Nq&t?`t++k9y8@fkEaHM_0X~`A@&lJ>>zd^7osk1=rL| zbPKj$pAmORX{$$Wh~Y~8wNIL2rbPFZ3C+p!(^Ws5`EpG`*Bn#7mBpdqmw#5x(7Uqu zYtCNJ=`W0GUFKg&{}Ng28h_dROYC0Pc^p{^hxK$+YEzXq8oS7MZ*?&oVR?IBP_tyTZ zQr$;Sy>Htp^(Jxcd6m|!^U~K|m$fML6IDOSX{kFW^_->eI zRjcnU=70V8mq_;BGg0ebckEj)KeOW6tdt-h=47p`+}Oa^I-7sAMseRs`hM?oRQ9H8 zyZ&FZYTMctw_@w0{^hF{g^B*QE;Ik;{l-Pde46NL(O9`yvAM#s61p9H9p5^)^_uZ2 zIa+*Zwm$gwK}La!g^UarAIt6L{^r($O$lWN#xtaRxZK!U4?a+^Kf%4reUozJ#2ycg zNphJYh02-}r6&IPaP~v*hp!)IerPE8Uf{Q*cE`H^2lPLN|M33H`md&bo&D|k5Bon? z|2+HmjrIP!Gwae{y^YWRSNi$8eY1U8MfKzFmhEqP{`kig1}%-@`oA-)JvylKvV1>F z$g{8zS5v>RQk6w)SxTH+1Ef!`Xr4Z?Y1fMOUl|SI6S~^w*on(s+Tr_>W1*qZ2d#1q zVc!o{n=Xjl%xE*eAd|m{HENOQJ*Vs~j?r73t4kc*OPtb69K)Y1kS@9?YkNU>?}YYy zFPitAaJT<*oIxZ(f$d=~&oKd>qt+GThd;=*Ef!EVnDll1f#ngcS8ueO-yofOqg#K2 z{O@=ItF?StKR5T*Yf8*P;xc=>FT-}>$yVeug<>v$UD6H-dRWelCV%4 zWgRD;$S;37ceKk-e;)Yd*z*##^BnW_R&oDVZM~9yZfSI6i2g5|od@Q)$8T9-_ocL` zd*}MSEr*w{m-0A1k>%M!ljYYE*Jeq~b;&Xmzoa}HC4*&og`xD zzuCfG_XFk99{e<(gr48z0 z4`V6{#qt#PxO5kU?U~h*uDJSTO81(juP1#nPFx$es&zJ>{^diw?bi=0-Qmq|X+6(U zF~>V!=X2VxIj$DsnS1(8&TYt9Y^=Mfd0*DVxemWLyWcF*kNn}|@HnXZ4V#g+;I~ja z_L_GS&!`(VAM=KlMC9Zb?DHV61;g)mrt;g|QHdY%Ea&mwlhM!&-b0&V9lL_V>3 zh)vSf=9#Kpwv5M5Ws0f*+kGb2EY(Zp4yO)1YD~8@+x+zCgdIx)+x7PS{%>9T?=8!N zSuB;(buB-Rscehq{PR}-iNgIjbIz8_yI$FL>UMJv9HA&RxIx8-@PLH z@5g(^HM*_mQOaNI=ee`)o4NNh?Q?sgii>NPlr(y|HWaqPl;xff`>X8fQ79W%{mAn>l*z)4%yF0UY1r!D~&#w3Qo9zk?gWCrW zEI7NNyK!RU%tp`IiS`o`PcAsW;FQ8qg#!l;99Xz_eq-msnFnQ7c+7K@&^mPH!N~;X zkfkRSn8X-gr6(q&CtSaG@W6rxQL{B4KHA%?sHl;|y!Z=S+X>#DT845b{+Xb?Dk2Pt z48aUO3=9nX|E(DKnFJa5namh?m=-edFl}bwXL`cGUvW$K5Vy}Pb|!`d_nC{YS)JN> z&C+`=zl+P3j*clxNox!fjD*YS(ziO*Nb z+cW=O*b$KX;#lN~$S;uxZ$8^>ojAoHI^x0KY2W`AaPAS`SFiUh=I~Bd7lWpr2Z}Bo zZbt+TwMP7%ZXqM2_mAO|<6m~`=k0ne@dZbZK8Hd z__@$tiC7`c&WT4nwfwaFSNR30Y*i^uo*2P1tz&8O%?P`&j;kudlV6^ElTx?IAaat- zfrAAPcVx(jxgW|5>I!1fd^Ba(lx0);rrZ;8?ov%vOEnaoy=&gCxm6XCMV4=ho}^xR zs%FFIf6Vw}ObusT%k)Q6e}wIkT7R7X;ql9hE|+8;GpW86Gt2z!{B6z$glBQcvIrma zED#RknB8LQq%e1epMU!D&zD1^prMiXbw@JUj$ojmvCd66`)6A_<;D(CL0ZLL`PyX#%o$5V_; zn}VD(7p%~*ol@7;`Dn=wP3U@ zbOP&XuJc{z4y8@p4BD*84O~lr=nYmXxTc6`Q?Up`0?eylaH-m5fF42p1 z%3mn`a`l(TG9i5G?h}G1U!Jsi%I0~S=N6x6FgPSJkw=92yn^wIo*K642h*n*y7bf@ zE7Vh&KI`g4t}-~XKY zWcn-pxko!5op|&sdf|4jyw1Fr`Fk}JrfObZtTDTr#Yo^5(-y~et=-0OYF9mzey0%Dxrtxuf- zcGQa(hgXD`UynbhUH*5sUyJzF&SURe?>)W~d_Q`9$7+rB95t6e`5renp4#D6xAddk z7rWQ{e(j6z5qf;2XruR@4-H=v{x!Zo*yf^fbIKb}rvJgL>$_GfgaXw z4_RrY!CU{|evt3I#58E?mUt`GQt#TJ{Uy;=3bqpurf@_~;ZgOTIx&?;GCE8}dvfTB zB}T1lBCjc4KJhEn*=Y9})#x>X_3b~`#mXt^PYXXK`l)QEU*5FyC&Qmwf0`Usk?W(o za9W)9I@4=;S6r`lzDj%LCnqG|CI8JnX7%x_)35s5c2zB@N~zwm)ilebr>M2dQzfH}2+V**2w1E&e|+Xkr%ObP}pHySh(Z?N}W6)5eHTG$uDzskQZ z>QClU_4Uj5rGI^XYW{E2=cZO?4{bh`u6_Q``EB#w+FHLl`u$ZE@BWrQi+;MU=e^dJ zc|Ln${=zLbYk%20TWveH?Djk7Zwr4F)V{OJzaMo!?Y`grM!B{AS0{flshwBnR{ux) z{q@#5kNU*_&+;$aFHw-`VOZ>FGJ|W9gVYT6q611BM0D7XCh)GPSj`#IcsD`+2EUXe z_Y0Qi2V4tSzcfcbkgG5eFkz7PkX^v@gx7>GN3x4I>hP=26Q1*)Up_CN=MdY==0gX6 z-dC>A|9dxE$Fxb`L%&5oN58E7Q`@cf80YrG6CQ4Ocp~wNLEQ|iIreKz=b9g#QJ}V| zGxO0bFCV4JSGHtC8RyRAb8B*Qa#wP@qpYnwTe(`9(fG_6Bk`H6X&Y~5f16!?#(nXH zz#l6zLabKFhAo)5pX$2U*qOx^Z);{(GZ5=A`5ZZgr*w>JsDF{y5jO?|)d`)%K{<;;&2 ztX}YKYkn_arP5dBzIpNKg@rtpF?|0m^5)pZ8QwF=o7pi#!M8wNMR-={PR{p7ZXJ1c zqjZNL4+*+yALc|z8jv!?i*QlC2c?BvIj*PU$DJS393 zs?@4N%CL8ioA2XgotLk?oc6LW^EXe8TGFyQvy^G((Ppb>#?G%b-fdm|!fAI+~77{|0|}e$gg(o@xG!?R!-AE!mf{@5#O=`?u^)z7w?l z(%n~aHKKpH{(5~n^&_i%VM*d^(`ThmUoX7g-W}UL>*(D58TF=rw{8&GDYAJ7OQ)%gX--$;JnvBxoPhWNYQ4`!8H<93%9TP8{FJ`+7nCwuz! z>Haky@>kVAmHw!zv6_D{{nO3=%l_`&aVYlVdYQk@zt!K%pQ~s5z0(}DNx9vF)>|*OH6(`2{H$7*je1( z&i1<}GI@jHa|W}7-!*LW-xk|Fw!Y0WzwpMz@2jkQypU(J$L;;zH7Rhpm)0%S%|Sd%mmCV|GYaYtD)|)H&!w2xgnQOy=PchWsh(@1G3C^;8na}hNm0u$FfU#EV$&t_ch|$NXMCzF zK9IO>()DXsZ{L+FzY-*UdYhDq6!X56YxetZY5e~YZ+5vo>-DRw>&EvcD2JTBa`j5a zs;5=uN2X|poqfD2YVpKHE1w+FzQX-QIYf8q!ao<{SCxMXT&0)!n<>$-E?XCs+M~z+VpPRkE@ftYQ=2>UoBejm+=e3F1cIB4LTox zW0c#Za$o1rS*4TZPj)!;aWnY&giUYFp8xzx9zO#^rq}uh-HQr#d;JJ>z3+ZgL;P#q z!uwT!cFhawd^@wSF*4{ty~DOMC-fXvn|uit+v^bdptEVYyQbT3jioj7c3(dW+2YHRV`}Rx!+<*J$e(U-EOD7s-r%cUhjM=HPbCXw*6}Lk zGQ}0L4jW^l~=^Wlp`YSV6~@c5b@uS559 zK1}iY-DuaFqbI;2=Cdq^O~b;Go!MdEPba->lbL5uF-+KUD5Ky~n!2-g`Pnxw?md71 zHTQ)1*VQpMA2iBte!Tgp@4vh3P{qT2-gq^Jkl`%o6@h0+bR5SL8k$eiL({5$*1YTRc>@1t<9pNnpB){Z;{BFO-_59l1Kb%|7<(b^v%GG); z&*)ZZ*Y!1>eDl{UCyKt4uRSewPv>vzo8PbYnytO|Y_0gah3j@46?)J0@%yFFBv$@A zYehvh4xC%n8vf$?%k=?v4;WlubzgaOGIHKuqZozgvLZXT%7+JejvSwu8m`-Loj?CK zF!iW4H z`wJd&=W4xlhD}sv^Eq)Qp=oQEO?_6wn9B7beeuB~5hk5gM)W2W$O?Tpz zfK#`HHk-M0#g!-91k|s~UiBsD+vRO)@w+wpT~GFX0};pJ`QHA8xaG8S$T* zGc9?|ZB2-J}_{nnSM@`y?tUG=NB`pxxITE zO+R$=`SQ-av)}gal)J@WzWL71v)^SM?U8@KTxfe{v)SRK*nM)J?1agFS))=cEj7Z zbFDAeUMO4e)mG%4_cW`XeV*EhB^6hX{B_uH>huHsqC|sqW$Xs-9krPLbW^liyGH zDz`7#`$ebpH7W{2?HbfFJxqvjoZq4F%Q>hpEJ{WUiowT;sivrCws z?Va{dq`*zQ)NRIBzCWt&Po;S0AJaCr-}*E_sePqxyQN0^N?q|~+hmq)o8yzq?vu;A zPJg-C!NYbt60)uzx^nHn4HJV}Q-iG_^ufsee9$>f^AD3H*nStx)y>)7o?CiI)_1N= z;UkrO7he6F8Mb9YOxyI9{{uH~a^vG4s)~?%RgF&eivsXWU$=>r~DA<13qIwO7mn9cP|Z z3_2xDIwcI;a~Zg0_pD@&c)=iM)zI2^fa&4S=Yds4Z+VU{m~ya2uGsL)mbJZv+ZnUzPT3L7S8rHuloCT=c3IU`wuv7`@r?G zT&6apLpr^1bX<=3YP_dc$yu0J@DJ9=JEpUKYj@Qv%P#bg&{n+bbb&G{?* z&82;Na*S@W&%-n(X>lJm*1wrEZp&Ut(plgb9+FFUin_SZdnaQuCUd|dJSz2E&7>9=_wm#--hySJUeu8z6nWKj4z5BH#& z9S>yx-f!(^laudfJbTDzx`UK=`<{Xh#WSyLysn+Nd^5i$HoAN7Z>PsUCqC0#tDIrh zb|(75o?nYhv-`fJ%G#gt+p>9Pi2wJ1)%s6EuCBW9`dK^y0?Z;u7+4KknnXUxiLorO)t#nRd4q+~ z%<p89i-g5nfc)5$X%_j4@iuuJhVE#WzRH~HX$RckKa z-eq@t=hB;EFYaHJd|htyBG>ft%p|qB%Zz93(k^F>tWM0e+rIMj{8<*3Ti#8Zx#woU zugnXz1y#P^9fTL|{MCB>!r}bc`VYUp;${f_V)gK`T!hKKf-g@m>0fYv^`|7^cp6V} z8yCYFUWQ`z1AA8TlxpW4)5_e=CVr*hZPdcMdl+8Z9I(XdatPPEusq9l&m1l1XsxA&5e$ltBoD-D zEnH~-yleZ0*y!2av#s~6j{59b|GPqE->#{5lR3ox<}BJ9kn{KYwrLZrh5OAfh2&hh zS*K$&fqCar`#Zbty^5LJ_4SDFv54@OVeS_$1}x7%zl=-wMS;!Q?N4q5Sn*x>s{2Rk zFYAN!=Ej_*8#Wzd_GxEac35B!!(@)cdvdir0ZW&>VG*%nXboprB;N2swBZG-LKS02 z9GIv2X77aa;vGFv*SI^5EIt2(yLV1f+O3LLu~x@yCh&brll|A%8B)0E>eM-P@7I0b z;2ONnFjS{xxBmSu8N2jCU$gD|j>^86n|bf+y}z}*8O!hQO;7eu&*xUX!G9s1WAOo@ z)@N%~xb7BRIvS+OeD{&3nr)m;-U0KD9G3e5%u^FP7u$7au5q%8y0Xb7NJwhBm(Po= zkIWoLe%HQWFA+W?s;|F#lHi337L(BC>A8}BCaN7-dj99xqMb&)en-9HUDq0>*!(-0 zoBlj~VcN7^^0v+UypQ;8cH!FH5T3c_MuSaQ!^)@a+THIo-@1Okvp@a3`S&-C``H%o z-xvDrpf0{%xJEu>Q3rFQ^i#+E`y2L!&gx%y?NWI1i*1kR&)N5K+FP0Y5{CEx)m}vF zUFb5`+1NW}>skXnj^fQCpG~JaBxorZfXF>b42>%r4um))XgMX+iM{aJ7E!{$HCb}0 zn|6v-;z#$t(<*MR`D91o zdrH3)>@P6!Y*FCZ5+pz6@S|xhtMVs*N1-IF!*)~}gW#n(T!e|uZ=V%ENO&gDI&vHQ$c zZr^NGfAQ`nwc59l%{#x$*DO2!@!siUO073%hppdPxa#5xxAl25-n|c!K67<{u!d&U z!}SgZ*^co?y#HR9G3?Y{`}cfYM&^7Q5JWf$WvOFeX8n5oqkO`>#U?XQn8yRO|L#6z3l}1*G1D>*M@j0 zF+Mhp^a=M}oI-DoFAz- zS-Sb`h4mt9CPpp@EsuQsaOdu-$e(kC!YsHV*jTxlS*N%k{u)=XF%0a;6Kf5IUPuoh$q1-@|vOk0qZpZMO>Zbr0M6 zW%FCk)vEV)wVJN~mNGdyf7YFf$J0_8WY6EYo&GEA>=tW=qY~+tS<=N;Y4lubU{9UU zvq?_;O0h}u1+H0Mw*7_)Ni5b@M(U?L9PgK#f7@Vd`)}Tw*Vm@4oSfTVzwGy`n_^pX zbE^HqFU_8n*7p6r&9epa8~N^cRGNQbeG-$i|J_2d^){yuO5d)q3}d{yMdr)H_ciYu zb_&bhP5#ob;@6}8x|S_VnP1$^syaJ8ef~{Hd!y6!@9#gXzWQ|H=d-J)PhEZbe(40LGMNO1-8y!GpS~=&hElZyC>Hy zel@8iX-#|$W5J2w1*|8IF^Oa_a&2K?jbZ_l9X8tH+cYY;^JgA>dLtohdBB3R+v_(J zKAtM;T&>LfF7%>9`L)EJEv<8Wr=5QFZ<_7OpU>UR?ryOZvzfFNBeYKFZOn{s*!Z|qV*Oq@*|w@_f867L-~IFF{jQfzbd zjyfJ%9An?lBgJrBoUbTXHG$_pYwpbzu};x$e^v!vn#L*~aW97@)%KmC1c$3+CG)%w zR}R=S_DKqSEAC~T*7#pdNyex`_0a#9%xZ0pn|5aBPr2B!jJLS8-S4ztol*ZbmE{r1 zy_-_p_6MrVzN_$>1miy$@i9EkH`L=}@o{C+U@F~Bk_4tW*LA)<3W&gKS zpR;(@SE zO&6=(L8in_O!E^O{Wr|Hw>u@=X{U!w*7BFq%E{BeCY^NIG2gT``fua34JSo170b6& zK021W^2xN>W?bLx62!js$=3ee{KL+>vv>(-K``^&D(mcvtTS3~oNC*-)KU9_-lL<; ziJC@_j-F_-v%O+#@#@r%FWcLGm2X=&@Bgvh=NI;uihGx?>)D^1Jo&5WuZhhp|I%M@ zv;6aXwRcL2xn7sO^wckho4IXd_!j+HIpm}CStGa~dqzm!WA3b>UK;YFqv8e3q zS5m%T<)nDIZ#d1KuCTcN|6awJ*Xs_56=n&~&KD^NJ9g3RfM8tnHExTb#DEnl8&=+! zp)*@hFF?&9N_3*((*kqBwGpn{UUK~EDB>25bN{eRq{Y_ix0&SG*eD+X1x)>c_V<)EX1X(_|xx|EVt_pY>PjzO@6^6_MG30Am02Njvv;oo^!u6 zH1M2im}%kpski3|UQaGO9{T+C%*@*bR=3{YpOG)MqS%ye_Az7LedjvgoM^1zx0dnT zdUY4q#UCE`e(ImxxJX-E^7Ak0&2If`9hY)1wQkz@Z;P&!WZ~_@iF@}hTbh*i!T1uzjWc+g`@S$+P}SR7H?ztxA?-g z##y4b)*bb|>UC>fK=M+Ki(DKRnVhyX24zr<+TTYSj-;`?GT(=mIWWAm5ayVbqWNv84rp-0?V6XlM+ z-}iF2{I7em&(|&dES`8pe7|Q#0Jm3QmMUN-kRp|}67(amqGGcO;VzVLti!rS_F zQ}a|$DY$MIlJtnt|M@=r%~w73CHii*_niYKcx3lVxrFUsSEt)y5zl&2|T@4VAJWAKN4Y46?esi z4cPfijQ>CWzQ_C9y4w>LeGyl2pRZ@zddp(xazpK-Uls+=NMi#_Xj^K+Bgp|{dv zAM|(+vE4ksK(17?Ic#cOi=1smf%vbd`|i4g?~t^d>2~jt%Jbg#)V<16&0cTVHqmrh zUHO+6oX;j(>)$F1dGk=QZhv6>1#NZx>YoP5TmIyp>pCvj@~t=N_vy$jXLjnGdA>%k z;>(Noes31kZ+)Eq`eD9Xl(X>}feX1|yZB=rXZ(p-DZ~@Ql=n3!;AGwN6OW74`(lps zOr7`d-*?L$*L2S;+OJo$IBEW69)VTP`+r}UXB%THT`N^N^PFn+lwS!4|6Ko{Q8~@d zc589p8sBxT;TP^_n6H@{_-dhQ%>Jy@^DHlKEjhldP$}RFM_JUF<~#)m)%YUT5~aO+ndnPM#2$%cIZn;(iHR^^z5ZYy4ZSAM>WK zd*x*w`TOv?Hzhwl-JHL3^RFKPuXX*Rud>aY&AWkjquKwqv*&U)_}Q*pf8Q$d*Ual% z?L}jI6HWR4-1Ohi#$3kyM%*~%ZBSY`+dMJx4AldVean|L>^ySUCdYV_(1gU`d5#R* z7#}1tBuF#dU}M+@;x*(d9JqEseP^x1-V%GZ6F%V=x^FkQO@3+l+G9zfMe4Ta$EDS! zM8nVcK94HO^p9JAdO>}v^TC6*vboi5%C@~<^skC9H#_$xM!fLPy=PBe=y84d!gOKs z-kkprkH>HASyG(&P5$lu)c=t={~oUWuaR}yBHC@+R{zo}o4LVjUw&;&bH5h$=FOdu z{J8sKQg`n1CHGj}O-_5;_A=A&dUH`HqvOexp9=)P)Ns=VLD>l@r|Oh1x**e{o-r?+vV zp@Es3gfw$xF zx)+wOxMA=KdUr8BTzL1bu7mXU`Rg`c|F)&oTHQZCBrdeI?n*s5YklmlMd7-l&rY%KxpZnGSH7mo;^0FsrW|@P#lT9n$Bz@t zYca}lz3=*_KeAu-tkF^F&0f<^%#Cb%*yhoHJH1y@Y2D>lr=MS2o9*%C;`*0YgtuPJ zS&*5XDN&o3y?MQE-qSDBf3-5aUA8?S_6o{g!Jd&RAb+v+ZHVo!4@mZj<^BS)AxOl~ul~@OY!ceV^>_*A{)fS7I~o zj+DRovDmFu-M8LptL4u8)pjsxkN(XAW^dMoo_e)AxN+T-wO*MkOkZ95;(klnEqIBp z$Ku_STb;7fg^$M{e|X&Wm*|37#@;$fx0e3->boTVCEwOZlX8|th=qQrDh&(2P`Fxm zg4p(&7ssC8SuN~bTdcQUJ%3SsVEC_A{T*dHN_efrJ{_C0G+Ogfu~(pdQqGa*Rz8W< z&%D-54xiNdXurtWn?27L)e{=n9-W48yEdDz4?$P^)&Bf}r38>s( z(JYy{{Kwh#DXa}*k;+Ts3!<9MzRoedD*k)ghqcfyyy{^#C`w`-l}+5cJgh1p5` z?}75UA8Jc~zOD(rm3n1^_r<%3vQO{WF66J^5}6P@KSSf&xy&oOtd^}xyDG3Zy7nVq z@!mPh{oP!joII~{k$-hqn-gpD8ivzK$21C`DY9;DQfbk=!61?&pmBpCl*i#9+kyn< zfDMhyA4Dl}CPr(0Z`nJ)ll8jKH-qUyr89T&hky4;v%Yd~>%@ceELWetm@#9srK~0M z+ShTyoNUT1SMCdbbd6aWePLpU_zc?Dq?Q6Wp z)<+^NOh#*0+nF0X4`02<>p5fpp_!7)UVkKzI{5Di_p!cvf%RAH>MhxFAsL zc7Oc3lK$dDwRt+i?>3$>DO$Amz3Q*+u@f5j2^bi3}+Vibxvx1Px(A-z?r!DT8#r&fcDXk!as_so>6 z-3$3cBJVscf62sH8=yY*|Cv^uY2~Kd5|}4e%%8QH?^y9+Nn?-QH&41fP1O06_G{5E z1+gmqcVWu69t*47J7+TUcE#i;YPVR0i+Q&SC4M-wBWq>u(yU1RNVhF^sg*5Uzk9vz zz7W-Njz4rUAxQEnFJrr-xo(t0UXDIjQvTg15oKPv&sohEFD|(Dy2RA^5VT))_uwAJsk18d_k~yJwNy9BL=&sEe^lHcyWG)jL8+xwJF-w!aK#@cXJ$? z)NX!lQRD7&_p4gpoO=CmbM%GdF7>6qRDblfS#5h1v$i4p=%GLRGyU#;p15^Wsk}wm zvUs!7zb!dWM5^*%3Vf+huG+ALvzF<0-hVFpe;l>zv_FggtIj_gKW)4E^xmDUs;l{h zyp1@f9}NF~zwV#&`%F3juij70PAisse0<`XbtOE3`iry6-recC_U2C4@%7ObZ8bjf zKAjq+jYS{g)aNiq@K!2`B`^Arlq{2fn$^#}VvgYJhkMRX6+EruwkZ72tu@^dIyXPY z9E(r=a5Klwd8++n>GM%Kf?wq7e{|+7kKcUt;Jojqzs_>aJoG02%iMI?Xw!e^-Uuh! z*L+;oTD_v%r()$=akWRj$NLN)?w36_@BW4FZX4g5&S0J-XZ`S`dw!hhFV6yHD5VstXhc)H~R_raST+GArAgksSWHF7JTa-Z|X1 z0qoOqJNB(hyRgFgVe#uVWmgM&uTC%VsQ3P}@LtG!6V|Va(-+>0cyG|k!?=Ck=5!Tt zu07}1wNV=vnfl${h3fN7 zDgy&!vx+OWY`Pfu<@F1Pb2B}*@6vfIyZEp0LA|{>&%e!L%byf`m48Q*-37ZU_K#0_ zKgArM`s9g!@+YQ_%8s7S+aEa#4C5o>v}R15^Se7zG9D~PG@Yl_`#b0_5ow4 zU^3J5Yi-RhKd?<~bK3K9{$$I7gr0wuZ_czIUhkQsoHm!otyv&%dh6@p=lOdh%P#-< zS-bsC(P_yY7tFS-`r@6UU0aw?^WaP755^DLp9Pnm@D#C8H!Qlt@_F*5yZ%$&9s8`Y z_k+PNyTAP*+@>LMzLnSfYJN_(*wEj@;O+I5>EKo7gIBp(!ueZ5`M17md;mh7Co)>g zvrnGt^mcx-(pl&A^V0@Dr{-34yLj+@Z?etrJnz7G{Xt!z#wE_}SD&5XKRRpM594#+ z92DYmJ=xlhFW#{u)8yu!slL0dm=~Ieurr@^JS@0%z3$UhpG%iqm72m;F2N(&zg@z_ za*Z-u^WjxyuXtCr&HLuC`r?F-n|u`~U*2^qV^g%r4}L9eX@BW8Zj-M)Ub%h787p1y zib=iuSnr;Y@Q`Vo_x;fN=gK=nCD@ttn-Wu1&u>0gaN{LU>%0ONCBASCm-|9x7EX%o z$~t!}?H?z;68OvftG*#!Wu@FEwi^pgTshXxynkS~Lsrr6pzLAsP?sHgen)Tt;&6GP6Z(ow-D9Jzhbo-;<*Z!;$p1tX& zuX@;8E3=tr{p6h2TIF_M+*qt-IAPr*!|a#QU}k?s1D z0`3=zv*wyk2uctCzHVPmezHYgMyl*b(>LEr{UaCeO341Cu#36&R>~y)lWV?BdwA`h zqVs{c)lyeiy8o_A%9i+Ab<68|-hIC>6{nmxn{a>1lU-=M=X31Q=Sx-`)t+WFgZY}~ z^E?gXZ$HoX$M*O2*#3HP0 z{%Z4Lrt{Kz*Y7fx+h_Tgdc z_j}9JU-Da*1#okRuxwo@`D=fMYOm`SGp^}31Lbm+Q{x|=a*6Nk+c#Ky;&gMv_vO2jUnJi+^JVO;%4Kh4yIqBO!guyv)hyj(KiAz|I{n_o zZCmd?eL3f)!&!Z!&i#K^i2W7Y$*sKcN5;Xw+p`OGY`>aMSZvP`u=;88%hjHJ&8bXx zE@*U`d#mld!@*<3blg;6o+9(S!1KcSTDfeev{O#H&2j2k@Ha;(%6gJ-@7Ai>ymIQ< zh5IhA*_Sod=Jjc_*ICwEqz+^=7Q9_l&skAB>9}^YZchf|HAb8Ch*vL!x=UwPe`vgA z!+GgOg{)}Kb({I=30j6s^Ve^Q^*^*#e4X%(kInrTzje&psvWt)@VxW(Wsg6a?DINr z`6+qkmx_B2PxLQ0POfa{y6gD5eb=tGw%xnigR`Ue&YM>H^2{!={@tmuC->UeFP}We zPWky$HW8f}y{A-q>)9^0uRq-LXVYtgaQA!p>Gd1_{hs-JhjiP+L+UdtfAxnzwB`CWJ#XbMJb8l=- zMXchBPsi@uewkqbIGBJ+Ri1uM`YBfx7xYhdV~zgZ=ETh(tQF#fKQ0n2ya& z8iiSLe-B%;U+OSriJC2Wg>8q8O3~YW_eJxat-i4PzO;W-|IhVN_)`DB|D2}F9N%!Z zF7?~YNEPS1N7(xn4dZ*SxUZOMW29|!;?Ir)=f9dUUsiMbwPN3rwKf^9-PddHCA?(0 zd6V-~(`3*hF!B5iB|*D4&gSHMaPW=mD-)gGhl;a)C7o;LQ%$7Vp%=O^12{V9BhHD1U%ERT9n`a0}O#5A|&s}s(oHaTS|9f@G}u3_GI)YdC<{_`B+ zvWsiys`_bL8Fn-UXM6G-?VI*i{kGiu_w_qo&zgB{vr5jpd)3u{R&Vm#!h8J0!apor zQSJFQ4bIQ^S$&KRzRaU~pgYd@S>~+y%dbx^5^{HXFzMmP!i<}rX1YS0zjo56@~)@W zFRUTaH|vJd%Dh(wzm%#Z7pN5!Na|0${=sgxQ{BAt^0GEXDIYX`b|$&E^~p*cY~uLLB*R zdZzx~$qFX~=F7hMu#&%^GTUPN(FHCa)sM-QTzt91H<@dTo6l1HT{7uA-M{F{Y)Rby z<9l1R`^Uw%qTJ_Qe0H+-+NAij_cPw!-g3UJ?#vDAvM-Mg@E$e&_S)(D+ynhQwWsRT zYV6(3kJ!(@;3(`bKl${u^B00AefoX$Q{=BHka)89cqaMrqT1Un)1KSP+h1b)%=3PI zr{SqR+6`4N&9cuLRbPy`&|kH4fxK*5P12cuLHEBlHaB)w)!sgE)8YTQZ@iyBH-9c) zI5Sjt>3-AxExuy8>Mz~z6?S}gZ7TfIR5Nw?J!jo}vf8J^EMq22o**Ls#*OErUSmg$ zfswetMDC6gtS(Q4z@*abJ|0h<Jg9{v+&{%=}M0?nqJQ3$Ign7Ab)8}j(*w`?~z zcD`Cr=ePFBjx(RzSEU{j(4J7qSfVtmMI&*x&h*!lyFY&7^!UtpsfOuNO@oQN!ddp( z4~&;;_LLV-`P4Zx?cTnAp+50T!CIfvn66D=`CuczM%}eSFG+L8=2a3?NXo~9<6t3v#l>6z_BjMN}C$Kp0 zeF|C1IE}ri)#U1&jxhhTI%PZZ4$Zq^D}3`y#p>m(tINaKPXuoM`rc;C3Fh7R_SmiG z(7E)pW4+#`cKqlk-jbR({GPTQw3+|TlKy3w=eg! ztYOXc{Js9;=Wkkv_Q$t;;ydQgdXZ(9c>a$^`<;J&U%026k;yIkg5||-vF3po2v2FoW$_(v zmL76D`RI<%kAAP(smdGn=ucH5zkdd7>-vF?^j zUDUks+O&{`y?S55GoMTjt@>J!UHp6hoZS27LSIYrvNdzwe!1zZvH9G^*k6m!U$(K> zm6jrWT)DGe=HNl8dD~N2?p)w&YTjzo_jS^z9TEEy19!&j%#XOz=cRMs>vF;VSa?c0MSk`~rzjFP(3meM~RIF3?-zu)!lzE_m z?ZUB@G4mIGacwdCWF%5G^}Al_5kMazWlm|FEn!`OdUi|4K&so#1?2lfv zzguql2}9nbzrI`AZg~FNwO~QM`cBc9r*F8XPuiV6)3(U;j4SiRB$-9_E!mk-@}|mq zg*7q<7rEG%&0l!xok>Nu%*&+f0m+*J{QfNdx?@hMntSh_+m|Nte~J9z;$Xq&?|3}% z?Dotpl6N+qnZ5ScpJVMiiet|2E;0x)j{HB@>DSIEp^e#X+8p7G>*^*I_62y$ ztx!GBe%5-WO=M)wAK@=f-Af(jg)Mei9oQJQIKZB3ixg{AFVkAL(;F+ND(q^>u$>&c ze8Wy2IfjJb?+J>FH;1kj*n2%fUOr3tVzt)t%W=vMW>?ZzZj-#HGt2+N@y#yxxjy{5 zwnc+~kHfP%dHe6)lYV{g{+j;Mc+#)BjsIBQP6Y?c?0HkKZ14PPzIeaKD|>}&_x@Udzp;GGk9Ys$-Cn%2g#BJA7KEsvRYr&xJ@4$jcK7<#kVbKR+!dl#xE<;z+ZBzWAKcU*gGyM=*% zX*6HjnUve7&ph>u5?ZIeOTWA){rue7(lRQJ)jKC{naO|a^p~SwYHr-yw>A0Ixvk>% zs-1U)b34L2%#O@0S*Rl|9A|srbJohYpYk^T)0?-wcvDGpM7{9ah;9Ggxo+C-yJr8) zXT={F>{A-U?mms-5Z$Svbx8Tt4;^a*kKh2yqbWRP7eD%ctg(DMwI!1?#`{bQt52+F z#iYH8>96I^sCmaf3{JMSUj224tW5a&V8LyD!I6nS_jMg{O45w!S=;x(&Q0s@)6~;> z?wLmeO}Y{%o%80I+!M3t=@J>Wl_44`F>_9<{u0|b`B{hJ%O?*+vbUx+@t$0AHEu>m znXa_&%F-2o)}}F87SGjv_2qkn=*5MxM^!&gRr+hAaOr$q)zwW_cSY9ko+y*l67F6R zS8J`QzOl!L<5YV^T<#KyjsNZ@{f)gN#~Z)jan1hDFwa~1*YEqvPl3dseZg1n^N;4F zIn|mt|8HLMPjBPDvbcXLl?OcjFRuB&e(DR)__j}p`)ZUY`a7Ij`d-m;)|o3SMU4-J z%H(_!n|V0nQT@r()ozQlrR><3blLxRK4-n?WF@Q_8buG_q$Ow3`uunEs+Vk>`1)GemEJYBdrfSF zo;-+WGGIITk8%6`P0Y2Er~DTx_)Pb{$Us4x$&SFf6Jg?%N{&6n3# zD$H^z7OFn-Iv`GE%jv84Tjwb}-QW0$rJ9U#Yy|l1nJtiizZDJ^*DLMgKJ%=NZdy8?<-!_FL%FG`z(F> zH$9u>!bwiryH-}u`96VhPeSI~a3PEL$KL(9q0d}r=ly!x$&KM#llt~fwA9-)^+Q|h z+!9%ami*~mi#0U!BRLk?GvqKm;r7ZBd1<*v?~Tjjmgz@+*6vOB_~{+6fAaS5z4DKx zKmP7Ku$u33zr$aamGuq(OpaGCxZ}8=?P;Q z>pxRpx%Er%q3?x#c1pX|f7+hWpJb<1AfxkHXG;I)r{%$Ac|I1)=STc!sFhuLpZ}?! z(XzrkpBKD=aX<5a6)v=!wd{T5j00a6{+&Hj%xi_cZ+`rbc@gnB@=sQ6-*5B3YLbUNC;w!nY-q)e9{ zaWz|=335e-zL`SiGQPPpU;D)Bx$)mmmDXEO`|1*Zlk;AC<-j9PZEt;kB=?r5c4x}p z?(VWfyjy~o+`P*2FH>%Ryl{rt@w;7LTg!HQlNWgX{`vPaJHP!+`m0&@KGyZr_l~ER zUkKaj3pBcKBh`84msgBOZs@12DPNy?XZKzUb^f`=z?h$oEc;7Mj@O{889Kqdqg`le(wLKQo~@{+{1%t{3=zv;5NW z)7#<}onG^_RI+;sI9KnnXGoXM6L_89w7lr=^drB1zu2wv^?K*m?HA<^$w!ODCH8&z zDY)Np?UtW%$5}s$PErk%sFwO5DgH?A_W#{BT^IE4g`C`*`FxYFef-SOz>Peb=!1?}0UL9&IaUisn39Z*aS@tk&i5uZxq4?e3{4Mb7%SC~5Vc zkMGa8H}6d4Rm}F=&d+JV$>`_ABjl*=xV?%DS)rT$Y#lZq^pFHQBZ$J#I^% zJxkiSa%Du$Ki5qRvm%2|6i@CvdinXf;~ziXbXnrCW#ff!oxQ=Ag@sR?Te|n*&lhHg zmKWR1f2aCXMQzrHm%Mv;-_BN=f6whlN#FC!bL32TYJRERQoT0c@xNZ?f5wgf>Z+Qi zR4@EHn{)oNSN;p-Cl^gRJn4)2`S0zQmwVWlygbixf4;outNZ%b<}W?2^7U`hU(PKD zo}WnZ=sP3#YP0sUto0i%nLTQ9>)W%dAtK79evh|h#<9ZA*)QF8oIas6sXZF zIh`q{%Xjd-`SR_&$U(=6 zadNW^GY)POGP$oZZ!goFubmO4g_C#RzAFDL>CW%#mY- z&a-rX&)@N7-~4y+)9x+b;49_6mT~Xnn&n{(kGwLKPH))nFzt7hp}6()ysoXUZauFo zC_L#Oc~>Z+=XkQIuZ8?8<=&O9eGI<~i>`EE*In9~wSZG*zx=|grIp9-tCaj^5_I09 zl)hf6_VS~MW6w|b@pvOc*e{qGN7{ofZ+uYc|E(O;{N{)*mseQ(5n)s6q` z;^dBfjaUElN=1J?8)sd+n1~90;e?8%9zSzuo@3gfprEOtZn}rz&%}rP+l}Lc+ydSu z+aIDne~%@tiGrJYxTKLzrW70Z;1cGK4ZbvNxwcP{k8pLqqMWB^USqlr*kwf`u|l_ z+MN41b=!N-SNCw~ zqo2*+p0cxeTGMgqslW1*mV=YpI8}HjD`d`CkgfKp<1)*222X+J&u)e88Of^MDa#*k zHcOknr1*$ZD_8armHK3*OOL-rC$)9_j`}JZ5xLJT_2A1_?;aRgPI}U}&ml4UrO)w{ zXqWbnj*ome?&Lpv_)q-c{icrsJN`50Cs(#yuijYy(|p07xPAXDQWdM-hc5WOY~dfn zeRg*I!YRBHzLut(S3Z9`?pxs|wiCbng=e2(iNAOBqU4ou;kyeCyk-k8eyw<={cD@p zwZoEDeji$j|JZteTBK8c?Zl-wbun)C(Yws6ww^k~)%hptu$3L#hbWWdOA7OxPfFe@ zI``i$JB-c!QhNCPS-bl7Z7X;cl4$$?oXnodPwzW=>SaZD$fh*6=EqOpRr>X&$=}Dk zzRUeg1M}_g317EvUN)0qsq(&bE}^rbd=rj*eDFghF-|kYIG)F(-RDd}Zb$0kt%rLo z@A%B$==OX8m9jrOrf#W}E@iwGBeY)Kur$77^S+2P$B(@fx7|2{T~E*KFIP%x zn%MDqpRz4GZMSwRUgjzM@I2YS^h)!b=KXb%?EgJ?d^=Riv~Ko8rH#wkCReDuytH`l z_h?_W*;jKm&0GInO}1~z@_qN3-`}hHWghnDeA;HSBQ{lg)vqOVKB}H_zIE>chpb0O zmn%QFPTpaxqS58gsde`QYr?!OiE>%y&)>#2&vxTF*t7Q8lpVWg&o#LI;!mA^_1-Dgu3a9r z+)VQB#IlEeA1zt)oUa>Nd;093cif^p$k_j;!%|k6r&flw8EL<-82*~ve@w2Z*6u66 zh}PVt-*xsxpXon$wmoDPr`VbDze}D1v$t8v4PZDp7 zG}AxBEi>oLs(Y*0(hua6MO&jfEuV1oRRZm^JUu^%vR33|x7C*1>i|?a7V8f`M-M)!(L8(joR~B zM$yyL+3X``N?usH_shlBe8bmabA&tQ3oqR(9L%1+e4Fgj_fR$F5XZoD@a(%mK-j0P0_kSwX7$11U^waCXZY{y-2V<;*PiXlro9@IH z-QXzIymQ&{u;mN)C-7J5sQDU5naZr(I61$5hTT4av~M5MPdzRx`LX-X&Th6I*Tu6G z-5aOb$&^JbG;O)!c4wZ~=^t+#`&$Dq^vr2KR#` zC@Y>9{Ii62%$+Ucxc~IrIaWc=pI%HY(=*@>);>~ndV2R$z1W)Wggm};$Hhdre>cw9 zQO4`}a++@RO2s`5cZ)k-WFP-^VA;{WX$LkJ&c42=t@Xbn`;o2FpFP)@cgb{V^o7DJ z8~E}+uW7E@AGdJc(?^aEel59o$gpZg(#&_Nd-@rzc9<4i&Z_!cA63`$_KK>t?d}hC z&+LrUb3<9*&sNs4JpEv1i?Se;I<`f2{}-<02{?5fOO6tFNgm^`d| zwffod))@i66#kk9+^q@INtRu1r}yUX<;P2Gw#;56vgz@1&5eH&gXChP`fhnv=1kx6 zhkrq~o#QEE*LAge*M6#BICp-b4acVc?wX&D3C8?$*Z42B&i{S>!&k+20`bguxAgDq z=UcG5^UU`4?pV=tua}5U@!!J#ebW8EkM_NN{iFQL(xYErMxUz7SW>rQjr4^3w@=lX zKl!d9AAEAIZrj=a7mM6}cO_Sxx?P#t_0ZipsRv5EQD0|v1d3}P=7 z7S(@UI&VGis>YwX=cJtD|3Bp4zvau0jnZc?ZgW_mn`L%9iuvHS4#`w=m3yBK81mWu zsBviU_i4GF_^G<-QL*SH<|j1^Ott6T2)DcP{q2(AkZGF}irrUj`n)|%JM+)FLpo<=D; zvpq{-FNoM67^omQ8NbArvbzl^y4cwWtX`y12Cr#@L16R&Y$dO82a zb?0oIop)QwoOz(|_{9xVlP$|HyYeqw>-$$xH+EO=%Kk4;Ki5vIVv}9CRqTPG+w9bD2#CsQHL+fUKv1G5^!+TkC z@B9bv>=!&%?oRp>AAc~dcA zK>~+aH-1XoGkwy#8=4kn$!c+|K6|_p9)(uSmYh)`YVc7j;ZbPHau4SCvPpB5a@b1yQ@mhy_0{dqBDgKEy| zNjv%SQnGumY0O?5xww-@Z29&4yJof*Uz}_AIoN1B*TUoYgVVdtS=86g_!{$L11>A4czhr2YF<}jVeap~ba6xy(Qeu}=j!e+)3IV>qN zGFw?Ev@)h7GNvRlL`wV;U<31*HnG&WpH=@NT=e9_Z@oK@(!}~i!Zmo+Y|l0G7B4Wo zAR&1tu&2EB%i+7T&3E256WzUCMEC#P%vBp(VwY{P-nCKjn3=)FdsD79E-SycSNpcW zIm=nsBU3+>pIK&B^3(Wse%+S+x5IfPUvIr0>%HFSx%t;Cn;&ku{j6#0oAca`vlbTS zR7p>C3_m3v<0sX7SwQ;7l>MfEg0*5j3{)-|tu{A4(!t$v&eSea-dFr?@yEEuZ*J{e ze|@FMr@LiuKgfo^|EO-Y-?;x>(UhKdVf~hm158T`EN?hBI7@$2&DQZ&+Vddr*aC6! ziq<*2adyYn&$5@FlijgPssDg>Z23gZH^f;H1QYukKR2#veS7Pc zkI)zS5KH66q%BKVu6(+6tNYx(Z#Pz5jjP_j@?K`3^w+AXns>METbWrMuW`frs+5+S zt=0Q$>#n}O&XFFl*Xz-3SF7iX7q6b?J55;psp-~&XMA#|cAt2?6Mw95SM7O>C`lY~Q>4{fTuaH)ucGdi8459m8{c9@i8WbhABreQiV1zgJzg-YeJ7 z{wGv>cgv5OJ*xZidSjlLzW=by#k^o%-mO)SLrZyfzxcyjl3LU296jB@^-y-Zex2Ld z-?kU44k&J`_CDva{>0wEbDMf?e`NmaDan}@$juyZnBmGHhAS85Nu_r*GOkEu$od$w z(%X|$;Yq#nPcx3y=hP(F*4M9@+!=7#CJKHam&{r+E+E6sR0J+oK&(FXSui?0bf zy4(H#x?KMDuXVD$@$ULjQQN+M%gf&wQ*-E+&DGo1S94S=WR4gyuWerVGyKkOZT8AZ zf3~s}-OA4^ICn>&Y)LKK9@S^xuAkG8YGSp2w$`#?C2K;IZ<0#5)xp(s)b~3DHlCkR z(f)tIocME%@7d+eLe5{kx^QN#{9d2;TaVrO7;s`&bDeH!O{u3_IPd!&`?kU8n39&QQZk)We>blU+z}+EMHIsv%o!V(Br))WCYD(y(PJiA%!fpI<3+C|n z*j-AW##yHsm(Bacq2b;w+2Gks4_iL>n7-L~{p313-{?1i%N;i^y%jts<8INrA7cJT zwm<#!^JCC#=HKUwEQK7!?EJnQv`;+Dea6z)ve@_NuSi42>Ce8d7w)%yE_9Up?@{ho z%eNe?Sp0can?ZK?Nx%5z5v-*0z+Bh4Rwzuzu({}1yyO%fINycy1mWoftWeW~U5 zPFubBc)OnE&mOK@-nX_tcA4&!S6F1&*QkAzW#^oD(ZpuX$P;p>qkR*n-wT%MO*Lch zYF(D0C7QeT^sUEvb5-v>EMKdx57P{JhD&=eFOA6UPeoJn>RjobtO=lU?btPN-Iq8Rv7AGR+S2*D5;x zMGyKeX1v<{>BPz87?-~#`*u#yJyxr~@czAmZ`-10m-io=^}i)%asZZ9KNXd2QB*Bd&XML}eQ@Wfr_!Tp;i`>HUeP!l4%b z^ow#{>0hj!q$v6Np;uAm(GyclIA5-JDed8|F`0QGHZFUGa#o(6ShsoAkK)BQ=H2W& z_?j!qyyDY$t>11LH#?Ns)=Mzkj#~ChxkxSaV(XY$>OTpo4c-uDi8RbFWt9 z(;r(WuWQ_TIi_#*+6XT#zJr>pFYj4x$+mOO5jB>FS_iKB?>WtR;weLsr8-xEd$+LA znXa8T5=Fnc7p>L$y0vtc!})2)X71e}RliHsc<0uy%NqM;Un@QLt)e_%F}tYYpHZi8 z$K)4WwMCNl-Kr0{roSqW)m52v+*nEdT=LSunUDLpPiTpxt;zo6cGW%P+_4YOZrWPk z4Bfrk|4vcqftsy{cM9lMyjt~ImThvVvim2G^h0XD5C0QR&wqD!?6P1Kw{Mq#!+uuTVE;ebPiyY&f2zFV)V`j6!5_+YZtc}g zh6jpPgd1(BdA%`MOJ~CW;s;l1pRc!7w66PF`M>1fmW%JVt)3wDGG}SKcloaZiDkU9 z_iO9T(m-2p6Mwy6ol)QWW1orlW5)`;)v=axOLCeYE(>S$cK&JfN>pMA=Q-)aDQd$>sH$mFh>DU)k!eWCF1F74-`{wwE)|KR$Y zXcF=(Xy0D0U!704&S#KqKdpW-^vIf!4fDDt&seJdF-!mA?fVS6g}Y4c*bncYaiKHo zaF-uzq~p!gPq|*i$4s1ZJ#+W57xU+3O0S)Ewb$hBj8Bs5H{QG%a;5Ik(RcTJqodCE znBLv^bJpwV+q0~nJu|z1(WGoy>FH%#nU8Pf=H~v-WwTWHx9lgg&AK%*8tKN$mCIge zY}{KbGWBuLuA@7q+EN1;ODT}!q=UV5s1<$s)9^#j+G+E^DZ1tR= zwB15$e^owO^-Aiz%)RF3g;B5O9PD{6+kDq7_vPv@AMWj)pItEDswnhz+q4C{_V~Bd z&i`O1_%ZcS&UO`c_P?Sl<3bJlHd#f8$?V+RqIY!7ir>5aHpdmsF|`yrm;B{G)IR0i zr>>oQC;x6=j?J<3)o(N3e>OQj*C-_TmvVCd_Pj5%kK5dQa&5NSPL{2UBa5p{_AlOH zmM)sCc;cRG-Oj!9M01bS$K3Gz+jHe{3S-to{xiHP<<26vA~M+*&3U#!DN*#Bf~!SU zW4W?<@x6n4I#s8h+j^RtwLkDoD$A0EA*Vh6a8J)(axd|a--oa-@A}s5Wp2E1pzm7x z`?agD&6Yjr#{c(9Lily9@V2Y`E8iYmW*XkJ@53t7{o8JA+j!EeU*>i}+Ae+R3x7B6 ze!0H%oXPz9$ve4^B`=7%(kNP9sMYlLzS6e3Oc&crMSK@T^lQ1K?IPdV>&F|pJ!DD# za&-Rr^Z#r1J>F&g@x!k$%a09K7jIo!{?c7+!CTg>=TFzZ{w%iTTlv;+OV(>^&#V6? z()l#bTeod@)l7>!TwA|0=`eN7@jv{qd6G}eoZ0i|&w2C6v)k?DkvaP3L#k%@oS6To zy0UHBW4rH@Dt~@iG{=VLoaw1M9;_F(OUCTu`#o#YkJFM>0>^^AF&d-7!cjLom6 zo_E)NzE_a%>)}IUmo~bYok(nytEqDPedJI6$8ERU?Ro6~&y-trWAd}lTg@EjUtxGE zm$mc?chGB|!}F6u?D+T9tkV6)Yr^#+y;QDk`6ruS=Pzj|7r*aYzjMv&&o7k!Hp?m} zuXX-%VsABHY3>QBm+oE@w=KK>eEPeI#nqE4&P%h+UJ}+cy@Y#`&~}B1LYGyl_OAQ# z%I5Eh#_oP6?JtL<8=5mGg`aRLtIeJ?Nm#TpGkouwx?{atURC<-2>o!g(eilx8e6jm z!8dP7&Uo`A!coS&X-XDbmEbi~i7#5(yEdjqg&9z(^%q;eWa#^=>DT7Ztb6$A zxmW$a5A73${$`!uwzHR&`B&)EfA%NhRcGAZz2Lput6$sgH)|I}PE20obSYv^jf2HA zry0L3?3(A?IA^3|d5H7!Y`fDB?&isM_wm%ch>iby#<%?I+*iBP{~5>EzGwgCzi`>5 z>lXvB#QpNW;;?T0lyi@adg5i6|4Xe&Jh|!b?E4}ScBdx?F0uQmni~7Gj8pGv$8C+8 z;~H+p-se-9X6bd@i)(tUJW(n!v-<4*tYxJSGE$D13T3{1n=g5Ni+c5~%MU}}%{wCc zc4w#A`GWT4s#!myiq^dFTl&j(-L{(Ox^yLB|68)n6FYQoK7B86p;8@nn(ZqigZ!PfRtsdH&u0xTRD6w$weD zdTr%FF>cvi7QcS~mG_9R@jUapNcqG5RlPl_< zbVzHRa<}>7E4R;nO*y%*{NLizEcZRu%InUFyT5$6xS0RV`weT}yjJ}6=1=`WcIOjM z-F^vZ9IxWsC&bdX{=(f0%YSW(-O{u=gk#=Q&+g@V*8Pke8E z;EBe%Kf8CSKfg1%_}0z2bLY;SJM*k1duF+4nB`k9Cyj{{U80%{0#ghu9vr?QA#E_@ zFxy0a9y2>>i%A=Ml?%?zU}iU%^>_cOck^D}y(ud6?eF{D@2y?lmt6l+625m;)z^Eg zzt^2N4l2JiuX$%*$mX94MjPL4_N#s!?kuav{L0EmtEV)r(o@dr)vbS>oRdsHu^8GG z9u$1lq;BDKK<6ok(ihfZ>(0`pLgZgY}X`ZV*g#;2J#7W1E-c>cl&W!hD;C7n-h+&j0M-_HETO-GTg=lqXem90N@GePk| zc6XxIYu81cZPpJg zB+Az9tLypE7j^jK!Ur=>e^@5=(XU)VyuIrDW!0m0CtG|G0eeVXkI-MkBji_lIXhyAmR!4xW3H8o1ZwuA|%YO>7Ry zNjpB>jM3M=P}k-2c?<5%tIV({sJM8(*K$n6yvKZ)eE+jt~7G z>tgul_y35E^54&{ozHf{?t1dk4F}ltmpi)rczcTDAotOkm6bE%?#N#~5-X`*t#{y} z|Ab1<`Vi;(km7xZ6?9TuD=x&;B~6fv_|eoZs5p&HJXOfh&q@|P6NCFR873>s|VK^VY{}ALf+SewV%YLRWCfilR$j4(eaq;=;2f zYUwpru8%2xx`7YwL`vkps=K9e?Wp#)<|CUl@9|A4;7CwtKjnP>{DREC+FJ@|-MIVh zl32yG1?|ck<>Ca-#MEh}e;3=pU{S*0$A7)+%ZD{KQ%--{wZl{-dBcTyrtb{a^u5Y; zTN~0{c72VRjoQ>K-MrV**Y_;$-m>Q1pRB?!bF(k(|5m;>uUGQIDWQ2fa=)49$ngCA zZvo)4ZUDQd6Ewt4!% zRD90n#Xql16F#@|!L4rpykB?UPk8=U{NeuZ-TQyteg8p^cgyR@Nt++1Wf^W~Gu)u9 zwDUJhr<2-;SV;qhnFq?XFPD0GE}N_}pXFBloQq6pixR?LUBBiP`)6}+=Mk^?_U%iv zs<%}wIXK_nD!X}F!0%IM4qU5n->}puV_A}R3^GP=f zw6%AB{>)|)cRuXKpEZHYoS&bK(F~3_)VtO8SHkIM7xQH*+3#BK`FFsjPxbx!rm}dR z_vLa&-Ip+Byw>no9V5fup1E9a?#4foXZA?+FXsPWz!V}=m8KT8W@ebAWQ)q>>T)lE zMWyLi>++&Dy}Ncrev)AHp`brPQK!{zPB{6AFIT6IcddfL%#Qf*4gEJPwnmtT=19m* zK02>}Q!g@%FJzOq+^m_E8P9snGah^E%T~I#7>9q`ez0_+W31L&{x1KV`W-)_jbB8+ zczv|cW>M#T(R1F7_jj)8k@R2p+e233$7lH^e5_f9=OqheH}LbEWlm}4=&V%U&)A-1 zynXR=-uaI4_cyg}KJJmWIAzVL6{RL|mxDJ4s_}f{IhTFeZ}0i&mZNz~+m0R==&xEH z;UK=Y;OXi_71+$9UbaU3_JU>wIIg9kugs2maZ8*?4E_=~ItF<;E@8)Ml=eE4GYI~>K z_xCB=pL0<^n!kT`HJj39x`-*?S!dU-L6}eKh*= z^q7;c)?Fv*_YoTv?@u>aRR33Fu7%8UFRLSOS?VL0C%un)_4sePSn{qU@5YT&elvMz zcm)ODNmsq=aO$bI%GYIwjgKDxJablvZ}P|Q#v6mr^KR2UpK$Gu!n$Wam)v`KPil3; z^qvKaJNavsx6YWLy=`{J!*HLIc}l9KksIVP)ZJG+nr-Z`C*XI=x*nk1*!yAIt!_QZEx5kjYya=qNIBcY4ZJ^XLYr^jzO{`%v~tg4 zv*hzPD(c0jZ+{v4>-&W?b%T$;#lA{Bie76Gce^u?LE~`AN2b_4OtE`Zmio!`v01Qj zL`j-+A7Y9<x8X$DAx>GDE39h$kuBdl|IM45!Rfs_Ep1oo#b+OV z4!_#gus^rd_MGAT^XBPa4}LpoV{jwf_;hsh2AeJ0bEVfgeKUO>mK(7ssp7$Ii5Z8OxA0?q~Uq}GuKYpElRr=Ot^j0{>_Bz496K{AXQt0(1CS&p8_mr za72{zSO-2o@v9@nTF-vJTIsFEFT1XsnO>Y5xz+pb)Y?xc=ig|1eQep4Rm$~spR#YB z*lXhVerrLVz4`R)1T(iHUY8Z?0~T4-#QicjQ=WbK4FCE|I{SpCT=pzHD0cjvSIvwK z#?lit_ORrL&o&mZpgZ=7#1PwU{Fs_8;Ws|x(Q;%BCZ?C6-DtY^T( z(QCXhq`2$E#~-eeb`#^T#BA4al337wwr$nj$o$7Aer@BGWwd*rve^9fx$+bHzT0|U zZ|RiH?d8wQejMb>x2f&jzK=`yGRdh;oNu`&a?jx}Y>%5>Pdr*|NJi zEZjW5tO&R%zRGE`F#k-}v!eHeG|#4dJi>F_e;T9TZejfe5vR3v`I>f>tL;~-eXOwj z>&4nTSx2+$|GZLI(QyBvc=)C;L%tRNo%Z?9kD0tk{6p=g&-?uS@|Nnpj##=)^pv&s z^ZMkpXVQnPtf!t=3EsBC`~UX+7mqEUSCy4gx=K0kSC&!1>N8Is7rgxt({A^(*Wg&D zwdCXcvnK^TzDNX2S>)1x(2T*;Q*N3-Wx-eVsqNxXemqS&YJw-@6_ph14T^UwRLWL9 zZ? zN9x;ku7vlCt~plyc=mSp?CH;CZzQg+(EXVAa+Ch) z5i_SOwK3S_Cb;1Fp2mssmL?{}6Vv1cYr~$FnLW+Uy1e#n1c?p33vCG(DomuPe_aWB9qPlk*BY zT>4xm&8c?NhAko)ZkZQei>BYNc%Q27J#FP%wkYn>PV27c2OVO%r6%>J9W3vWRC@Ss zPU}yJ@1;j0#U<}`^lmR&C}nWea{s2<^y0o$^SeiOPMiAX@%Dqi!_I7u&JgRLzv99A zN1YmvlWQuEip=1ttAFux=Kc4F+rDJ4n|bX0)X6(c=gd!@@T=mxl%Lc5?yakzZY*=% zA!T!HouLAITkp9&{~kP1`Nd@Nvucaj?TukdRnL7>t_8g?IA|&p6Jjlptf#zbdGCGS z&+m`?2|0Man0No_EY@pI2MU-!U0A(*zTM@kt>t_Hmw)8f8UMRw^09UH-7|BXK3J_2 zeEjR5@t=oU43bBFTXqF4^X-wA=es^k~@3AX~_=?_(|1Vqp zK-rzqzg{@w%+{-Oe!ag_EnscNUCrOV@bj4#%QJUd6U1+|9;g&e;(p_j^DZXWqsv@b z?&oRVBMm*Z43dwSZ$utj`CRZ~X?J)?&%^8oib92Efd|EB+v>@rRV+@Jdw5Zdkju^` z3a3;TzMrgc>Y>ON&jeLZrN7&fY&**N*EHNcca}NYe%J8_p218Ed+i^5xpqzC_I7vs zYqbSGHKPQhcC}tzJNeo*oj1M~>z?i5w2ZcO{#Li^)Rt%4tNMiOW*%jY?7JpgvoB1~ z=k|}zP0T-94RU?5*)QBuyl{(gOBusjSqBi$F(a1s{YIURqtuIH1+VdZo$GP)I?4nTaJe5}I=Z~&`wu@UXY?;w|L+u-9jpAv?vhJTw zLSn(6+W%a-pypiG=dJQgy{Se*{r9@VNzvccC-9%PTl%zi(WNKPzjgV^M&_<~zP(%S z*>damk1Lcq10%Ms=zpA~=eO#prPIxRNt0d~f9W$*E1svkZofElX2#@~7hL13zr1>V z=6e0kA3PJDuf3h`uJ>r-oiC{uoe1k7x4V-~Lv1SJv^ib^EjLnx58qS=NAh#^Ux(Pvn%e-=6-wy2jzd z^1HVSKWJ;*{P*Cf{s+0Oht;RVWbOR>KJ~~nt9>g}w+(P9)Ahyn-haM^ar{`rJ!!Gi(-jFhPklYkZ47jK7TV&o ztjK}e)@a*Fi?8PnHouSA!mNMV^3lc5)+tY)2lH>NK0ovEf8F2Z6-6JbD|A=$-Z7iE zK|Ro1TX|!G(w4a#bqOw4YUCvLPbs?Q<<|V#B3EwWW8aNu+cm?P63?~DKbW)n!n2(9 ztM6WuDQ&Nq;M2rEzoX=x%*toZN2_N2cFx`E=e{X5w?lTb+m&Jl6T_Ces<%fc$K1Ga zsb_a?as2sbX8cEQx1}60o3d`fQ6u*ve=?%5mdzMXig?&-Jl#YFkP zlfuOOoxOi#7*`Q-`dM%RPQZ1B)?C_q=~uVtPAfEqxJ_(=MUYt`PjrS zS?D+KX7D$;o@cjfIR74OKDOlZsm{&*wXfM1H-EDK<9I4-qqU9E%ZQs&AMb5iy=Qw& zV#lfjHCo!a5*N>(YJRrikL0?@o3``UOYc9cvwh!E^FF?_JMMg))=`$`Ccmkt-$=VH zzE({xaosMTw2Ke_rfrSfH*5OsW6zH9h4k!A?mBLBruI{$v({sS`0stGeuoril%9Ro z9O1UPy714_faRwn{*>LkR@71#9y8tO-_Imx&zzzuQ@=f!d5Pha6!)>8CnrolSI{|O z??H!yZu?j2*0tsM*)(UZV&aVdxb)}7;}t#!ZEPnVS*s^_T3u8r*EK20Fy8p1BNbQKbb|pz{N7vk={k{KBoLxOh zVNH(8JZ|GT(#$7x<~(P5e*8fG#m|-Lg>li6C#}7MLpQ&_6s&Oi#!83Esp}$Gj=bov zNZ9#&(W8f<;e2P@_15gF2oC34y-p@9)^g3RqD{Lqt?Q0#a8ig0d(65(K=a$Q??#~} zz3(QjkvOUQx#X&hgk6bqO-B0lr{T)w--R+iR^F1zcJMB>yQ>+U)ORuC*S_Cjv6~eC zp6z@&dG@i*YZ_*E{PX)(=bF1dVbUWG-&I?lF0#_wVa~_-^2S7?#E(7aOyfVyyP>f1 zfp7k7UfBsI;)i4pI+X+$|K63>zdkke@jGUYy;D~&k9U@wBKK~qm3xiip4WGICLN#p z{MDUT@!xp9^93%l`J_Jm5$E!sHecuXtDWTSGgb*Qdh|Ww*lsiD-^!_3p)+E46XA&ILX0E!@dWktbGMlz+ZLbMca*FB%0m?IiQg zgs@v*OWv`_VM4p^FN51kzqhVgX?I)Yw|}H@(4!^uZm=`#?m5cl_aplKhl2c%v*tZ~ zC>OZq@5!YRzccOPg`PkEzHftlTUg>B_C0SDRC%lP`lt7wvdk)CTs>`@;?r%pGI~an z7TPb0<-YgaMPE7cr(IRq#@{ct@A$pI?$758$^N?&9riDnw>14{44cJ2f7NsO!3QeE z=B@bld-c>^=k9H2U-v0A^e2zwch&i(lkZ<&uzkgIiL`(3S$EV<;!%ud-XC7Lzh2`1 zJqeBfb!Ea|WlG=exi2pEySDD!`NTI4e=j~=^6yf)q z^6i`M7d(&Lj(IKj;;)n6A|C5`YxjxY&#u(uSs&r8?3(lGy|AEanAOw!=DRs#9bY_- z`cT`tcu)Sh*ELSwpFhWol?Y}DNs8?Cte<&*v*_uXS&u)=7XH0U!+ZCNGu(IP={}0p z-*jz_=+<}tKTZFBzww=p-y&=O9S_@tT}lmt)6YF#JnQI2er*<3!{tjm)z@1r6==_H z+xv4v-jXNfJ}m3)QgriwPsy%2E*lWOZd>`g9WR&3I@QizDIQ?|%kWCL?hV7j^&LNS zpPBn7RTz3(ynSdN|KOan*u%+>Y8vh@jbE}(dD?4%t4F_^U5kuac~nXKv{Jb%Th5zz zVSG!Y-^eTtIv9|ft1)BN(iY=gCD%k-)-#uuHdfBBh+QI;R$ii?;=* z2ksYns-7w4#jWLZ=7oVAwUz>fh^|aA?z5j{d*tzfcPyc*+V_4;z z*WwR;2Yz6`DX&*Q^?}%#bu;#In_jM0o0PV6ZpV_giO%oWO1hi(>Gm5pTCC|boZ@c% z;{N5LUxgJc(=V&^L|yRv)gQoSq>!bU`eWbMFVO+tN?z_`netX?|KGBeI^CNxcz3>^ z85GIz?zZ#0>TMxnE?YBZO{rZTa;^Q_Ld9P`8r3|fUj5i4zTgaR>Uqb=t|?y^tzMWT zJEeAe$hP)f?5s0%rq~Ak%H8?qVo+qxHnF!0?mf9>JzF`o^`^|Hz-?OvzRI zZX2mpd^rF5{`)NO)_hL{H{vRZ`q_P zv-Za(+oQh&8B7bdtkS5SqJ3EK&4J0QU+#9S`~7dvU;eXAhFN0w{7yeTt^K|@gXLrx z^Q5(I6LPd4>nyc-wQOGe)E@ngZJPa_<~BT&I_KY4-F`^eN&mqTE~n0;2dv%NxMExk z*>`HIuXFq)@Z2J2YGFi8>zi$<%L0#!-kzn_^mXUALlYi;Ul#wj{iS1Wee~A_r|qZM zybQkf^_kz6`VUuX^~#j4m>F4^8C-h0?TuN~IjdTRsQyw-PrhUP=W4|kNu3T^bJS(E zXr?=BOn}9#ovWGt>hy3Q;$F7q!5+4lrKSHTD=qu=vm;mL)I0&KYTV^@A1S} zX6Ewvgp<|>TK4pa=Fdsk^CCtsJ7u1S`sB=F7hBj~6yh+^_fDT?%Kqo<=`P{h+b?tGUSIX{%KR6< z`}eHLj@@VaKi=KV@Dsi>>@?ub#cIrDknnn#-lyjd{&;mZ>TypMLrB z(e}X4mzHKln`T!^#eRF(e$;s0rd!!MNBITHG=)B`YsjlTxM=4Rt!>|rWVW3>{<2Bm zyr3ZM#z$|znJ143ZaS@W>HZqg?lz}qjCJefpB$5MeD5;beVTaGzY@3V_^*@p+S*o6 z3;Di%{!c&eI?KKPrWE^G_s_kj^f7)z?w2`NUw(O2?6y7j!StM&Y3Hrq&Iz`dn|AWe z?=vDFOx|b)brq~**eG!OT;Y$tX8!vhjUv_@_%Ji6@Q~Ew9<^%+&VS+EdwAi41pm!j z4gcSKdwRXy#-+K>uRiu(f9r0cZ_@oIPb>q!$VGiJlHQhW@@>Q3T7~Ton=W4LHWMwH ztv|EEdgl47c7E5ochBHXoZEZxa7wsB+jZWQ#ZOeqb&r1jy?X}tvpb(tUe4pF_h0x( z?xCgs^mmbeET2~25&d3pe_|=uyQkMy9({K(d(YO8`PyP@&TlVND=hL4J!*TWykhO* zpXCpq%S3&!JU?yT<8?cpNB*;XY84)O=kQ+VKXblz+dY?@;P3Ty;ePd9?&q$vpI@&# zrG@iSy9V>g<0}<@O784gxTl_d#VH++^p2^gQ;N(IT;rac**)D~tiI{c@NRTn(I6}@(i3TNTEghx z*272HyZN0~?~!_TVC{*SrTWtP`}&d|tKV))bNT!>%G*;VzNxIT!M)(#VV(Zw9MP|` z%NF(I-~SUg=XS&qrSx-~lQ#WG7MW>tR%)BVFZ%_PZBMHQF8PtXF2zrL^0DIUN=XxT z$r~~(F5a7F z%c)6BmPwe=Ykznb*D{rj8;_h3R7m4E?N#)vxAReHPe{{*Hzm?lE`{wusYY$RFBWlb z5xk``jcepPER~Cv(&O@jU;1G{5oPq*)7}T2A6* zJDMR~v@BxlyEN9SBW1goPD(DTxXbd(SlPKNHfN)InTOitirG3VD$cTew-eu!-;=Mb zE-IrY=6qy(p!R|!aRG53mM!T^44gJa1nJx{Y%DVl(peDz_kJg>F!|G%U@_wMvp54QDxU23dc-{yQ{k!3Q+ z!U=*|Ts%r@=cNQs?|OG+>dwnYjjZMCYnC57y2yT^%g3vW7`1%b}kwqr3mxd;92K2`sDQdjZG`GwO0*N;yhoi5HO zl&-b?>;7q8@X;+RPOt_)d{`&4J;O&v@;$qP{@j<|>2Cjc(%A25oK>1~)Kc}yF@b0f z$&1boYBBzeK40Wxb1pVmi~Z#+e` zeRN(OhoyY&mLK1mA3wfxPvuv`zwi~gp_2bs9BK^isXvms^U0nSwJk+5{{meu=qO+K z!J(rrc;S%Jf=D-(vqns_Qd@32AB<@@d~$o&o6sE1_hKIN_OE-r)u_#zZ^!nyy=D)y zXXdPlz9;qV+V{HPyMkS2PqObCwzJhLzjKuS{^Qz)+S~lOS+nGPe#{DcVkGSQ?{`w? zvU%I=+*eKRNn})?@kC*5T*>zRZwfRjL}qP%=D>Jmefa(#zb0Dm@7N+f@yzn*i|0Gv zhfcZY{P@lx$$M@po}o8(KWBc<+4v&pLh+M`%ZzLJYG3YS_I~+pseRIo{(q~IZ@hfj z|BuU_`KS0^w)5-HsIL0SveU)ChJm%)JHCqZZup;<%o>0HzSOO+Nk4t<`GfGtB`)`) zQ}{Kz?asbcJbRAI%rMH0UpUghwbo^Chn@RrjV4$7-&_}daGxog(H^(zP>22Ti{f8) zFfCgny7%j?t>tsd+Me7#aqfb==*90!N1eaqZwsoqcjN3CsatHn>ZZL~cFu||r>T8q z38(Ibl!^&Op9~cY9W%QRD)e)DMfbG09DkV6klb+Kn~lfPhvlu}8)O-!yXBWy#VgEd z)II+1QR%KZu0p#Dl2t0!=s#7yb3^xvkwx6JS93nSUR-*1;h~6Y4_CQ@G*jCRyd1j*ggVz&+SC+6nu=2iL_32y60in#;Su5gh3B5aaJNs0)eO^wo zvSz#Cqs?2)Ot;*8a7W~0R7d=uH|6PzUof(%+ofsB1RSu8x9M4I-RjpcGi^?{U5d_9 z0hhCiyH~F>o|f^gb#9^e71NEYb{&;3JoaKgYm@s8m*_)DSA17Z{b%rZ_QR`eHK*2! z%Dv+H!u`d4Q)3iwzTd}rJQllk4*ll5IwwR^H9ajbcL&d8!@e^$QC2^jmS$Xum;NR_ zH}C9*Q<8p_N5Z$>TU^sVZT1?q^}1=DKhLVoKAGM;?dRG1imipkchVc3^us%L#!TC^ z;Qhtf3#YvmNjqO*QQT)HvU2aLmK7bkIX6}$KKR}o!lrl4-%Tg~z=o%WGOqr7V(iBc zeSFmQ?%Tc3(Q4t>95`Y;y~J`oHNn;^sBbLdT~B% z>b%@-UdaU z3mrSTW_3mI$EtU=lP;h59drDrozNp)?uDz5=->5?s}ldW`+~RQx!ql*ffchkZrx;h zfA#RL8BK42>QMzl9P3gLbigY(-T$(Oq5f~^orjZrf4sjxKPbbbOYzV1Babb2&xpwqsr<8(@qb{3oz=q~^GjXI z|JYly{$INN;eM%)FP7S$zyGoGpUCuwlfQerip&33-dFX<{%6q7DL-cJ)!*7t(UZ5( zvVX@*z2m|0T@wtx%>10MdH%cdbTNIWbmQC^CK+9`Up?s#zo56JdH$OS`zyxcjq92& zvX*ryt7;iF*4eO_>BqjdC=b`we|Os}z3d;)dtm|ISyyIVwm7S(yu9Gj^W71L$s zxjxKpZ%*uFjg74NH#Pjl?>?Q_cDn@~@lvj{9qXn#tuN8hI{3+Gd)C2*%w;KMT_Q<} zFRa*(xUt>*{(icQ#f9$&n8WQq9BBJ~ulD<1-VB~z@%P&InyfICCckqJ^tKNLg5Lpw|KM72$`Zt?B zT9q6rXJ;^hf8WGCt=>v+pQX_#ixI4y_GSw@ghr8Tx!OR(=R5^j5=KU{$*^{6V4N=R=q9DR6V%1I;1T< zlXFSy3YWm|k|@*F6Fh7eZgAT+>E#DrzLHH|?M_PDS6z{s#V8w+y7`4f=bX|FMV!el ztF(H3(i24u1x$Rjma0!GS(SCU&@Fl@hvpNvolXl)tBp^lM4eTbF1C`%Yw@+*VB?^b zk|$Gw)|wnoVM-QOmdn1Bv-yI_*%MEBbcBqS`mPLH#kQ&Rube0EUGo)}UN13O8yw*i zwKQt6p;zh|jkT+?b4;wa1g$)pv~Hc}jFc^YeLZ&<&iWVQ@XIvz)I(>h-doEG6xaGS z$G@MjOJc3t+ba@xvwC;U542v*?6o&UZED)Yw#Hu#Aq(2~IhT8EW%E9gbZX)D-noJ9 zb}uhVmTo!rj(?R17bkP+=2bj=vt!TCSYx*H?!pOf!isHfCX;4<$>Ma@7BO1w^PVfL zy4SR5>14;Akmp-wW}h)zEv>lo){?LpPq>O>qWQhLHo881|KY?EweFb2&Z^v?wcg6+ z;o+^O6R!qo>TdmZ?5 zSF#)a33ZA@tumEhN^?spTB+*crv0Q(t6zDg){lu%%cpCvxg>V%Ro2S>)2Uo+c@s|a zc+K@+*cQL4HfyKb;%V8jYROZXpDqz>_gXzgiBmUl<`=Ip?d=CTnizA(1lp87f837Nh*r7XSGH*s43 z0__5y)5oGL=1mk0*tMZG+Uz5)Uu=^%lUs~&a)*~jg1V&P8e7|U@($2@?P3=>)AD_sf?nRb_p!@Q=crkK615! zjmnf2myAA^tUWcer(%lM3zo|edEdoXTvRSYd4)z~FfVh>$y*f{ z`zV>Np6IhaG^%mqjI%-y46>%Wu1lR-HJPhFb7j!#B9|qWPgWSsiixuPU}otf*Xp$@ z>_>?gbDEowo8si-ucKqambqqyp7?5I`bj**vwis~#qbLS&9_n~89Zw^$RHAYu!g-T z`-__;ukb9x+Y8fd|#mB4H9$2+O5ZZo zidETXH*k41E%8W7SrT@3NsLygkwJK<(AsN)OXe2+Dd;}FIA^QEV$ZI%a#JSN_5Yff zVr}d3L1}M@=~Q;lvKdj1xlNKW@e0Q_$;?jN+1cZ6I{R#auu+@3+{_GvSvRX}{^&jt zvp6`(Yu&uH`UkxDmS2={7R&i(y(g@BTV}G^Ns+2s-FEs%Z3Hqy1Ds6~Cop?YnX4S? zWnjNCj)8g3 z>O2jR%_r7`T?(sE%RXo>Fz1AXNOF*)VjaUAhMAH-jvY%n#z5C@gfGY`^}( z=|)pcZmq3hOmiZC)?a%2-|yu&Nzvwd)$^45osuo!E$VFTi$n&?#Z4=FkwV3t1Sbc@(nh(_HtO)p5_<63_ZJobzqCGtZ*&1_Z4v<{=-yo%bcES8z;`lVP` z<}q)bYt?zn{cOPWpzDV^PJjAlKWAZvz3S80_viHI#ztE0o@l?iXL9SZlbb6nrySbU z`&2yal;em`s0uGfDQAAVl^+^O)H*{ua{7sO9G;ylxD z?mW9qQ##w{_}Z;)T(;b)@T7R=-gEaW00`cUC(m>(m6H8?i@luXcZ%&j8zH^jNYB~-R`$8Ie_!M}`_H|%?%dkD0oRi|)}3AX zw#3Hw+!^jfeqo+-_7}ci4wNvr;4A0dyZeW#-LwBTA=B81-CFEMW*#gBXTlw|Lj~};u$zcDRYd5ds`+irmCyV75d)IAODLc_-Hu?8F zovAw?Zh!4L^F+R6*Bkxe4Punn|5t1JnK=e@GSRj+@=G@ z8-4FMEQ;Nz*nIp7v*VAGr_${rtDenjt33Z^G1~=!Lmmx+_x=aYJ2Zorr{6>0kiox} z(S1>Jxjaw!B;BJ;b$L&pJUMmJeodtDrmC+TuE85`@?YTlQtHL8eTQuoQ~%S%h+{3s zXK`vNey&?y=@@dz(_-7cG8zqduVbj=oYi) zmRZSb4u~*YE^_FcAbp|8dy#f!MC>2W#09sWY~HNsy*qz{UPMPkz+U6%jQ*aI<>vX;gXXZhoQ8_R7L8tJWxm2iN&a3qGBg;FP=Me}KG9+icb+?s}Zxn>uDa zy)sqh;@zrk%XGIb+<9?QlJmw0gJorwhZ)ngCVu2U&hEDOW5r*~ce^$$-Fz>Nch}!{ zaqX8A`=8mq>zg9JgD3G*`oZ0DH8XlIpoaWZBB!^WB2gZI0XO zZ>*G@Gv$fzrb&VO=B>@^z4CRZbn?}I83z__eEn;p&sWR&i+8@CuwP(1>z|nwHWFMK zPx8O|XR%wvFl3z9lTfyk*tlHB#NM{X$wfxv*n<^DO$CqD71{61>E*~>J*8Rg;SIjy zGYe|C`1a)rW<!PVymCn2GCNDNu9Z9)Z)kZ zBShG0W#?o$|K+DjswNlYv_JN-uw!NSUoLS$)9o08pY78JNA;7GwVHQMX|N=n zL@xc_dv3!1gEua<2t5lpCV$3VN4jnH^^&Vnb*s&{Ut?PwD1T-B^jkcyBPPB1yZOlH z$q#LB7npl{n2RsyS1$N6sb|%tv&zcG%E~Fcf5c5({w{oCeCk78&5wU}DnG?{bguba zG>Q9NyhGij!t0x(GrBSxwSThz*p>KgxzCI`zJ1{ZMQmHeZP|kwc`QViEtLMUFmD%k zS~Sm-ym@VkK8GiqNNouJ(NW(N5@5Z=!jrY^RZF5uYodzi6+X=svOz*qVDFB9deD;pLqW_NY>7uoys;Ezj{oBpNChFWg7o?c)f^h4O>ll7zK+fmWm z`Hnqij=p_s8}E^cs}r}J%UUa)n<3#Dxpw8mHaR}y<;%;zdxTy+k=NJn^!j3v)MZUm z{_5DR3wApkZTkJ{D)0I^J#uqmDnFdK{9&!&yzg2UF2){GfrM zE_Scu+4`mD>2mWgYckgthc0EF_^jsO+;@*Y&eeCaZ>hQ-6un~StMy#x6-rM|z2YR* zd3`d&$?yZ=Qq|8bTD`0nUh-S9MOf=?i^XUCpUoA%@D&kv1{r2XIjxwUpz?BRpi z>th@L*#_SExOM$QUG7tCUutHbJNzbdr3`yg)vpI$L61ZkE2N`Fnqkq?zG_uW!!!ZEL+$dN;N?cVbWY z>Wd3{rSq<@+S4nXa_{<~J?SrYFO<6abj`XwsxF%u3KZMf->8dzlM&Cm@#m?P)`xx# zB(&my{h|Z*i{y9P7*|w^U3-51c9zat;h_H+HrFP9Ws9DkZgtIU=c8uzE&7=|jc**f zH1k-AnsfS>Tfy6pIlVjNVz+&lanSan{}(oSn?GOOy}#pUd9KuZsf-04_r7vpu)Wa! zM{4e>2mCR=JT|$pH^|q&{t_>K-)Z|i>4n+L3>+6ZL~~!b<}DEIedVd}!wj(o@fQ6? zqsqo*l?yWC7G%n0%wnJQ>|tc(g3NgrOnByNIR*DTnkJAji(!^p!!phVnM@h8AiNVn zaqRQYeF}&B==)XIE^0+q0^1&h_Z~@mDw9c`3Vk^-I57YfR@JJ#Ayy zADf+b`kLshi}zA)y*bhP=%q^J_4DrajPqJj=ah=bO)G9++~s{o?U?nKX>H*V3P}}FsobLl1cckdrI@$C%?bEF;D3ICDkizSp43e_xRESU*(Eo zyT2*-^s6)Pob-F1)BVMzAO5a;Gax^5FDrMr0ciLDKS zs*9_i#eNUklhah#`QRU8(b?pR17FMb?Nuq`TBrZ8_{M|^g&q5PmWy}ZZ+v~aQo3tW zHh(Q^roFsA^Y!q;GI70otn1dR-T!PTQ&7w6pDz^6c>VgPx5^(m3u?nJj-abg!8s6Q&un=>6_r zYC6_ymq(UG?V7&p_pyh6N-V0n?ps~0mHM^)d3Y_`zv!=jUilxcUp>Em-kP&@6C%H! z;aXt6O|g=7jiL@mOVOeyynFb0?g^fY%1tfF)<0V%8MVLkaLMg$1^yX2^WTS7Z`vrl z-6G36DVSGV`R>7g8L{2Rru(a~Z+e$L?d`R@6?=6gqaN`;y?kxK^@W^1{BBX%wV!6^ zPdWCNSaIC=C#1g=J8(|RIkhlCUG9?Te`ABl|1utH zlp6O`RocZ|tv;6$t#WBziPhw{6Fs6Y{d`e#V)g%`3Hb&KM0Z|xWLT?b#v1F^tex`A z-ZymaRz7##V~f2Wo`1x-Y{Kb`7X4>;14N(OeY_*hc<+n0l=aRH0tObGn{HyO)#zUwOyP0jb%{z*49yTTar0|VDyNpjqsTKm}GVB=xCcTLX% zPhIz(GINdTgwskdeb3rk{|r8w8o%)MwRL-*oY)&2JY|Bu>|frD$d$KW{M-M+Z2!ma zZzG#7?Rs?K$;-d@j@^n_ov*a9+F(CV$?Th}L}&ZU-q@9R^yX`Jr_!GZTej{yI{WqV zmY5Clj(d$$C3~*th##xkIxR_hDU* zh_-c#w!IL>zvU`3nCDWpy7ha+bIxB$b2<9O=CPQEb0v z%_<4~rnP_N;&r=j-``uOwtdgZbl&Sb_wZirTb}JE%{;Tj|HS=k7sB@YJ?^m#mfT;S za4Gh>+_&ee?-&L239a4pcG4M9+0Mh!7Ud^moS$vf^6H-xT=V+&?svNax0ipJ7M(ZK zML$e*`MZ79+p}n$I2>8=Vj@I&T5{q$9OHJ zT&v8?zP;n|SJrm9bZ_k8w|~!O@!s0_F|YTO zdx*ANe-!JNIg6t|-h3$D_cLrtiMILt+4Fi-q}+sbdsJp6d^iT03uWN5nY6@0I9Su| z&ySMTM?(CNKSM zvwXf#{|@Qt=FhH|xV^eQ=i=5^vxH|wcz?WFk#T!nXWvCLy|Tx)U(#QE_uAc^ckpaU z=fX8PifeNIKCe^Ju4A`d(tCk7c(td@X89Mn3|0DT@?ZWde;r+)m$66b!p41DQ)5@} z-@kPNW9@1yOSKo#rDs3f=f55G=%7!mmiO%JW3_jGuWsY2tFK$Is`S#+=!t7zdT!b_ zYuzKud0OjZvtOQA7JcjD&aIZKH(QFFU)Hee;mz$Q{~SMXCgQ%)QfKUyfRv+T}Zx=*z&J=(l@Z(}0+D`95K_$}F?%PMnM+uMG9nd>n-@AQ_f zYL9$l8;i{q;-~J-oIdzNVhXq zm%r0?&qY5mx+VGDcSikv=bG1jRoo@B&fNNg#aqVM*XCdL9+-c{=2^F8=((LvPcE^l z1WLauTfX<~yloezoxObSOu*e|0khjrufEjzdDV^BORw`yD=CDX>u-&>F1Bh{e4aP#NV5I*ikzlnF)m+MN&ZkOPR%MADRZpmi#^i^7NZ)x0vNp%WFL0fHH zl;c*M(J#p4T)Sgu%|6LHK8ABXIP=Gqc@#Z8$X*^>b~9DH=2h@~r`H!xJ<49O>c`c_ ziH)Dnx7**?$N%d~{=)sURwhnTblfAnSonaD&=R+b|3_6yCU9Dv0F#GUWK){>j2zi# zS~&0Mus#!9vgQ%*jGem#Z=O0|9BveuzxMviPtV%3q^`Lc-P@L7va)2!qKV69EIszV zq*~f7*!Q(lX1u$}yf*zLWpDq>ZMR>QxaID!U3+=)GneUCgXDQkLvQZs6YReE{L1Y$ zVZFy>*L^;Id(E^Mj(tgc&l#@f-It^**1I?R&Z8|id5>+l_$KA8TXM_o#S#nsns;s& ze|AkyX}0)<@Qa~es#&s&4)3{o|A6BH1B)eFW<~Ewt+?;SRTJxWmy`VhZ?oXZhCHJM zvwIFru3+d3Ettb_+|EMpV3;CPi_)h*bB~wRiF&9p|4X^_K7aM+s@J#vG;Xu%U%rmF zHej+xNO-vFB=6j-xf>(A52bl;IhM5cs@X!@8+{9#!{>NaoQ%3)8|S#c_4RDoJKytu z)al09KUuM%J3*&3X?x|&Q`r>2tJGI|A zugrNqd!gFYiJMg?NV=r;wryWr*x9~h53j?y^P;x@)07$S%;VoKyJ?Z~hkv^ZRNpym zlP$l$_px70ueIi){DylvKdV^Zeev&iF1O=)_vQZ{qrdj;mVd8verZm1ulux->xXT` zM=_CtKPNRG9Fkqo5Z^ODvG}2N%r>ECC7!P02Fw2^irW4w)UsK>{-WW7<%X|Tx_+Ht zlw)=6y2P9dOPLObYa2xA8bqx$FzGS`lOl;b_IR-Lw z0%X;B*wuO1mn+=0O#E6T^zt0@)Q1AqxhbqqH`FZtJfXUu?QZoWuFo6(Uf}FKe6Xtg z)^&?DzgNDTy8LYX}P+XDn`}syUy(ap1;-ON`r7`!5## z`{$Ua&o27%Kf_O5zbEFduj+ZiwBmmx$M#RX7#r3$)k{C0w{p|p`$gA&C-d$Mv1`7N zY{-ABWL-Y5^``H~e0^`bW&hEg{PWDGX%F5e*1P8)fADK*&Aj^>a~W@Q)P{X+jezjJ<=ueV43XZK_MeI5Ja{`~yA z;^)?vy7hk(K7Tn~Ve8$idpLVmPKYWA zkzsCW`h3P%HGSUAuLqc?*FTny{`YJ9{=cQ%QN7nh-fPs&JpKOATiynr4~#pXy$;s_);@)un2SYpsMzi)*Yl@E@uU zc<*y_`C=O*v2QOA$i5TPdfVo;yVYy=!b>+gukcPSb6$FP4`cB<|MnA8%+A+YUT^pr zx1qQ;_|q^cBFCL=8}0_ z(`v1MoZVen@^xB`b%dSjfy7B-Cw9-sKOS?v@21E1wqy5VH>&b;GNbE&De`iC6-^-1-2 za!p10_lVbb7wTCX+CO_?*L>~rmPLwE-%QqJoLK*ohgm&dy^c$ok8Xdg-*&A2%r%MGw*6rY`9&Z1$$rl5O;J1g?1ohG z{1ews)b*^LxIlKD?SHksEpN4@rLS+P=-e0>e|_3JgI&tkDuR#HAB(yr{as|*ve)5T zSd#Wib4RbY-gv+7UF_a{o6TnwWiS4}Vy|HR`J2+2l8c|!igxG^%W+-hUA}d5=d9;k zzWKn`?wHS;>|%DGG}WJdcx(IW_ZL$#Hs-TG{{Q@RYr)ymtsiRUm@&=#V;*S>2nC3HrWnLunRwK&r&)9dR|4muE>(^;d*x&O69V5zSCx7f-4x2clf7;EXrY|wi9Jo)E9e*sF@MP`lme8Axp*LB>Qq})IDlj=<$k47ad3Ob~pPX*` zj`u#>HpDjS+MbR6^|4k790cWq7vK8CeuQpv=H7)4>j30M)NQkeW_L^DdddMrjFR9_B zi_NEhHVw1ZKezTq3_q*K9?m^Gn(CmIgLY zv%c=1sW_|Km}%N);Zr|vJ>=1vbJ31r(dE_y$&TZ{L;ymipldE$)vhSarN54Xm?_IbWu_us9T z4@;D6=EW@GKmPn};L2y#^H=t%+RVBA+pQ&?t!Tz2h1Tbr+`i0APfwdS_vh*O7k~Wg ztDaasynE&JhrG5UtX;X!RO|c*BPeb>JzUgY>PO>c6hGkPvaNiO;;zKzB-vD zSW&?HY0A`t|6g$UdZ$QKdTe^UWwHuSvW5BQR@q4_^_TTtY+HJE-4^4djbiH^mZx4a z?fkxwb^1c%AOBQpA2gOloc?90U$**L^#=K1ei^mZ+q|{n~r>?M<6qi%PHjcqg5I;pbCr;fc35b}gS> z%l~)I5xKht=e@HQ-Yl$bVEZ|OLfdvt!vv+D^GVe8{5P_obtjmR)Uoe7AJn zZ6#UFa3iBPA6=cQ+K;X&(a+~MRlgBYap0)fmaxf@OFxF0Gv_ueUS!@;6CY7BS2Vp~ zn%<;?mJ04SXIfwAuKE&W*cmtL(4TsaACsCtoYnojM@%d2^�r0V}5GiG~jD5(}oW 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 JADJxw9RO|dotppv literal 0 HcmV?d00001 diff --git a/FiraSans-Regular.woff b/FiraSans-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..9ff40445bf4a6f459c4ba7399555ba89bbf39181 GIT binary patch literal 91946 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 literal 0 HcmV?d00001 diff --git a/Heuristica-Italic.woff b/Heuristica-Italic.woff new file mode 100644 index 0000000000000000000000000000000000000000..b0cebf01de49b61c0f1ec5cb47f2687c64e918c2 GIT binary patch literal 119956 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
iP2J|6?(P$8 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index e391c9a48ea3..19fd3f232d3e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,254 @@ -# The Unsafe Rust Programming Language (Book) +% The Unsafe Rust Programming Language + +**This document is about advanced functionality and low-level development practices +in the Rust Programming Language. Most of the things discussed won't matter +to the average Rust programmer. However if you wish to correctly write unsafe +code in Rust, this text contains invaluable information.** + +This document seeks to complement [The Rust Programming Language Book][trpl] (TRPL). +Where TRPL introduces the language and teaches the basics, TURPL dives deep into +the specification of the language, and all the nasty bits necessary to write +Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know +the basics of the language and systems programming. We will not explain the +stack or heap, we will not explain the syntax. + + +# A Tale Of Two Languages + +Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust. +Any time someone opines the guarantees of Rust, they are almost surely talking about +Safe Rust. However Safe Rust is not sufficient to write every program. For that, +we need the Unsafe Rust superset. + +Most fundamentally, writing bindings to other languages +(such as the C exposed by your operating system) is never going to be safe. Rust +can't control what other languages do to program execution! However Unsafe Rust is +also necessary to construct fundamental abstractions where the type system is not +sufficient to automatically prove what you're doing is sound. + +Indeed, the Rust standard library is implemented in Rust, and it makes substantial +use of Unsafe Rust for implementing IO, memory allocation, collections, +synchronization, and other low-level computational primitives. + +Upon hearing this, many wonder why they would not simply just use C or C++ in place of +Rust (or just use a "real" safe language). If we're going to do unsafe things, why not +lean on these much more established languages? + +The most important difference between C++ and Rust is a matter of defaults: +Rust is 100% safe by default. Even when you *opt out* of safety in Rust, it is a modular +action. In deciding to work with unchecked uninitialized memory, this does not +suddenly make dangling or null pointers a problem. When using unchecked indexing on `x`, +one does not have to suddenly worry about indexing out of bounds on `y`. +C and C++, by contrast, have pervasive unsafety baked into the language. Even the +modern best practices like `unique_ptr` have various safety pitfalls. + +It should also be noted that writing Unsafe Rust should be regarded as an exceptional +action. Unsafe Rust is often the domain of *fundamental libraries*. Anything that needs +to make FFI bindings or define core abstractions. These fundamental libraries then expose +a *safe* interface for intermediate libraries and applications to build upon. And these +safe interfaces make an important promise: if your application segfaults, it's not your +fault. *They* have a bug. + +And really, how is that different from *any* safe language? Python, Ruby, and Java libraries +can internally do all sorts of nasty things. The languages themselves are no +different. Safe languages regularly have bugs that cause critical vulnerabilities. +The fact that Rust is written with a healthy spoonful of Unsafe Rust is no different. +However it *does* mean that Rust doesn't need to fall back to the pervasive unsafety of +C to do the nasty things that need to get done. + + + + +# What does `unsafe` mean? + +Rust tries to model memory safety through the `unsafe` keyword. Interestingly, +the meaning of `unsafe` largely revolves around what +its *absence* means. If the `unsafe` keyword is absent from a program, it should +not be possible to violate memory safety under *any* conditions. The presence +of `unsafe` means that there are conditions under which this code *could* +violate memory safety. + +To be more concrete, Rust cares about preventing the following things: + +* Dereferencing null/dangling pointers +* Reading uninitialized memory +* Breaking the pointer aliasing rules (TBD) (llvm rules + noalias on &mut and & w/o UnsafeCell) +* Invoking Undefined Behaviour (in e.g. compiler intrinsics) +* Producing invalid primitive values: + * dangling/null references + * a `bool` that isn't 0 or 1 + * an undefined `enum` discriminant + * a `char` larger than char::MAX + * A non-utf8 `str` +* Unwinding into an FFI function +* Causing a data race + +That's it. That's all the Undefined Behaviour in Rust. Libraries are free to +declare arbitrary requirements if they could transitively cause memory safety +issues, but it all boils down to the above actions. Rust is otherwise +quite permisive with respect to other dubious operations. Rust considers it +"safe" to: + +* Deadlock +* Leak memory +* Fail to call destructors +* Access private fields +* Overflow integers +* Delete the production database + +However any program that does such a thing is *probably* incorrect. Rust just isn't +interested in modeling these problems, as they are much harder to prevent in general, +and it's literally impossible to prevent incorrect programs from getting written. + +There are several places `unsafe` can appear in Rust today, which can largely be +grouped into two categories: + +* There are unchecked contracts here. To declare you understand this, I require +you to write `unsafe` elsewhere: + * On functions, `unsafe` is declaring the function to be unsafe to call. Users + of the function must check the documentation to determine what this means, + and then have to write `unsafe` somewhere to identify that they're aware of + the danger. + * On trait declarations, `unsafe` is declaring that *implementing* the trait + is an unsafe operation, as it has contracts that other unsafe code is free to + trust blindly. + +* I am declaring that I have, to the best of my knowledge, adhered to the +unchecked contracts: + * On trait implementations, `unsafe` is declaring that the contract of the + `unsafe` trait has been upheld. + * On blocks, `unsafe` is declaring any unsafety from an unsafe + operation within to be handled, and therefore the parent function is safe. + +There is also `#[unsafe_no_drop_flag]`, which is a special case that exists for +historical reasons and is in the process of being phased out. See the section on +destructors for details. + +Some examples of unsafe functions: + +* `slice::get_unchecked` will perform unchecked indexing, allowing memory + safety to be freely violated. +* `ptr::offset` in an intrinsic that invokes Undefined Behaviour if it is + not "in bounds" as defined by LLVM (see the lifetimes section for details). +* `mem::transmute` reinterprets some value as having the given type, + bypassing type safety in arbitrary ways. (see the conversions section for details) +* All FFI functions are `unsafe` because they can do arbitrary things. + C being an obvious culprit, but generally any language can do something + that Rust isn't happy about. (see the FFI section for details) + +As of Rust 1.0 there are exactly two unsafe traits: + +* `Send` is a marker trait (it has no actual API) that promises implementors + are safe to send to another thread. +* `Sync` is a marker trait that promises that threads can safely share + implementors through a shared reference. + +All other traits that declare any kind of contract *really* can't be trusted +to adhere to their contract when memory-safety is at stake. For instance Rust has +`PartialOrd` and `Ord` to differentiate between types which can "just" be +compared and those that implement a total ordering. However you can't actually +trust an implementor of `Ord` to actually provide a total ordering if failing to +do so causes you to e.g. index out of bounds. But if it just makes your program +do a stupid thing, then it's "fine" to rely on `Ord`. + +The reason this is the case is that `Ord` is safe to implement, and it should be +impossible for bad *safe* code to violate memory safety. Rust has traditionally +avoided making traits unsafe because it makes `unsafe` pervasive in the language, +which is not desirable. The only reason `Send` and `Sync` are unsafe is because +thread safety is a sort of fundamental thing that a program can't really guard +against locally (even by-value message passing still requires a notion Send). + + + + +# Working with unsafe + +Rust generally only gives us the tools to talk about safety in a scoped and +binary manner. Unfortunately reality is significantly more complicated than that. +For instance, consider the following toy function: + +```rust +fn do_idx(idx: usize, arr: &[u8]) -> Option { + if idx < arr.len() { + unsafe { + Some(*arr.get_unchecked(idx)) + } + } else { + None + } +} +``` + +Clearly, this function is safe. We check that the index is in bounds, and if it +is, index into the array in an unchecked manner. But even in such a trivial +function, the scope of the unsafe block is questionable. Consider changing the +`<` to a `<=`: + +```rust +fn do_idx(idx: usize, arr: &[u8]) -> Option { + if idx <= arr.len() { + unsafe { + Some(*arr.get_unchecked(idx)) + } + } else { + None + } +} +``` + +This program is now unsound, an yet *we only modified safe code*. This is the +fundamental problem of safety: it's non-local. The soundness of our unsafe +operations necessarily depends on the state established by "safe" operations. +Although safety *is* modular (we *still* don't need to worry about about +unrelated safety issues like uninitialized memory), it quickly contaminates the +surrounding code. + +Trickier than that is when we get into actual statefulness. Consider a simple +implementation of `Vec`: + +```rust +// Note this defintion is insufficient. See the section on lifetimes. +struct Vec { + ptr: *mut T, + len: usize, + cap: usize, +} + +// Note this implementation does not correctly handle zero-sized types. +// We currently live in a nice imaginary world of only positive fixed-size +// types. +impl Vec { + fn push(&mut self, elem: T) { + if self.len == self.cap { + // not important for this example + self.reallocate(); + } + unsafe { + ptr::write(self.ptr.offset(len as isize), elem); + self.len += 1; + } + } +} +``` + +This code is simple enough to reasonably audit and verify. Now consider +adding the following method: + +```rust + fn make_room(&mut self) { + // grow the capacity + self.cap += 1; + } +``` + +This code is safe, but it is also completely unsound. Changing the capacity +violates the invariants of Vec (that `cap` reflects the allocated space in the +Vec). This is not something the rest of `Vec` can guard against. It *has* to +trust the capacity field because there's no way to verify it. + +`unsafe` does more than pollute a whole function: it pollutes a whole *module*. +Generally, the only bullet-proof way to limit the scope of unsafe code is at the +module boundary with privacy. + +[trpl]: https://doc.rust-lang.org/book/ -[Start at the intro](http://www.cglab.ca/~abeinges/blah/turpl/intro.html) \ No newline at end of file diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 000000000000..d136ebcebd4e --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,9 @@ +# Summary + +* [Data Layout](data.md) +* [Ownership and Lifetimes](lifetimes.md) +* [Conversions](conversions.md) +* [Uninitialized Memory](uninitialized.md) +* [Ownership-oriented resource management (RAII)](raii.md) +* [Concurrency](concurrency.md) +* [Example: Implementing Vec](vec.md) \ No newline at end of file diff --git a/SourceCodePro-Regular.woff b/SourceCodePro-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..5576670903aea90041f214624c8dd1176fdf6081 GIT binary patch literal 55472 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 SbK%{4Uj1i(_C*df+z0@cHiz^8 literal 0 HcmV?d00001 diff --git a/SourceCodePro-Semibold.woff b/SourceCodePro-Semibold.woff new file mode 100644 index 0000000000000000000000000000000000000000..ca972a11dc428209dd66212e382b884f168e83f7 GIT binary patch literal 55360 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∨L+#A0B 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 literal 0 HcmV?d00001 diff --git a/SourceSerifPro-Bold.woff b/SourceSerifPro-Bold.woff new file mode 100644 index 0000000000000000000000000000000000000000..ac1b1b3a0bb7a673d52495743d8f86fd55188b44 GIT binary patch literal 48720 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 TMcZC+MUG$MhoYLkF)#oC1SsqC literal 0 HcmV?d00001 diff --git a/SourceSerifPro-Regular.woff b/SourceSerifPro-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..e8c43b852e10e1556268d6c17b47bd0644d6edec GIT binary patch literal 49960 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 Option { - if idx < arr.len() { - unsafe { - Some(*arr.get_unchecked(idx)) - } - } else { - None - } -} -``` - -Clearly, this function is safe. We check that the index is in bounds, and if it -is, index into the array in an unchecked manner. But even in such a trivial -function, the scope of the unsafe block is questionable. Consider changing the -`<` to a `<=`: - -```rust -fn do_idx(idx: usize, arr: &[u8]) -> Option { - if idx <= arr.len() { - unsafe { - Some(*arr.get_unchecked(idx)) - } - } else { - None - } -} -``` - -This program is now unsound, an yet *we only modified safe code*. This is the -fundamental problem of safety: it's non-local. The soundness of our unsafe -operations necessarily depends on the state established by "safe" operations. -Although safety *is* modular (we *still* don't need to worry about about -unrelated safety issues like uninitialized memory), it quickly contaminates the -surrounding code. - -Trickier than that is when we get into actual statefulness. Consider a simple -implementation of `Vec`: - -```rust -// Note this defintion is insufficient. See the section on lifetimes. -struct Vec { - ptr: *mut T, - len: usize, - cap: usize, -} - -// Note this implementation does not correctly handle zero-sized types. -// We currently live in a nice imaginary world of only positive fixed-size -// types. -impl Vec { - fn push(&mut self, elem: T) { - if self.len == self.cap { - // not important for this example - self.reallocate(); - } - unsafe { - ptr::write(self.ptr.offset(len as isize), elem); - self.len += 1; - } - } -} -``` - -This code is simple enough to reasonably audit and verify. Now consider -adding the following method: - -```rust - fn make_room(&mut self) { - // grow the capacity - self.cap += 1; - } -``` - -This code is safe, but it is also completely unsound. Changing the capacity -violates the invariants of Vec (that `cap` reflects the allocated space in the -Vec). This is not something the rest of `Vec` can guard against. It *has* to -trust the capacity field because there's no way to verify it. - -`unsafe` does more than pollute a whole function: it pollutes a whole *module*. -Generally, the only bullet-proof way to limit the scope of unsafe code is at the -module boundary with privacy. - diff --git a/rust.css b/rust.css new file mode 100644 index 000000000000..cd158283180a --- /dev/null +++ b/rust.css @@ -0,0 +1,407 @@ +/** + * Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT + * file at the top-level directory of this distribution and at + * http://rust-lang.org/COPYRIGHT. + * With elements taken from Bootstrap v3.0.2 (MIT licensed). + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 400; + src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff'); +} +@font-face { + font-family: 'Fira Sans'; + font-style: normal; + font-weight: 500; + src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff'); +} +@font-face { + font-family: 'Source Serif Pro'; + font-style: normal; + font-weight: 400; + src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff'); +} +@font-face { + font-family: 'Source Serif Pro'; + font-style: italic; + font-weight: 400; + src: url("Heuristica-Italic.woff") format('woff'); +} +@font-face { + font-family: 'Source Serif Pro'; + font-style: normal; + font-weight: 700; + src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff'); +} +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 400; + src: local('Source Code Pro'), url("SourceCodePro-Regular.woff") format('woff'); +} + +*:not(body) { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* General structure */ + +body { + background-color: white; + margin: 0 auto; + padding: 0 15px; + font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif; + font-size: 18px; + color: #333; + line-height: 1.428571429; + + -webkit-font-feature-settings: "kern", "liga"; + -moz-font-feature-settings: "kern", "liga"; + font-feature-settings: "kern", "liga"; +} +@media (min-width: 768px) { + body { + max-width: 750px; + } +} + +h1, h2, h3, h4, h5, h6, nav, #versioninfo { + font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} +h1, h2, h3, h4, h5, h6 { + color: black; + font-weight: 400; + line-height: 1.1; +} +h1, h2, h3 { + margin-top: 20px; + margin-bottom: 15px; +} +h1 { + margin-bottom: 20px; +} +h4, h5, h6 { + margin-top: 12px; + margin-bottom: 10px; + padding: 5px 10px; +} +h5, h6 { + text-decoration: underline; +} + +h1 { + font-size: 28px; + font-weight: 500; + padding: .1em .4em; + border-bottom: 2px solid #ddd; +} +h1.title { + line-height: 1.5em; +} +h2 { + font-size: 26px; + padding: .2em .5em; + border-bottom: 1px solid #ddd; +} +h3 { + font-size: 24px; + padding: .2em .7em; + border-bottom: 1px solid #DDE8FC; +} +h4 { + font-size: 22px; +} +h5 { + font-size: 20px; +} +h6 { + font-size: 18px; +} +@media (min-width: 992px) { + h1 { + font-size: 36px; + } + h2 { + font-size: 30px; + } + h3 { + font-size: 26px; + } +} + +nav { + column-count: 2; + -moz-column-count: 2; + -webkit-column-count: 2; + font-size: 15px; + margin: 0 0 1em 0; +} +p { + margin: 0 0 1em 0; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +footer { + border-top: 1px solid #ddd; + font-size: 14.3px; + font-style: italic; + padding-top: 5px; + margin-top: 3em; + margin-bottom: 1em; +} + +/* Links layout */ + +a { + text-decoration: none; + color: #428BCA; + background: transparent; +} +a:hover, a:focus { + color: #2A6496; + text-decoration: underline; +} +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +a:hover, a:active { + outline: 0; +} + +h1 a:link, h1 a:visited, h2 a:link, h2 a:visited, +h3 a:link, h3 a:visited, h4 a:link, h4 a:visited, +h5 a:link, h5 a:visited {color: black;} +h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, +h5 a:hover {text-decoration: none;} + +/* Code */ + +pre, code { + font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace; + word-wrap: break-word; +} +pre { + border-left: 2px solid #eee; + white-space: pre-wrap; + padding: 14px; + padding-right: 0; + margin: 20px 0; + font-size: 13px; + word-break: break-all; +} +code { + padding: 0 2px; + color: #8D1A38; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; +} + +a > code { + color: #428BCA; +} + +/* Code highlighting */ +pre.rust .kw { color: #8959A8; } +pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; } +pre.rust .number, pre.rust .string { color: #718C00; } +pre.rust .self, pre.rust .boolval, pre.rust .prelude-val, +pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; } +pre.rust .comment { color: #8E908C; } +pre.rust .doccomment { color: #4D4D4C; } +pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } +pre.rust .lifetime { color: #B76514; } + +/* The rest */ + +#versioninfo { + text-align: center; + margin: 0.5em; + font-size: 1.1em; +} +@media (min-width: 992px) { + #versioninfo { + font-size: 0.8em; + position: fixed; + bottom: 0px; + right: 0px; + } + .white-sticker { + background-color: #fff; + margin: 2px; + padding: 0 2px; + border-radius: .2em; + } +} +#versioninfo a.hash { + color: gray; + font-size: 80%; +} + +blockquote { + color: #000; + margin: 20px 0; + padding: 15px 20px; + background-color: #f2f7f9; + border-top: .1em solid #e5eef2; + border-bottom: .1em solid #e5eef2; +} +blockquote p { + font-size: 17px; + font-weight: 300; + line-height: 1.4; +} +blockquote p:last-child { + margin-bottom: 0; +} + +ul, ol { + padding-left: 25px; +} +ul ul, ol ul, ul ol, ol ol { + margin-bottom: 0; +} +dl { + margin-bottom: 20px; +} +dd { + margin-left: 0; +} + +nav ul { + list-style-type: none; + margin: 0; + padding-left: 0px; +} + +/* Only display one level of hierarchy in the TOC */ +nav ul ul { + display: none; +} + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; +} + +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} + +table { + border-collapse: collapse; + border-spacing: 0; + overflow-x: auto; + display: block; +} + +table tr.odd { + background: #eee; +} + +table td, +table th { + border: 1px solid #ddd; + padding: 5px; +} + +/* Code snippets */ + +.rusttest { display: none; } +pre.rust { position: relative; } +.test-arrow { + display: inline-block; + position: absolute; + top: 0; + right: 10px; + font-size: 150%; + -webkit-transform: scaleX(-1); + transform: scaleX(-1); +} + +.unstable-feature { + border: 2px solid red; + padding: 5px; +} + +@media (min-width: 1170px) { + pre { + font-size: 15px; + } +} + +@media print { + * { + text-shadow: none !important; + color: #000 !important; + background: transparent !important; + box-shadow: none !important; + } + a, a:visited { + text-decoration: underline; + } + p a[href]:after { + content: " (" attr(href) ")"; + } + footer a[href]:after { + content: ""; + } + a[href^="javascript:"]:after, a[href^="#"]:after { + content: ""; + } + pre, blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + @page { + margin: 2cm .5cm; + } + h1:not(.title), h2, h3 { + border-bottom: 0px none; + } + p, h2, h3 { + orphans: 3; + widows: 3; + } + h2, h3 { + page-break-after: avoid; + } + table { + border-collapse: collapse !important; + } + table td, table th { + background-color: #fff !important; + } +} + +#keyword-table-marker + table thead { display: none; } +#keyword-table-marker + table td { border: none; } +#keyword-table-marker + table { + margin-left: 2em; + margin-bottom: 1em; +} diff --git a/vec.md b/vec.md index d38265b429e4..71b950b12215 100644 --- a/vec.md +++ b/vec.md @@ -11,7 +11,7 @@ project will only work on nightly (as of Rust 1.2.0). First off, we need to come up with the struct layout. Naively we want this design: -``` +```rust struct Vec { ptr: *mut T, cap: usize, @@ -30,7 +30,7 @@ As we saw in the lifetimes chapter, we should use `Unique` in place of `*mut when we have a raw pointer to an allocation we own: -``` +```rust #![feature(unique)] use std::ptr::{Unique, self}; @@ -474,6 +474,7 @@ impl DoubleEndedIterator for IntoIter { } } } +``` Because IntoIter takes ownership of its allocation, it needs to implement Drop to free it. However it *also* wants to implement Drop to drop any elements it From fa6fff585f5c23146e6d8db7899f4bb1d71399b4 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 24 Jun 2015 16:21:17 -0700 Subject: [PATCH 025/104] vec 1.0 --- vec.md | 520 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 509 insertions(+), 11 deletions(-) diff --git a/vec.md b/vec.md index 71b950b12215..a2fecf823825 100644 --- a/vec.md +++ b/vec.md @@ -1,11 +1,11 @@ % Example: Implementing Vec -TODO: audit for non-ZST offsets from heap::empty - To bring everything together, we're going to write `std::Vec` from scratch. Because the all the best tools for writing unsafe code are unstable, this project will only work on nightly (as of Rust 1.2.0). + + # Layout First off, we need to come up with the struct layout. Naively we want this @@ -63,16 +63,19 @@ as `std::rt::heap::EMPTY`. There are quite a few places where we'll want to use `heap::EMPTY` because there's no real allocation to talk about but `null` would make the compiler angry. -All of the `heap` API is totally unstable under the `alloc` feature, though. +All of the `heap` API is totally unstable under the `heap_api` feature, though. We could trivially define `heap::EMPTY` ourselves, but we'll want the rest of the `heap` API anyway, so let's just get that dependency over with. + + + # Allocating Memory So: ```rust -#![feature(alloc)] +#![feature(heap_api)] use std::rt::heap::EMPTY; use std::mem; @@ -184,6 +187,10 @@ fn grow(&mut self) { Nothing particularly tricky here. Just computing sizes and alignments and doing some careful multiplication checks. + + + + # Push and Pop Alright. We can initialize. We can allocate. Let's actually implement some @@ -240,6 +247,10 @@ pub fn pop(&mut self) -> Option { } ``` + + + + # Deallocating Next we should implement Drop so that we don't massively leaks tons of resources. @@ -270,6 +281,10 @@ impl Drop for Vec { } ``` + + + + # Deref Alright! We've got a decent minimal ArrayStack implemented. We can push, we can @@ -311,6 +326,10 @@ impl DerefMut for Vec { Now we have `len`, `first`, `last`, indexing, slicing, sorting, `iter`, `iter_mut`, and all other sorts of bells and whistles provided by slice. Sweet! + + + + # Insert and Remove Something *not* provided but slice is `insert` and `remove`, so let's do those next. @@ -362,6 +381,10 @@ pub fn remove(&mut self, index: usize) -> T { } ``` + + + + # IntoIter Let's move on to writing iterators. `iter` and `iter_mut` have already been @@ -410,7 +433,22 @@ struct IntoIter { } ``` -And initialize it like this: +One last subtle detail: if our Vec is empty, we want to produce an empty iterator. +This will actually technically fall out doing the naive thing of: + +```text +start = ptr +end = ptr.offset(len) +``` + +However because `offset` is marked as a GEP inbounds instruction, this will tell +llVM that ptr is allocated and won't alias other allocated memory. This is fine +for zero-sized types, as they can't alias anything. However if we're using +heap::EMPTY as a sentinel for a non-allocation for a *non-zero-sized* type, +this can cause undefined behaviour. Alas, we must therefore special case either +cap or len being 0 to not do the offset. + +So this is what we end up with for initialization: ```rust impl Vec { @@ -428,7 +466,12 @@ impl Vec { buf: ptr, cap: cap, start: *ptr, - end: ptr.offset(len as isize), + end: if cap == 0 { + // can't offset off this pointer, it's not allocated! + *ptr + } else { + ptr.offset(len as isize) + } } } } @@ -635,6 +678,10 @@ impl Vec { Much better. + + + + # Drain Let's move on to Drain. Drain is largely the same as IntoIter, except that @@ -674,7 +721,11 @@ impl RawValIter { unsafe fn new(slice: &[T]) -> Self { RawValIter { start: slice.as_ptr(), - end: slice.as_ptr().offset(slice.len() as isize), + end: if slice.len() == 0 { + slice.as_ptr() + } else { + slice.as_ptr().offset(slice.len() as isize) + } } } } @@ -771,6 +822,8 @@ impl Vec { ``` + + # Handling Zero-Sized Types It's time. We're going to fight the spectre that is zero-sized types. Safe Rust @@ -781,13 +834,14 @@ zero-sized types. We need to be careful of two things: * The raw allocator API has undefined behaviour if you pass in 0 for an allocation size. * raw pointer offsets are no-ops for zero-sized types, which will break our - C-style pointer iterator + C-style pointer iterator. Thankfully we abstracted out pointer-iterators and allocating handling into RawValIter and RawVec respectively. How mysteriously convenient. + ## Allocating Zero-Sized Types So if the allocator API doesn't support zero-sized allocations, what on earth @@ -797,13 +851,457 @@ to be considered to store or load them. This actually extends to `ptr::read` and `ptr::write`: they won't actually look at the pointer at all. As such we *never* need to change the pointer. -TODO +Note however that our previous reliance on running out of memory before overflow is +no longer valid with zero-sized types. We must explicitly guard against capacity +overflow for zero-sized types. + +Due to our current architecture, all this means is writing 3 guards, one in each +method of RawVec. + +```rust +impl RawVec { + fn new() -> Self { + unsafe { + // -1 is usize::MAX. This branch should be stripped at compile time. + let cap = if mem::size_of::() == 0 { -1 } else { 0 }; + + // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" + RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } + } + } + + fn grow(&mut self) { + unsafe { + let elem_size = mem::size_of::(); + + // since we set the capacity to usize::MAX when elem_size is + // 0, getting to here necessarily means the Vec is overfull. + assert!(elem_size != 0, "capacity overflow"); + + let align = mem::min_align_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + let new_cap = 2 * self.cap; + let ptr = heap::reallocate(*self.ptr as *mut _, + self.cap * elem_size, + new_cap * elem_size, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom() } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } + } +} + +impl Drop for RawVec { + fn drop(&mut self) { + let elem_size = mem::size_of::(); + + // don't free zero-sized allocations, as they were never allocated. + if self.cap != 0 && elem_size != 0 { + let align = mem::min_align_of::(); + + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr as *mut _, num_bytes, align); + } + } + } +} +``` + +That's it. We support pushing and popping zero-sized types now. Our iterators +(that aren't provided by slice Deref) are still busted, though. + + + ## Iterating Zero-Sized Types -TODO +Zero-sized offsets are no-ops. This means that our current design will always +initialize `start` and `end` as the same value, and our iterators will yield +nothing. The current solution to this is to cast the pointers to integers, +increment, and then cast them back: -## Advanced Drain +``` +impl RawValIter { + unsafe fn new(slice: &[T]) -> Self { + RawValIter { + start: slice.as_ptr(), + end: if mem::size_of::() == 0 { + ((slice.as_ptr() as usize) + slice.len()) as *const _ + } else if slice.len() == 0 { + slice.as_ptr() + } else { + slice.as_ptr().offset(slice.len() as isize) + } + } + } +} +``` + +Now we have a different bug. Instead of our iterators not running at all, our +iterators now run *forever*. We need to do the same trick in our iterator impls: + +``` +impl Iterator for RawValIter { + type Item = T; + fn next(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + let result = ptr::read(self.start); + self.start = if mem::size_of::() == 0 { + (self.start as usize + 1) as *const _ + } else { + self.start.offset(1); + } + Some(result) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.end as usize - self.start as usize; + (len, Some(len)) + } +} + +impl DoubleEndedIterator for RawValIter { + fn next_back(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + self.end = if mem::size_of::() == 0 { + (self.end as usize - 1) as *const _ + } else { + self.end.offset(-1); + } + Some(ptr::read(self.end)) + } + } + } +} +``` + +And that's it. Iteration works! + + + +# Advanced Drain TODO? Not clear if informative + + + + +# The Final Code + +```rust +#![feature(unique)] +#![feature(heap_api)] + +use std::ptr::{Unique, self}; +use std::rt::heap; +use std::mem; +use std::ops::{Deref, DerefMut}; +use std::marker::PhantomData; + +struct RawVec { + ptr: Unique, + cap: usize, +} + +impl RawVec { + fn new() -> Self { + unsafe { + // -1 is usize::MAX. This branch should be stripped at compile time. + let cap = if mem::size_of::() == 0 { -1 } else { 0 }; + + // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" + RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } + } + } + + fn grow(&mut self) { + unsafe { + let elem_size = mem::size_of::(); + + // since we set the capacity to usize::MAX when elem_size is + // 0, getting to here necessarily means the Vec is overfull. + assert!(elem_size != 0, "capacity overflow"); + + let align = mem::min_align_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + let new_cap = 2 * self.cap; + let ptr = heap::reallocate(*self.ptr as *mut _, + self.cap * elem_size, + new_cap * elem_size, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom() } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } + } +} + +impl Drop for RawVec { + fn drop(&mut self) { + let elem_size = mem::size_of::(); + if self.cap != 0 && elem_size != 0 { + let align = mem::min_align_of::(); + + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr as *mut _, num_bytes, align); + } + } + } +} + +pub struct Vec { + buf: RawVec, + len: usize, +} + +impl Vec { + fn ptr(&self) -> *mut T { *self.buf.ptr } + + fn cap(&self) -> usize { self.buf.cap } + + pub fn new() -> Self { + Vec { buf: RawVec::new(), len: 0 } + } + pub fn push(&mut self, elem: T) { + if self.len == self.cap() { self.buf.grow(); } + + unsafe { + ptr::write(self.ptr().offset(self.len as isize), elem); + } + + // Can't fail, we'll OOM first. + self.len += 1; + } + + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + self.len -= 1; + unsafe { + Some(ptr::read(self.ptr().offset(self.len as isize))) + } + } + } + + pub fn insert(&mut self, index: usize, elem: T) { + assert!(index <= self.len, "index out of bounds"); + if self.cap() == self.len { self.buf.grow(); } + + unsafe { + if index < self.len { + ptr::copy(self.ptr().offset(index as isize), + self.ptr().offset(index as isize + 1), + self.len - index); + } + ptr::write(self.ptr().offset(index as isize), elem); + self.len += 1; + } + } + + pub fn remove(&mut self, index: usize) -> T { + assert!(index < self.len, "index out of bounds"); + unsafe { + self.len -= 1; + let result = ptr::read(self.ptr().offset(index as isize)); + ptr::copy(self.ptr().offset(index as isize + 1), + self.ptr().offset(index as isize), + self.len - index); + result + } + } + + pub fn into_iter(self) -> IntoIter { + unsafe { + let iter = RawValIter::new(&self); + let buf = ptr::read(&self.buf); + mem::forget(self); + + IntoIter { + iter: iter, + _buf: buf, + } + } + } + + pub fn drain(&mut self) -> Drain { + // this is a mem::forget safety thing. If this is forgotten, we just + // leak the whole Vec's contents. Also we need to do this *eventually* + // anyway, so why not do it now? + self.len = 0; + unsafe { + Drain { + iter: RawValIter::new(&self), + vec: PhantomData, + } + } + } +} + +impl Drop for Vec { + fn drop(&mut self) { + while let Some(_) = self.pop() {} + // allocation is handled by RawVec + } +} + +impl Deref for Vec { + type Target = [T]; + fn deref(&self) -> &[T] { + unsafe { + ::std::slice::from_raw_parts(self.ptr(), self.len) + } + } +} + +impl DerefMut for Vec { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { + ::std::slice::from_raw_parts_mut(self.ptr(), self.len) + } + } +} + + + + + +struct RawValIter { + start: *const T, + end: *const T, +} + +impl RawValIter { + unsafe fn new(slice: &[T]) -> Self { + RawValIter { + start: slice.as_ptr(), + end: if mem::size_of::() == 0 { + ((slice.as_ptr() as usize) + slice.len()) as *const _ + } else if slice.len() == 0 { + slice.as_ptr() + } else { + slice.as_ptr().offset(slice.len() as isize) + } + } + } +} + +impl Iterator for RawValIter { + type Item = T; + fn next(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + let result = ptr::read(self.start); + self.start = self.start.offset(1); + Some(result) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.end as usize - self.start as usize; + (len, Some(len)) + } +} + +impl DoubleEndedIterator for RawValIter { + fn next_back(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + self.end = self.end.offset(-1); + Some(ptr::read(self.end)) + } + } + } +} + + + + +pub struct IntoIter { + _buf: RawVec, // we don't actually care about this. Just need it to live. + iter: RawValIter, +} + +impl Iterator for IntoIter { + type Item = T; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +impl Drop for IntoIter { + fn drop(&mut self) { + for _ in &mut *self {} + } +} + + + + +pub struct Drain<'a, T: 'a> { + vec: PhantomData<&'a mut Vec>, + iter: RawValIter, +} + +impl<'a, T> Iterator for Drain<'a, T> { + type Item = T; + fn next(&mut self) -> Option { self.iter.next_back() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +impl<'a, T> DoubleEndedIterator for Drain<'a, T> { + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +impl<'a, T> Drop for Drain<'a, T> { + fn drop(&mut self) { + // pre-drain the iter + for _ in &mut self.iter {} + } +} + +/// Abort the process, we're out of memory! +/// +/// In practice this is probably dead code on most OSes +fn oom() { + ::std::process::exit(-1); +} +``` From a9143a8e2a4bdaa5e642f4041677049f046dd65a Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 24 Jun 2015 22:49:02 -0700 Subject: [PATCH 026/104] fix vec size_hint --- vec.md | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/vec.md b/vec.md index a2fecf823825..9f7250c951af 100644 --- a/vec.md +++ b/vec.md @@ -496,7 +496,8 @@ impl Iterator for IntoIter { } fn size_hint(&self) -> (usize, Option) { - let len = self.end as usize - self.start as usize; + let len = (self.end as usize - self.start as usize) + / mem::size_of::(); (len, Some(len)) } } @@ -949,7 +950,10 @@ impl RawValIter { ``` Now we have a different bug. Instead of our iterators not running at all, our -iterators now run *forever*. We need to do the same trick in our iterator impls: +iterators now run *forever*. We need to do the same trick in our iterator impls. +Also, our size_hint computation code will divide by 0 for ZSTs. Since we'll +basically be treating the two pointers as if they point to bytes, we'll just +map size 0 to divide by 1. ``` impl Iterator for RawValIter { @@ -971,7 +975,9 @@ impl Iterator for RawValIter { } fn size_hint(&self) -> (usize, Option) { - let len = self.end as usize - self.start as usize; + let elem_size = mem::size_of::(); + let len = (self.end as usize - self.start as usize) + / if elem_size == 0 { 1 } else { elem_size }; (len, Some(len)) } } @@ -1018,6 +1024,10 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::marker::PhantomData; + + + + struct RawVec { ptr: Unique, cap: usize, @@ -1079,6 +1089,10 @@ impl Drop for RawVec { } } + + + + pub struct Vec { buf: RawVec, len: usize, @@ -1231,7 +1245,9 @@ impl Iterator for RawValIter { } fn size_hint(&self) -> (usize, Option) { - let len = self.end as usize - self.start as usize; + let elem_size = mem::size_of::(); + let len = (self.end as usize - self.start as usize) + / if elem_size == 0 { 1 } else { elem_size }; (len, Some(len)) } } From 8b60fe99ec7d52cf6de435d1414ea968105c11d4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 25 Jun 2015 13:45:52 +0530 Subject: [PATCH 027/104] The Unsafe English Language demands tribute --- vec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vec.md b/vec.md index 9f7250c951af..31cc70a91391 100644 --- a/vec.md +++ b/vec.md @@ -253,7 +253,7 @@ pub fn pop(&mut self) -> Option { # Deallocating -Next we should implement Drop so that we don't massively leaks tons of resources. +Next we should implement Drop so that we don't massively leak tons of resources. The easiest way is to just call `pop` until it yields None, and then deallocate our buffer. Note that calling `pop` is uneeded if `T: !Drop`. In theory we can ask Rust if T needs_drop and omit the calls to `pop`. However in practice LLVM From 3f6692874fdac72a7d0cbf578ed096ca8d0cbd1d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 25 Jun 2015 13:47:04 +0530 Subject: [PATCH 028/104] lowercase level Virtual Machine --- vec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vec.md b/vec.md index 31cc70a91391..fd69e4b262ba 100644 --- a/vec.md +++ b/vec.md @@ -442,7 +442,7 @@ end = ptr.offset(len) ``` However because `offset` is marked as a GEP inbounds instruction, this will tell -llVM that ptr is allocated and won't alias other allocated memory. This is fine +LLVM that ptr is allocated and won't alias other allocated memory. This is fine for zero-sized types, as they can't alias anything. However if we're using heap::EMPTY as a sentinel for a non-allocation for a *non-zero-sized* type, this can cause undefined behaviour. Alas, we must therefore special case either From 414f7301978b7d84c12bdbd46242daae254e963d Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 25 Jun 2015 13:53:05 +0530 Subject: [PATCH 029/104] If you prick a code block, does it not bleed? --- vec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vec.md b/vec.md index fd69e4b262ba..94bc65fcac08 100644 --- a/vec.md +++ b/vec.md @@ -444,7 +444,7 @@ end = ptr.offset(len) However because `offset` is marked as a GEP inbounds instruction, this will tell LLVM that ptr is allocated and won't alias other allocated memory. This is fine for zero-sized types, as they can't alias anything. However if we're using -heap::EMPTY as a sentinel for a non-allocation for a *non-zero-sized* type, +`heap::EMPTY` as a sentinel for a non-allocation for a *non-zero-sized* type, this can cause undefined behaviour. Alas, we must therefore special case either cap or len being 0 to not do the offset. From 0f924555e50bbc9b5e7d408c5230510d4a5bc9de Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 25 Jun 2015 11:24:14 +0200 Subject: [PATCH 030/104] Fix Typo --- vec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vec.md b/vec.md index 9f7250c951af..825104d0943a 100644 --- a/vec.md +++ b/vec.md @@ -1,7 +1,7 @@ % Example: Implementing Vec To bring everything together, we're going to write `std::Vec` from scratch. -Because the all the best tools for writing unsafe code are unstable, this +Because all the best tools for writing unsafe code are unstable, this project will only work on nightly (as of Rust 1.2.0). From 758895718c8883376f9faff883247b8abe937bca Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 25 Jun 2015 09:46:59 -0700 Subject: [PATCH 031/104] rewrap uninit --- uninitialized.md | 154 +++++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 66 deletions(-) diff --git a/uninitialized.md b/uninitialized.md index 89d0a93f6385..88cc7deac472 100644 --- a/uninitialized.md +++ b/uninitialized.md @@ -1,8 +1,14 @@ % Working With Uninitialized Memory -All runtime-allocated memory in a Rust program begins its life as *uninitialized*. In this state the value of the memory is an indeterminate pile of bits that may or may not even reflect a valid state for the type that is supposed to inhabit that location of memory. Attempting to interpret this memory as a value of *any* type will cause Undefined Behaviour. Do Not Do This. +All runtime-allocated memory in a Rust program begins its life as +*uninitialized*. In this state the value of the memory is an indeterminate pile +of bits that may or may not even reflect a valid state for the type that is +supposed to inhabit that location of memory. Attempting to interpret this memory +as a value of *any* type will cause Undefined Behaviour. Do Not Do This. -Like C, all stack variables in Rust begin their life as uninitialized until a value is explicitly assigned to them. Unlike C, Rust statically prevents you from ever reading them until you do: +Like C, all stack variables in Rust begin their life as uninitialized until a +value is explicitly assigned to them. Unlike C, Rust statically prevents you +from ever reading them until you do: ```rust fn main() { @@ -17,8 +23,11 @@ src/main.rs:3 println!("{}", x); ^ ``` -This is based off of a basic branch analysis: every branch must assign a value to `x` before it -is first used. Interestingly, Rust doesn't require the variable to be mutable to perform a delayed initialization if every branch assigns exactly once. However the analysis does not take advantage of constant analysis or anything like that. So this compiles: +This is based off of a basic branch analysis: every branch must assign a value +to `x` before it is first used. Interestingly, Rust doesn't require the variable +to be mutable to perform a delayed initialization if every branch assigns +exactly once. However the analysis does not take advantage of constant analysis +or anything like that. So this compiles: ```rust fn main() { @@ -68,76 +77,88 @@ fn main() { } ``` -If a value is moved out of a variable, that variable becomes logically uninitialized if the type -of the value isn't Copy. That is: +If a value is moved out of a variable, that variable becomes logically +uninitialized if the type of the value isn't Copy. That is: ```rust fn main() { let x = 0; let y = Box::new(0); let z1 = x; // x is still valid because i32 is Copy - let z2 = y; // y has once more become logically uninitialized, since Box is not Copy + let z2 = y; // y is now logically uninitialized because Box isn't Copy } ``` -However reassigning `y` in this example *would* require `y` to be marked as mutable, as a -Safe Rust program could observe that the value of `y` changed. Otherwise the variable is -exactly like new. +However reassigning `y` in this example *would* require `y` to be marked as +mutable, as a Safe Rust program could observe that the value of `y` changed. +Otherwise the variable is exactly like new. -This raises an interesting question with respect to `Drop`: where does Rust -try to call the destructor of a variable that is conditionally initialized? -It turns out that Rust actually tracks whether a type should be dropped or not *at runtime*. As a -variable becomes initialized and uninitialized, a *drop flag* for that variable is set and unset. -When a variable goes out of scope or is assigned it evaluates whether the current value of the -variable should be dropped. Of course, static analysis can remove these checks. If the compiler -can prove that a value is guaranteed to be either initialized or not, then it can theoretically -generate more efficient code! As such it may be desirable to structure code to have *static drop -semantics* when possible. +This raises an interesting question with respect to `Drop`: where does Rust try +to call the destructor of a variable that is conditionally initialized? It turns +out that Rust actually tracks whether a type should be dropped or not *at +runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for +that variable is set and unset. When a variable goes out of scope or is assigned +it evaluates whether the current value of the variable should be dropped. Of +course, static analysis can remove these checks. If the compiler can prove that +a value is guaranteed to be either initialized or not, then it can theoretically +generate more efficient code! As such it may be desirable to structure code to +have *static drop semantics* when possible. -As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a secret field of any type -that implements Drop. The language sets the drop flag by overwriting the entire struct with a -particular value. This is pretty obviously Not The Fastest and causes a bunch of trouble with -optimizing code. As such work is currently under way to move the flags out onto the stack frame -where they more reasonably belong. Unfortunately this work will take some time as it requires -fairly substantial changes to the compiler. +As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a secret +field of any type that implements Drop. The language sets the drop flag by +overwriting the entire struct with a particular value. This is pretty obviously +Not The Fastest and causes a bunch of trouble with optimizing code. As such work +is currently under way to move the flags out onto the stack frame where they +more reasonably belong. Unfortunately this work will take some time as it +requires fairly substantial changes to the compiler. -So in general, Rust programs don't need to worry about uninitialized values on the stack for -correctness. Although they might care for performance. Thankfully, Rust makes it easy to take -control here! Uninitialized values are there, and Safe Rust lets you work with them, but you're -never in trouble. +So in general, Rust programs don't need to worry about uninitialized values on +the stack for correctness. Although they might care for performance. Thankfully, +Rust makes it easy to take control here! Uninitialized values are there, and +Safe Rust lets you work with them, but you're never in trouble. -One interesting exception to this rule is working with arrays. Safe Rust doesn't permit you to -partially initialize an array. When you initialize an array, you can either set every value to the -same thing with `let x = [val; N]`, or you can specify each member individually with -`let x = [val1, val2, val3]`. Unfortunately this is pretty rigid, especially if you need -to initialize your array in a more incremental or dynamic way. +One interesting exception to this rule is working with arrays. Safe Rust doesn't +permit you to partially initialize an array. When you initialize an array, you +can either set every value to the same thing with `let x = [val; N]`, or you can +specify each member individually with `let x = [val1, val2, val3]`. +Unfortunately this is pretty rigid, especially if you need to initialize your +array in a more incremental or dynamic way. -Unsafe Rust gives us a powerful tool to handle this problem: `std::mem::uninitialized`. -This function pretends to return a value when really it does nothing at all. Using it, we can -convince Rust that we have initialized a variable, allowing us to do trickier things with -conditional and incremental initialization. +Unsafe Rust gives us a powerful tool to handle this problem: +`std::mem::uninitialized`. This function pretends to return a value when really +it does nothing at all. Using it, we can convince Rust that we have initialized +a variable, allowing us to do trickier things with conditional and incremental +initialization. -Unfortunately, this raises a tricky problem. Assignment has a different meaning to Rust based on -whether it believes that a variable is initialized or not. If it's uninitialized, then Rust will -semantically just memcopy the bits over the uninit ones, and do nothing else. However if Rust -believes a value to be initialized, it will try to `Drop` the old value! Since we've tricked Rust -into believing that the value is initialized, we can no longer safely use normal assignment. +Unfortunately, this raises a tricky problem. Assignment has a different meaning +to Rust based on whether it believes that a variable is initialized or not. If +it's uninitialized, then Rust will semantically just memcopy the bits over the +uninit ones, and do nothing else. However if Rust believes a value to be +initialized, it will try to `Drop` the old value! Since we've tricked Rust into +believing that the value is initialized, we can no longer safely use normal +assignment. -This is also a problem if you're working with a raw system allocator, which of course returns a -pointer to uninitialized memory. +This is also a problem if you're working with a raw system allocator, which of +course returns a pointer to uninitialized memory. -To handle this, we must use the `std::ptr` module. In particular, it provides three functions that -allow us to assign bytes to a location in memory without evaluating the old value: `write`, `copy`, and `copy_nonoverlapping`. +To handle this, we must use the `std::ptr` module. In particular, it provides +three functions that allow us to assign bytes to a location in memory without +evaluating the old value: `write`, `copy`, and `copy_nonoverlapping`. -* `ptr::write(ptr, val)` takes a `val` and moves it into the address pointed to by `ptr`. -* `ptr::copy(src, dest, count)` copies the bits that `count` T's would occupy from src to dest. (this is equivalent to memmove -- note that the argument order is reversed!) -* `ptr::copy_nonoverlapping(src, dest, count)` does what `copy` does, but a little faster on the -assumption that the two ranges of memory don't overlap. (this is equivalent to memcopy -- note that the argument order is reversed!) +* `ptr::write(ptr, val)` takes a `val` and moves it into the address pointed + to by `ptr`. +* `ptr::copy(src, dest, count)` copies the bits that `count` T's would occupy + from src to dest. (this is equivalent to memmove -- note that the argument + order is reversed!) +* `ptr::copy_nonoverlapping(src, dest, count)` does what `copy` does, but a + little faster on the assumption that the two ranges of memory don't overlap. + (this is equivalent to memcopy -- note that the argument order is reversed!) -It should go without saying that these functions, if misused, will cause serious havoc or just -straight up Undefined Behaviour. The only things that these functions *themselves* require is that -the locations you want to read and write are allocated. However the ways writing arbitrary bit -patterns to arbitrary locations of memory can break things are basically uncountable! +It should go without saying that these functions, if misused, will cause serious +havoc or just straight up Undefined Behaviour. The only things that these +functions *themselves* require is that the locations you want to read and write +are allocated. However the ways writing arbitrary bit patterns to arbitrary +locations of memory can break things are basically uncountable! Putting this all together, we get the following: @@ -164,16 +185,17 @@ fn main() { } ``` -It's worth noting that you don't need to worry about ptr::write-style shenanigans with -Plain Old Data (POD; types which don't implement Drop, nor contain Drop types), -because Rust knows not to try to Drop them. Similarly you should be able to assign the POD -fields of partially initialized structs directly. +It's worth noting that you don't need to worry about ptr::write-style +shenanigans with Plain Old Data (POD; types which don't implement Drop, nor +contain Drop types), because Rust knows not to try to Drop them. Similarly you +should be able to assign the POD fields of partially initialized structs +directly. -However when working with uninitialized memory you need to be ever vigilant for Rust trying to -Drop values you make like this before they're fully initialized. So every control path through -that variable's scope must initialize the value before it ends. *This includes code panicking*. -Again, POD types need not worry. +However when working with uninitialized memory you need to be ever vigilant for +Rust trying to Drop values you make like this before they're fully initialized. +So every control path through that variable's scope must initialize the value +before it ends. *This includes code panicking*. Again, POD types need not worry. -And that's about it for working with uninitialized memory! Basically nothing anywhere expects -to be handed uninitialized memory, so if you're going to pass it around at all, be sure to be -*really* careful. +And that's about it for working with uninitialized memory! Basically nothing +anywhere expects to be handed uninitialized memory, so if you're going to pass +it around at all, be sure to be *really* careful. From d2e802b827d5020c89e1d3290fe13602386a4b33 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 26 Jun 2015 09:29:42 -0700 Subject: [PATCH 032/104] tweak usize::MAX --- vec.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vec.md b/vec.md index e45782c45ce9..2b4e35e7653f 100644 --- a/vec.md +++ b/vec.md @@ -863,8 +863,8 @@ method of RawVec. impl RawVec { fn new() -> Self { unsafe { - // -1 is usize::MAX. This branch should be stripped at compile time. - let cap = if mem::size_of::() == 0 { -1 } else { 0 }; + // !0 is usize::MAX. This branch should be stripped at compile time. + let cap = if mem::size_of::() == 0 { !0 } else { 0 }; // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } @@ -1036,8 +1036,8 @@ struct RawVec { impl RawVec { fn new() -> Self { unsafe { - // -1 is usize::MAX. This branch should be stripped at compile time. - let cap = if mem::size_of::() == 0 { -1 } else { 0 }; + // !0 is usize::MAX. This branch should be stripped at compile time. + let cap = if mem::size_of::() == 0 { !0 } else { 0 }; // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } From a1f6bbc67ae532be0f1bfbe7a631ae39c230c717 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 26 Jun 2015 16:52:20 -0700 Subject: [PATCH 033/104] niko fixes --- README.md | 1 - lifetimes.md | 221 +++++++++++++++++++++++++++++---------------------- 2 files changed, 126 insertions(+), 96 deletions(-) diff --git a/README.md b/README.md index 19fd3f232d3e..04cfe58b3b0a 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,6 @@ quite permisive with respect to other dubious operations. Rust considers it * Deadlock * Leak memory * Fail to call destructors -* Access private fields * Overflow integers * Delete the production database diff --git a/lifetimes.md b/lifetimes.md index fe4dc6270e19..48bfcb029913 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -102,59 +102,11 @@ more than a local lint against incorrect usage of a value. -# Weird Lifetimes - -Given the following code: - -```rust -struct Foo; - -impl Foo { - fn mutate_and_share(&mut self) -> &Self { &*self } - fn share(&self) {} -} - -fn main() { - let mut foo = Foo; - let loan = foo.mutate_and_share(); - foo.share(); -} -``` - -One might expect it to compile. We call `mutate_and_share`, which mutably borrows -`foo` *temporarily*, but then returns *only* a shared reference. Therefore we -would expect `foo.share()` to succeed as `foo` shouldn't be mutably borrowed. - -However when we try to compile it: - -```text -:11:5: 11:8 error: cannot borrow `foo` as immutable because it is also borrowed as mutable -:11 foo.share(); - ^~~ -:10:16: 10:19 note: previous borrow of `foo` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foo` until the borrow ends -:10 let loan = foo.mutate_and_share(); - ^~~ -:12:2: 12:2 note: previous borrow ends here -:8 fn main() { -:9 let mut foo = Foo; -:10 let loan = foo.mutate_and_share(); -:11 foo.share(); -:12 } - ^ -``` - -What happened? Well, the lifetime of `loan` is derived from a *mutable* borrow. -This makes the type system believe that `foo` is mutably borrowed as long as -`loan` exists, even though it's a shared reference. To my knowledge, this is not -a bug. - - - # Lifetime Elision In order to make common patterns more ergonomic, Rust allows lifetimes to be -*elided* in function, impl, and type signatures. +*elided* in function signatures. A *lifetime position* is anywhere you can write a lifetime in a type: @@ -336,16 +288,18 @@ In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes are derive from scopes, we can partially order them based on an *outlives* relationship. We can even express this as a generic bound: `T: 'a` specifies that `T` *outlives* `'a`. -We can then define subtyping on lifetimes in terms of lifetimes: `'a : 'b` implies -`'a <: b` -- if `'a` outlives `'b`, then `'a` is a subtype of `'b`. This is a very +We can then define subtyping on lifetimes in terms of lifetimes: if `'a : 'b` +("a outlives b"), then `'a` is a subtype of `b`. This is a large source of confusion, because a bigger scope is a *sub type* of a smaller scope. This does in fact make sense. The intuitive reason for this is that if you expect an -`&'a u8`, then it's totally fine for me to hand you an `&'static u8`, in the same way +`&'a u8`, then it's totally fine for me to hand you an `&'static u8` in the same way that if you expect an Animal in Java, it's totally fine for me to hand you a Cat. (Note, the subtyping relationship and typed-ness of lifetimes is a fairly arbitrary construct that some disagree with. I just find that it simplifies this analysis.) +TODO: higher rank lifetime subtyping + Variance is where things get really harsh. Variance is a property that *type constructors* have. A type constructor in Rust @@ -356,21 +310,27 @@ take a lifetime and a type. A type constructor's *variance* is how the subtypes of its inputs affects the subtypes of its outputs. There are three kinds of variance: -* F is *covariant* if `T <: U` implies `F <: F` -* F is *contravariant* if `T <: U` implies `F <: F` +* F is *variant* if `T` being a subtype of `U` implies `F` is a subtype of `F` * F is *invariant* otherwise (no subtyping relation can be derived) +(For those of you who are familiar with variance from other languages, what we refer +to as "just" variant is in fact *covariant*. Rust does not have contravariance. +Historically Rust did have some contravariance but it was scrapped due to poor +interactions with other features.) + Some important variances: -* `&` is covariant (as is *const by metaphor) +* `&` is variant (as is *const by metaphor) * `&mut` is invariant (as is *mut by metaphor) -* `Fn(T)` is contravariant with respect to `T` -* `Box`, `Vec`, and all other collections are covariant +* `Fn(T) -> U` is invariant with respect to `T`, but variant with respect to `U` +* `Box`, `Vec`, and all other collections are variant * `UnsafeCell`, `Cell`, `RefCell`, `Mutex` and all "interior mutability" types are invariant To understand why these variances are correct and desirable, we will consider several -examples. We have already covered why `&` should be covariant. +examples. We have already covered why `&` should be variant when introducing subtyping: +it's desirable to be able to pass longer-lived things where shorter-lived things are +needed. To see why `&mut` should be invariant, consider the following code: @@ -391,28 +351,29 @@ fn overwrite(input: &mut T, new: &mut T) { The signature of `overwrite` is clearly valid: it takes mutable references to two values of the same type, and replaces one with the other. We have seen already that `&` is -covariant, and `'static` is a subtype of *any* `'a`, so `&'static str` is a +variant, and `'static` is a subtype of *any* `'a`, so `&'static str` is a subtype of `&'a str`. Therefore, if `&mut` was -*also* covariant, then the lifetime of the `&'static str` would successfully be +*also* variant, then the lifetime of the `&'static str` would successfully be "shrunk" down to the shorter lifetime of the string, and `replace` would be called successfully. The string would subsequently be dropped, and `forever_str` would point to freed memory when we print it! -Therefore `&mut` should be invariant. This is the general theme of covariance vs -invariance: if covariance would allow you to *store* a short-lived value in a +Therefore `&mut` should be invariant. This is the general theme of variance vs +invariance: if variance would allow you to *store* a short-lived value in a longer-lived slot, then you must be invariant. -`Box` and `Vec` are interesting cases because they're covariant, but you can +`Box` and `Vec` are interesting cases because they're variant, but you can definitely store values in them! This is fine because *you can only store values in them through a mutable reference*! The mutable reference makes the whole type invariant, and therefore prevents you from getting in trouble. -Being covariant allows them to be covariant when shared immutably (so you can pass +Being variant allows them to be variant when shared immutably (so you can pass a `&Box<&'static str>` where a `&Box<&'a str>` is expected). It also allows you to forever weaken the type by moving it into a weaker slot. That is, you can do: ```rust fn get_box<'a>(&'a u8) -> Box<&'a str> { + // string literals are `&'static str`s Box::new("hello") } ``` @@ -424,51 +385,67 @@ The variance of the cell types similarly follows. `&` is like an `&mut` for a cell, because you can still store values in them through an `&`. Therefore cells must be invariant to avoid lifetime smuggling. -`Fn` is the most confusing case, largely because contravariance is easily the -most confusing kind of variance, and basically never comes up. To understand it, -consider a function `len` that takes a function `F`. +`Fn` is the most subtle case, because it has mixed variance. To see why +`Fn(T) -> U` should be invariant over T, consider the following function +signature: ```rust -fn len(func: F) -> usize - where F: Fn(&'static str) -> usize -{ - func("hello") -} +// 'a is derived from some parent scope +fn foo(&'a str) -> usize; ``` -We require that F is a Fn that can take an `&'static str` and returns a usize. Now -say we have a function that can take an `&'a str` (for *some* `'a`). Such a function actually -accepts *more* inputs, since `&'static str` is a subtype of `&'a str`. Therefore -`len` should happily accept such a function! +This signature claims that it can handle any &str that lives *at least* as long +as `'a`. Now if this signature was variant with respect to &str, that would mean -So a `Fn(&'a str)` is a subtype of a `Fn(&'static str)` because -`&'static str` is a subtype of `&'a str`. Exactly contravariance. +```rust +fn foo(&'static str) -> usize; +``` -The variance of `*const` and `*mut` is basically arbitrary as they're not at all -type or memory safe, so their variance is determined in analogy to & and &mut -respectively. +could be provided in its place, as it would be a subtype. However this function +has a *stronger* requirement: it says that it can *only* handle `&'static str`s, +and nothing else. Therefore functions are not variant over their arguments. + +To see why `Fn(T) -> U` should be *variant* over U, consider the following +function signature: + +```rust +// 'a is derived from some parent scope +fn foo(usize) -> &'a str; +``` + +This signature claims that it will return something that outlives `'a`. It is +therefore completely reasonable to provide + +```rust +fn foo(usize) -> &'static str; +``` + +in its place. Therefore functions *are* variant over their return type. + +`*const` has the exact same semantics as &, so variance follows. `*mut` on the +other hand can dereference to an &mut whether shared or not, so it is marked +as invariant in analogy to cells. This is all well and good for the types the standard library provides, but -how is variance determined for type that *you* define? A struct informally -speaking inherits the variance of its fields. If a struct `Foo` +how is variance determined for type that *you* define? A struct, informally +speaking, inherits the variance of its fields. If a struct `Foo` has a generic argument `A` that is used in a field `a`, then Foo's variance over `A` is exactly `a`'s variance. However this is complicated if `A` is used in multiple fields. -* If all uses of A are covariant, then Foo is covariant over A -* If all uses of A are contravariant, then Foo is contravariant over A +* If all uses of A are variant, then Foo is variant over A * Otherwise, Foo is invariant over A ```rust struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { - a: &'a A, // covariant over 'a and A + a: &'a A, // variant over 'a and A b: &'b mut B, // invariant over 'b and B - c: *const C, // covariant over C + c: *const C, // variant over C d: *mut D, // invariant over D - e: Vec, // covariant over E + e: Vec, // variant over E f: Cell, // invariant over F - g: G // covariant over G - h1: H // would also be covariant over H except... + g: G // variant over G + h1: H // would also be variant over H except... h2: Cell // invariant over H, because invariance wins } ``` @@ -497,8 +474,9 @@ correct variance and drop checking. We do this using *PhantomData*, which is a special marker type. PhantomData consumes no space, but simulates a field of the given type for the purpose of -variance. This was deemed to be less error-prone than explicitly telling the -type-system the kind of variance that you want. +static analysis. This was deemed to be less error-prone than explicitly telling +the type-system the kind of variance that you want, while also providing other +useful information. Iter logically contains `&'a T`, so this is exactly what we tell the PhantomData to simulate: @@ -526,16 +504,16 @@ However the one exception is with PhantomData. Given a struct like Vec: ``` struct Vec { - data: *const T, // *const for covariance! + data: *const T, // *const for variance! len: usize, cap: usize, } ``` -dropck will generously determine that Vec does not contain any values of +dropck will generously determine that Vec does not own any values of type T. This will unfortunately allow people to construct unsound Drop implementations that access data that has already been dropped. In order to -tell dropck that we *do* own values of type T and may call destructors of that +tell dropck that we *do* own values of type T, and may call destructors of that type, we must add extra PhantomData: ``` @@ -700,3 +678,56 @@ Bar is *also* live. Since IterMut is always live when `next` can be called, if to it exist! + + + +# Weird Lifetimes + +Given the following code: + +```rust +struct Foo; + +impl Foo { + fn mutate_and_share(&mut self) -> &Self { &*self } + fn share(&self) {} +} + +fn main() { + let mut foo = Foo; + let loan = foo.mutate_and_share(); + foo.share(); +} +``` + +One might expect it to compile. We call `mutate_and_share`, which mutably borrows +`foo` *temporarily*, but then returns *only* a shared reference. Therefore we +would expect `foo.share()` to succeed as `foo` shouldn't be mutably borrowed. + +However when we try to compile it: + +```text +:11:5: 11:8 error: cannot borrow `foo` as immutable because it is also borrowed as mutable +:11 foo.share(); + ^~~ +:10:16: 10:19 note: previous borrow of `foo` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foo` until the borrow ends +:10 let loan = foo.mutate_and_share(); + ^~~ +:12:2: 12:2 note: previous borrow ends here +:8 fn main() { +:9 let mut foo = Foo; +:10 let loan = foo.mutate_and_share(); +:11 foo.share(); +:12 } + ^ +``` + +What happened? Well, the lifetime of `loan` is derived from a *mutable* borrow. +This makes the type system believe that `foo` is mutably borrowed as long as +`loan` exists, even though it's a shared reference. This isn't a bug, although +one could argue it is a limitation of the design. In particular, to know if +the mutable part of the borrow is *really* expired we'd have to peek into +implementation details of the function. Currently, type-checking a function +does not need to inspect the bodies of any other functions or types. + + From 65a0c1753e7eaa2ee1a77a4591d328afc85766be Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 29 Jun 2015 11:35:09 -0700 Subject: [PATCH 034/104] poke at data and conversions more --- conversions.md | 176 +++++++++++++++++-------------------------------- data.md | 56 ++++++++++------ 2 files changed, 95 insertions(+), 137 deletions(-) diff --git a/conversions.md b/conversions.md index b35409553f74..ad5d240f2a74 100644 --- a/conversions.md +++ b/conversions.md @@ -32,21 +32,6 @@ more ergonomic alternatives. -# Auto-Deref - -(Maybe nix this in favour of receiver coercions) - -Deref is a trait that allows you to overload the unary `*` to specify a type -you dereference to. This is largely only intended to be implemented by pointer -types like `&`, `Box`, and `Rc`. The dot operator will automatically perform -automatic dereferencing, so that foo.bar() will work uniformly on `Foo`, `&Foo`, ` -&&Foo`, `&Rc>>` and so-on. Search bottoms out on the *first* match, -so implementing methods on pointers is generally to be avoided, as it will shadow -"actual" methods. - - - - # Coercions Types can implicitly be coerced to change in certain contexts. These changes are @@ -58,88 +43,42 @@ Here's all the kinds of coercion: Coercion is allowed between the following types: -* `T` to `U` if `T` is a [subtype](lifetimes.html#subtyping-and-variance) - of `U` (the 'identity' case); +* Subtyping: `T` to `U` if `T` is a [subtype](lifetimes.html#subtyping-and-variance) + of `U` +* Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` +* Pointer Weakening: + * `&mut T` to `&T` + * `*mut T` to `*const T` + * `&T` to `*const T` + * `&mut T` to `*mut T` +* Unsizing: `T` to `U` if `T` implements `CoerceUnsized` -* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` - (transitivity case); +`CoerceUnsized> for Pointer` where T: Unsize is implemented +for all pointer types (including smart pointers like Box and Rc). Unsize is +only implemented automatically, and enables the following transformations: -* `&mut T` to `&T`; +* `[T, ..n]` => `[T]` +* `T` => `Trait` where `T: Trait` +* `SubTrait` => `Trait` where `SubTrait: Trait` (TODO: is this now implied by the previous?) +* `Foo<..., T, ...>` => `Foo<..., U, ...>` where: + * T: Unsize + * `Foo` is a struct + * Only the last field has type `T` + * `T` is not part of the type of any other fields + (note that this also applies to to tuples as an anonymous struct `Tuple3`) -* `*mut T` to `*const T`; - -* `&T` to `*const T`; - -* `&mut T` to `*mut T`; - -* `T` to `U` if `T` implements `CoerceUnsized` (see below) and `T = Foo<...>` - and `U = Foo<...>`; - -* From TyCtor(`T`) to TyCtor(coerce_inner(`T`)); - -where TyCtor(`T`) is one of `&T`, `&mut T`, `*const T`, `*mut T`, or `Box`. -And where coerce_inner is defined as - -* coerce_inner(`[T, ..n]`) = `[T]`; - -* coerce_inner(`T`) = `U` where `T` is a concrete type which implements the - trait `U`; - -* coerce_inner(`T`) = `U` where `T` is a sub-trait of `U`; - -* coerce_inner(`Foo<..., T, ...>`) = `Foo<..., coerce_inner(T), ...>` where - `Foo` is a struct and only the last field has type `T` and `T` is not part of - the type of any other fields; - -* coerce_inner(`(..., T)`) = `(..., coerce_inner(T))`. - -Coercions only occur at a *coercion site*. Exhaustively, the coercion sites -are: - -* In `let` statements where an explicit type is given: in `let _: U = e;`, `e` - is coerced to to have type `U`; - -* In statics and consts, similarly to `let` statements; - -* In argument position for function calls. The value being coerced is the actual - parameter and it is coerced to the type of the formal parameter. For example, - where `foo` is defined as `fn foo(x: U) { ... }` and is called with `foo(e);`, - `e` is coerced to have type `U`; - -* Where a field of a struct or variant is instantiated. E.g., where `struct Foo - { x: U }` and the instantiation is `Foo { x: e }`, `e` is coerced to to have - type `U`; - -* The result of a function, either the final line of a block if it is not semi- - colon terminated or any expression in a `return` statement. For example, for - `fn foo() -> U { e }`, `e` is coerced to to have type `U`; - -If the expression in one of these coercion sites is a coercion-propagating -expression, then the relevant sub-expressions in that expression are also -coercion sites. Propagation recurses from these new coercion sites. Propagating -expressions and their relevant sub-expressions are: - -* array literals, where the array has type `[U, ..n]`, each sub-expression in - the array literal is a coercion site for coercion to type `U`; - -* array literals with repeating syntax, where the array has type `[U, ..n]`, the - repeated sub-expression is a coercion site for coercion to type `U`; - -* tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`, each - sub-expression is a coercion site for the respective type, e.g., the zero-th - sub-expression is a coercion site to `U_0`; - -* the box expression, if the expression has type `Box`, the sub-expression is - a coercion site to `U`; - -* parenthesised sub-expressions (`(e)`), if the expression has type `U`, then - the sub-expression is a coercion site to `U`; - -* blocks, if a block has type `U`, then the last expression in the block (if it - is not semicolon-terminated) is a coercion site to `U`. This includes blocks - which are part of control flow statements, such as `if`/`else`, if the block - has a known type. +Coercions occur at a *coercion site*. Any location that is explicitly typed +will cause a coercion to its type. If inference is necessary, the coercion will +not be performed. Exhaustively, the coercion sites for an expression `e` to +type `U` are: +* let statements, statics, and consts: `let x: U = e` +* Arguments to functions: `takes_a_U(e)` +* Any expression that will be returned: `fn foo() -> U { e }` +* Struct literals: `Foo { some_u: e }` +* Array literals: `let x: [U; 10] = [e, ..]` +* Tuple literals: `let x: (U, ..) = (e, ..)` +* The last expression in a block: `let x: U = { ..; e }` Note that we do not perform coercions when matching traits (except for receivers, see below). If there is an impl for some type `U` and `T` coerces to @@ -147,29 +86,32 @@ receivers, see below). If there is an impl for some type `U` and `T` coerces to following will not type check, even though it is OK to coerce `t` to `&T` and there is an impl for `&T`: -``` -struct T; +```rust trait Trait {} fn foo(t: X) {} -impl<'a> Trait for &'a T {} +impl<'a> Trait for &'a i32 {} fn main() { - let t: &mut T = &mut T; - foo(t); //~ ERROR failed to find an implementation of trait Trait for &mut T + let t: &mut i32 = &mut 0; + foo(t); } ``` -In a cast expression, `e as U`, the compiler will first attempt to coerce `e` to -`U`, only if that fails will the conversion rules for casts (see below) be -applied. +```text +:10:5: 10:8 error: the trait `Trait` is not implemented for the type `&mut i32` [E0277] +:10 foo(t); + ^~~ +``` +# The Dot Operator +The dot operator will perform a lot of magic to convert types. It will perform +auto-referencing, auto-dereferencing, and coercion until types match. -TODO: receiver coercions? - +TODO: steal information from http://stackoverflow.com/questions/28519997/what-are-rusts-exact-auto-dereferencing-rules/28552082#28552082 # Casts @@ -178,21 +120,21 @@ cast, but some conversions *require* a cast. These "true casts" are generally re as dangerous or problematic actions. True casts revolve around raw pointers and the primitive numeric types. True casts aren't checked. -Here's an exhaustive list of all the true casts: +Here's an exhaustive list of all the true casts. For brevity, we will use `*` +to denote either a `*const` or `*mut`, and `integer` to denote any integral primitive: - * `e` has type `T` and `T` coerces to `U`; *coercion-cast* - * `e` has type `*T`, `U` is `*U_0`, and either `U_0: Sized` or - unsize_kind(`T`) = unsize_kind(`U_0`); *ptr-ptr-cast* - * `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast* - * `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast* - * `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast* - * `e` is a C-like enum and `U` is an integer type; *enum-cast* - * `e` has type `bool` or `char` and `U` is an integer; *prim-int-cast* - * `e` has type `u8` and `U` is `char`; *u8-char-cast* - * `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast* - * `e` is a function pointer type and `U` has type `*T`, - while `T: Sized`; *fptr-ptr-cast* - * `e` is a function pointer type and `U` is an integer; *fptr-addr-cast* + * `*T as *U` where `T, U: Sized` + * `*T as *U` TODO: explain unsized situation + * `*T as integer` + * `integer as *T` + * `number as number` + * `C-like-enum as integer` + * `bool as integer` + * `char as integer` + * `u8 as char` + * `&[T; n] as *const T` + * `fn as *T` where `T: Sized` + * `fn as integer` where `&.T` and `*T` are references of either mutability, and where unsize_kind(`T`) is the kind of the unsize info diff --git a/data.md b/data.md index f9163caa4e00..d5259c1348a0 100644 --- a/data.md +++ b/data.md @@ -7,7 +7,7 @@ represented in Rust. -# The rust repr +# The Rust repr Rust gives you the following ways to lay out composite data: @@ -16,12 +16,14 @@ Rust gives you the following ways to lay out composite data: * arrays (homogeneous product types) * enums (named sum types -- tagged unions) -For all these, individual fields are aligned to their preferred alignment. -For primitives this is equal to -their size. For instance, a u32 will be aligned to a multiple of 32 bits, and a u16 will -be aligned to a multiple of 16 bits. Composite structures will have their size rounded -up to be a multiple of the highest alignment required by their fields, and an alignment -requirement equal to the highest alignment required by their fields. So for instance, +An enum is said to be *C-like* if none of its variants have associated data. + +For all these, individual fields are aligned to their preferred alignment. For +primitives this is usually equal to their size. For instance, a u32 will be +aligned to a multiple of 32 bits, and a u16 will be aligned to a multiple of 16 +bits. Composite structures will have their size rounded up to be a multiple of +the highest alignment required by their fields, and an alignment requirement +equal to the highest alignment required by their fields. So for instance, ```rust struct A { @@ -127,6 +129,9 @@ In principle enums can use fairly elaborate algorithms to cache bits throughout with special constrained representations. As such it is *especially* desirable that we leave enum layout unspecified today. + + + # Dynamically Sized Types (DSTs) Rust also supports types without a statically known size. On the surface, @@ -219,15 +224,14 @@ struct Foo { ``` For details as to *why* this is done, and how to make it not happen, check out -[SOME OTHER SECTION]. +[TODO: SOME OTHER SECTION]. # Alternative representations -Rust allows you to specify alternative data layout strategies from the default Rust -one. +Rust allows you to specify alternative data layout strategies from the default. @@ -241,32 +245,44 @@ to soundly do more elaborate tricks with data layout such as reintepretting valu as a different type. However, the interaction with Rust's more exotic data layout features must be kept -in mind. Due to its dual purpose as a "for FFI" and "for layout control", repr(C) +in mind. Due to its dual purpose as "for FFI" and "for layout control", `repr(C)` can be applied to types that will be nonsensical or problematic if passed through the FFI boundary. * ZSTs are still zero-sized, even though this is not a standard behaviour -in C, and is explicitly contrary to the behaviour of an empty type in C++, which -still consumes a byte of space. + in C, and is explicitly contrary to the behaviour of an empty type in C++, which + still consumes a byte of space. -* DSTs are not a concept in C +* DSTs, tuples, and tagged unions are not a concept in C and as such are never + FFI safe. * **The drop flag will still be added** -* This is equivalent to repr(u32) for enums (see below) +* This is equivalent to `repr(u32)` for enums (see below) ## repr(packed) -`repr(packed)` forces rust to strip any padding it would normally apply. -This may improve the memory footprint of a type, but will have negative -side-effects from "field access is heavily penalized" to "completely breaks -everything" based on target platform. +`repr(packed)` forces rust to strip any padding, and only align the type to a +byte. This may improve the memory footprint, but will likely have other +negative side-effects. +In particular, most architectures *strongly* prefer values to be aligned. This +may mean the unaligned loads are penalized (x86), or even fault (ARM). In +particular, the compiler may have trouble with references to unaligned fields. + +`repr(packed)` is not to be used lightly. Unless you have extreme requirements, +this should not be used. + +This repr is a modifier on `repr(C)` and `repr(rust)`. ## repr(u8), repr(u16), repr(u32), repr(u64) -These specify the size to make a c-like enum (one which has no values in its variants). +These specify the size to make a C-like enum. If the discriminant overflows the +integer it has to fit in, it will be an error. You can manually ask Rust to +allow this by setting the overflowing element to explicitly be 0. However Rust +will not allow you to create an enum where two variants. +These reprs have no affect on struct or non-C-like enum. From 9c6a46b0eee9f991a7ae6e72164550f781654c66 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 29 Jun 2015 15:43:51 -0700 Subject: [PATCH 035/104] fiddlin' --- README.md | 7 ++++++- data.md | 51 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 04cfe58b3b0a..b86f6209f35a 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ % The Unsafe Rust Programming Language +# NOTE: This is a draft document, and may contain serious errors + **This document is about advanced functionality and low-level development practices in the Rust Programming Language. Most of the things discussed won't matter to the average Rust programmer. However if you wish to correctly write unsafe code in Rust, this text contains invaluable information.** -This document seeks to complement [The Rust Programming Language Book][trpl] (TRPL). +The Unsafe Rust Programming Language (TURPL) seeks to complement +[The Rust Programming Language Book][trpl] (TRPL). Where TRPL introduces the language and teaches the basics, TURPL dives deep into the specification of the language, and all the nasty bits necessary to write Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know @@ -13,6 +16,8 @@ the basics of the language and systems programming. We will not explain the stack or heap, we will not explain the syntax. + + # A Tale Of Two Languages Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust. diff --git a/data.md b/data.md index d5259c1348a0..599415bfe4b9 100644 --- a/data.md +++ b/data.md @@ -21,23 +21,25 @@ An enum is said to be *C-like* if none of its variants have associated data. For all these, individual fields are aligned to their preferred alignment. For primitives this is usually equal to their size. For instance, a u32 will be aligned to a multiple of 32 bits, and a u16 will be aligned to a multiple of 16 -bits. Composite structures will have their size rounded up to be a multiple of -the highest alignment required by their fields, and an alignment requirement -equal to the highest alignment required by their fields. So for instance, +bits. Composite structures will have a preferred alignment equal to the maximum +of their fields' preferred alignment, and a size equal to a multiple of their +preferred alignment. This ensures that arrays of T can be correctly iterated +by offsetting by their size. So for instance, ```rust struct A { a: u8, - c: u64, - b: u32, + c: u32, + b: u16, } ``` -will have a size that is a multiple of 64-bits, and 64-bit alignment. +will have a size that is a multiple of 32-bits, and 32-bit alignment. There is *no indirection* for these types; all data is stored contiguously as you would -expect in C. However with the exception of arrays, the layout of data is not by -default specified in Rust. Given the two following struct definitions: +expect in C. However with the exception of arrays (which are densely packed and +in-order), the layout of data is not by default specified in Rust. Given the two +following struct definitions: ```rust struct A { @@ -91,9 +93,9 @@ struct Foo { ``` The latter case quite simply wastes space. An optimal use of space therefore requires -different monomorphizations to *have different field orderings*. +different monomorphizations to have *different field orderings*. -**Note: this is a hypothetical optimization that is not yet implemented in Rust 1.0.0** +**Note: this is a hypothetical optimization that is not yet implemented in Rust 1.0** Enums make this consideration even more complicated. Naively, an enum such as: @@ -120,14 +122,15 @@ such a representation is ineffiecient. The classic case of this is Rust's "null pointer optimization". Given a pointer that is known to not be null (e.g. `&u32`), an enum can *store* a discriminant bit *inside* the pointer by using null as a special value. The net result is that -`sizeof(Option<&T>) == sizeof<&T>` +`size_of::>() == size_of::<&T>()` -There are many types in Rust that are, or contain, "not null" pointers such as `Box`, `Vec`, -`String`, `&T`, and `&mut T`. Similarly, one can imagine nested enums pooling their tags into -a single descriminant, as they are by definition known to have a limited range of valid values. -In principle enums can use fairly elaborate algorithms to cache bits throughout nested types -with special constrained representations. As such it is *especially* desirable that we leave -enum layout unspecified today. +There are many types in Rust that are, or contain, "not null" pointers such as +`Box`, `Vec`, `String`, `&T`, and `&mut T`. Similarly, one can imagine +nested enums pooling their tags into a single descriminant, as they are by +definition known to have a limited range of valid values. In principle enums can +use fairly elaborate algorithms to cache bits throughout nested types with +special constrained representations. As such it is *especially* desirable that +we leave enum layout unspecified today. @@ -135,8 +138,8 @@ enum layout unspecified today. # Dynamically Sized Types (DSTs) Rust also supports types without a statically known size. On the surface, -this is a bit nonsensical: Rust must know the size of something in order to -work with it. DSTs are generally produced as views, or through type-erasure +this is a bit nonsensical: Rust *must* know the size of something in order to +work with it! DSTs are generally produced as views, or through type-erasure of types that *do* have a known size. Due to their lack of a statically known size, these types can only exist *behind* some kind of pointer. They consequently produce a *fat* pointer consisting of the pointer and the information that @@ -144,7 +147,7 @@ produce a *fat* pointer consisting of the pointer and the information that For instance, the slice type, `[T]`, is some statically unknown number of elements stored contiguously. `&[T]` consequently consists of a `(&T, usize)` pair that specifies -where the slice starts, and how many elements it contains. Similarly Trait Objects +where the slice starts, and how many elements it contains. Similarly, Trait Objects support interface-oriented type erasure through a `(data_ptr, vtable_ptr)` pair. Structs can actually store a single DST directly as their last field, but this @@ -158,6 +161,8 @@ struct Foo { } ``` +**NOTE: As of Rust 1.0 struct DSTs are broken if the last field has +a variable position based on its alignment.** @@ -235,6 +240,7 @@ Rust allows you to specify alternative data layout strategies from the default. + ## repr(C) This is the most important `repr`. It has fairly simple intent: do what C does. @@ -262,6 +268,7 @@ the FFI boundary. + ## repr(packed) `repr(packed)` forces rust to strip any padding, and only align the type to a @@ -278,6 +285,8 @@ this should not be used. This repr is a modifier on `repr(C)` and `repr(rust)`. + + ## repr(u8), repr(u16), repr(u32), repr(u64) These specify the size to make a C-like enum. If the discriminant overflows the @@ -285,4 +294,4 @@ integer it has to fit in, it will be an error. You can manually ask Rust to allow this by setting the overflowing element to explicitly be 0. However Rust will not allow you to create an enum where two variants. -These reprs have no affect on struct or non-C-like enum. +These reprs have no affect on a struct or non-C-like enum. From 10af239aad8024f1eed093947b8516ecf873d735 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 29 Jun 2015 17:13:15 -0700 Subject: [PATCH 036/104] unwinding start --- raii.md | 34 +++++++++------------- unwinding.md | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 20 deletions(-) create mode 100644 unwinding.md diff --git a/raii.md b/raii.md index 679c1dd3d599..f85562bd809b 100644 --- a/raii.md +++ b/raii.md @@ -1,6 +1,6 @@ % The Perils Of RAII -Ownership Based Resource Management (AKA RAII: Resource Acquisition is Initialization) is +Ownership Based Resource Management (AKA RAII: Resource Acquisition Is Initialization) is something you'll interact with a lot in Rust. Especially if you use the standard library. Roughly speaking the pattern is as follows: to acquire a resource, you create an object that @@ -38,10 +38,8 @@ treating the old copy as uninitialized -- a no-op. While Rust provides a `Default` trait for specifying the moral equivalent of a default constructor, it's incredibly rare for this trait to be used. This is because variables -aren't implicitly initialized (see [working with uninitialized memory][uninit] for details). -Default is basically only useful for generic programming. - -In concrete contexts, a type will provide a static `new` method for any +[aren't implicitly initialized][uninit]. Default is basically only useful for generic +programming. In concrete contexts, a type will provide a static `new` method for any kind of "default" constructor. This has no relation to `new` in other languages and has no special meaning. It's just a naming convention. @@ -59,20 +57,16 @@ fn drop(&mut self); ``` This method gives the type time to somehow finish what it was doing. **After `drop` is run, -Rust will recursively try to drop all of the fields of the `self` struct**. This is a +Rust will recursively try to drop all of the fields of `self`**. This is a convenience feature so that you don't have to write "destructor boilerplate" to drop children. If a struct has no special logic for being dropped other than dropping its children, then it means `Drop` doesn't need to be implemented at all! -**There is no way to prevent this behaviour in Rust 1.0**. +**There is no stable way to prevent this behaviour in Rust 1.0**. Note that taking `&mut self` means that even if you *could* suppress recursive Drop, Rust will prevent you from e.g. moving fields out of self. For most types, this -is totally fine: - -* They own all their data (they don't contain pointers to elsewhere). -* There's no additional state passed into drop to try to send things. -* `self` is about to be marked as uninitialized (and therefore inaccessible). +is totally fine. For instance, a custom implementation of `Box` might write `Drop` like this: @@ -120,7 +114,7 @@ impl Drop for SuperBox { } ``` -because after we deallocate the `box`'s ptr in SuperBox's destructor, Rust will +After we deallocate the `box`'s ptr in SuperBox's destructor, Rust will happily proceed to tell the box to Drop itself and everything will blow up with use-after-frees and double-frees. @@ -216,7 +210,7 @@ refers to it. The collection will sit around uselessly, holding on to its precious resources until the program terminates (at which point all those resources would have been reclaimed by the OS anyway). -We may consider a more restricted form of leak: failing to free memory that +We may consider a more restricted form of leak: failing to drop a value that is unreachable. Rust also doesn't prevent this. In fact Rust has a *function for doing this*: `mem::forget`. This function consumes the value it is passed *and then doesn't run its destructor*. @@ -232,18 +226,18 @@ It is reasonable for safe code to assume that destructor leaks do not happen, as any program that leaks destructors is probably wrong. However *unsafe* code cannot rely on destructors to be run to be *safe*. For most types this doesn't matter: if you leak the destructor then the type is *by definition* inaccessible, -so it doesn't matter, right? e.g. if you leak a `Box` then you waste some -memory but that's hardly going to violate memory-safety. +so it doesn't matter, right? For instance, if you leak a `Box` then you +waste some memory but that's hardly going to violate memory-safety. However where we must be careful with destructor leaks are *proxy* types. These are types which manage access to a distinct object, but don't actually own it. Proxy objects are quite rare. Proxy objects you'll need to care about -are even rarer. However we'll focus on two interesting examples in the +are even rarer. However we'll focus on three interesting examples in the standard library: * `vec::Drain` * `Rc` - +* `thread::scoped::JoinGuard` @@ -251,7 +245,7 @@ standard library: `drain` is a collections API that moves data out of the container without consuming the container. This enables us to reuse the allocation of a `Vec` -after claiming ownership over all of its contents. drain produces an iterator +after claiming ownership over all of its contents. It produces an iterator (Drain) that returns the contents of the Vec by-value. Now, consider Drain in the middle of iteration: some values have been moved out, @@ -376,7 +370,7 @@ in memory. -## thread::scoped +## thread::scoped::JoinGuard The thread::scoped API intends to allow threads to be spawned that reference data on the stack without any synchronization over that data. Usage looked like: diff --git a/unwinding.md b/unwinding.md new file mode 100644 index 000000000000..cd9ca58304d3 --- /dev/null +++ b/unwinding.md @@ -0,0 +1,82 @@ +% Unwinding + +Rust has a *tiered* error-handling scheme: + +* If something might reasonably be absent, Option is used +* If something goes wrong and can reasonably be handled, Result is used +* If something goes wrong and cannot reasonably be handled, the thread panics +* If something catastrophic happens, the program aborts + +Option and Result are overwhelmingly preferred in most situations, especially +since they can be promoted into a panic or abort at the API user's discretion. +However, anything and everything *can* panic, and you need to be ready for this. +Panics cause the thread to halt normal execution and unwind its stack, calling +destructors as if every function instantly returned. + +As of 1.0, Rust is of two minds when it comes to panics. In the long-long-ago, +Rust was much more like Erlang. Like Erlang, Rust had lightweight tasks, +and tasks were intended to kill themselves with a panic when they reached an +untenable state. Unlike an exception in Java or C++, a panic could not be +caught at any time. Panics could only be caught by the owner of the task, at which +point they had to be handled or *that* task would itself panic. + +Unwinding was important to this story because if a task's +destructors weren't called, it would cause memory and other system resources to +leak. Since tasks were expected to die during normal execution, this would make +Rust very poor for long-running systems! + +As the Rust we know today came to be, this style of programming grew out of +fashion in the push for less-and-less abstraction. Light-weight tasks were +killed in the name of heavy-weight OS threads. Still, panics could only be +caught by the parent thread. This meant catching a panic required spinning up +an entire OS thread! Although Rust maintains the philosophy that panics should +not be used for "basic" error-handling like C++ or Java, it is still desirable +to not have the entire program crash in the face of a panic. + +In the near future there will be a stable interface for catching panics in an +arbitrary location, though we would encourage you to still only do this +sparingly. In particular, Rust's current unwinding implementation is heavily +optimized for the "doesn't unwind" case. If a program doesn't unwind, there +should be no runtime cost for the program being *ready* to unwind. As a +consequence, *actually* unwinding will be more expensive than in e.g. Java. +Don't build your programs to unwind under normal circumstances. Ideally, you +should only panic for programming errors. + + + + +# Exception Safety + +Being ready for unwinding is often referred to as "exception safety" +in the broader programming world. In Rust, their are two levels of exception +safety that one may concern themselves with: + +* In unsafe code, we *must* be exception safe to the point of not violating + memory safety. + +* In safe code, it is *good* to be exception safe to the point of your program + doing the right thing. + +As is the case in many places in Rust, unsafe code must be ready to deal with +bad safe code, and that includes code that panics. Code that transiently creates +unsound states must be careful that a panic does not cause that state to be +used. Generally this means ensuring that only non-panicing code is run while +these states exist, or making a guard that cleans up the state in the case of +a panic. This does not necessarily mean that the state a panic witnesses is a +fully *coherent* state. We need only guarantee that it's a *safe* state. + +For instance, consider extending a Vec: + +```rust + +impl Extend for Vec { + fn extend>(&mut self, iterable: I) { + let mut iter = iterable.into_iter(); + let size_hint = iter.size_hint().0; + self.reserve(size_hint); + self.set_len(self.len() + size_hint()); + + for + } +} + From 5d4f854b4acf01c9e0355eccb779d90c75313ad1 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 29 Jun 2015 21:42:27 -0700 Subject: [PATCH 037/104] so much unwinding --- unwinding.md | 248 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 230 insertions(+), 18 deletions(-) diff --git a/unwinding.md b/unwinding.md index cd9ca58304d3..925f30423662 100644 --- a/unwinding.md +++ b/unwinding.md @@ -28,10 +28,9 @@ Rust very poor for long-running systems! As the Rust we know today came to be, this style of programming grew out of fashion in the push for less-and-less abstraction. Light-weight tasks were killed in the name of heavy-weight OS threads. Still, panics could only be -caught by the parent thread. This meant catching a panic required spinning up -an entire OS thread! Although Rust maintains the philosophy that panics should -not be used for "basic" error-handling like C++ or Java, it is still desirable -to not have the entire program crash in the face of a panic. +caught by the parent thread. This means catching a panic requires spinning up +an entire OS thread! This unfortunately stands in conflict to Rust's philosophy +of zero-cost abstractions. In the near future there will be a stable interface for catching panics in an arbitrary location, though we would encourage you to still only do this @@ -40,14 +39,14 @@ optimized for the "doesn't unwind" case. If a program doesn't unwind, there should be no runtime cost for the program being *ready* to unwind. As a consequence, *actually* unwinding will be more expensive than in e.g. Java. Don't build your programs to unwind under normal circumstances. Ideally, you -should only panic for programming errors. +should only panic for programming errors or *extreme* problems. # Exception Safety -Being ready for unwinding is often referred to as "exception safety" +Being ready for unwinding is often referred to as *exception safety* in the broader programming world. In Rust, their are two levels of exception safety that one may concern themselves with: @@ -60,23 +59,236 @@ safety that one may concern themselves with: As is the case in many places in Rust, unsafe code must be ready to deal with bad safe code, and that includes code that panics. Code that transiently creates unsound states must be careful that a panic does not cause that state to be -used. Generally this means ensuring that only non-panicing code is run while +used. Generally this means ensuring that only non-panicking code is run while these states exist, or making a guard that cleans up the state in the case of a panic. This does not necessarily mean that the state a panic witnesses is a fully *coherent* state. We need only guarantee that it's a *safe* state. -For instance, consider extending a Vec: +Most unsafe code is leaf-like, and therefore fairly easy to make exception-safe. +It controls all the code that runs, and most of that code can't panic. However +it is often the case that code that works with arrays works with temporarily +uninitialized data while repeatedly invoking caller-provided code. Such code +needs to be careful, and consider exception-safety. + + + + + +## Vec::push_all + +`Vec::push_all` is a temporary hack to get extending a Vec by a slice reliably +effecient without specialization. Here's a simple implementation: + +```rust,ignore +impl Vec { + fn push_all(&mut self, to_push: &[T]) { + self.reserve(to_push.len()); + unsafe { + // can't overflow because we just reserved this + self.set_len(self.len() + to_push.len()); + + for (i, x) in to_push.iter().enumerate() { + self.ptr().offset(i as isize).write(x.clone()); + } + } + } +} +``` + +We bypass `push` in order to avoid redundant capacity and `len` checks on the +Vec that we definitely know has capacity. The logic is totally correct, except +there's a subtle problem with our code: it's not exception-safe! `set_len`, +`offset`, and `write` are all fine, but *clone* is the panic bomb we over-looked. + +Clone is completely out of our control, and is totally free to panic. If it does, +our function will exit early with the length of the Vec set too large. If +the Vec is looked at or dropped, uninitialized memory will be read! + +The fix in this case is fairly simple. If we want to guarantee that the values +we *did* clone are dropped we can set the len *in* the loop. If we just want to +guarantee that uninitialized memory can't be observed, we can set the len *after* +the loop. + + + + + +## BinaryHeap::sift_up + +Bubbling an element up a heap is a bit more complicated than extending a Vec. +The pseudocode is as follows: + +```text +bubble_up(heap, index): + while index != 0 && heap[index] < heap[parent(index)]: + heap.swap(index, parent(index)) + index = parent(index) + +``` + +A literal transcription of this code to Rust is totally fine, but has an annoying +performance characteristic: the `self` element is swapped over and over again +uselessly. We would *rather* have the following: + +```text +bubble_up(heap, index): + let elem = heap[index] + while index != 0 && element < heap[parent(index)]: + heap[index] = heap[parent(index)] + index = parent(index) + heap[index] = elem +``` + +This code ensures that each element is copied as little as possible (it is in +fact necessary that elem be copied twice in general). However it now exposes +some exception-safety trouble! At all times, there exists two copies of one +value. If we panic in this function something will be double-dropped. +Unfortunately, we also don't have full control of the code: that comparison is +user-defined! + +Unlike Vec, the fix isn't as easy here. One option is to break the user-defined +code and the unsafe code into two separate phases: + +```text +bubble_up(heap, index): + let end_index = index; + while end_index != 0 && heap[end_index] < heap[parent(end_index)]: + end_index = parent(end_index) + + let elem = heap[index] + while index != end_index: + heap[index] = heap[parent(index)] + index = parent(index) + heap[index] = elem +``` + +If the user-defined code blows up, that's no problem anymore, because we haven't +actually touched the state of the heap yet. Once we do start messing with the +heap, we're working with only data and functions that we trust, so there's no +concern of panics. + +Perhaps you're not happy with this design. Surely, it's cheating! And we have +to do the complex heap traversal *twice*! Alright, let's bite the bullet. Let's +intermix untrusted and unsafe code *for reals*. + +If Rust had `try` and `finally` like in Java, we could do the following: + +```text +bubble_up(heap, index): + let elem = heap[index] + try: + while index != 0 && element < heap[parent(index)]: + heap[index] = heap[parent(index)] + index = parent(index) + finally: + heap[index] = elem +``` + +The basic idea is simple: if the comparison panics, we just toss the loose +element in the logically uninitialized index and bail out. Anyone who observes +the heap will see a potentially *inconsistent* heap, but at least it won't +cause any double-drops! If the algorithm terminates normally, then this +operation happens to coincide precisely with the how we finish up regardless. + +Sadly, Rust has no such construct, so we're going to need to roll our own! The +way to do this is to store the algorithm's state in a separate struct with a +destructor for the "finally" logic. Whether we panic or not, that destructor +will run and clean up after us. ```rust - -impl Extend for Vec { - fn extend>(&mut self, iterable: I) { - let mut iter = iterable.into_iter(); - let size_hint = iter.size_hint().0; - self.reserve(size_hint); - self.set_len(self.len() + size_hint()); - - for - } +struct Hole<'a, T: 'a> { + data: &'a mut [T], + /// `elt` is always `Some` from new until drop. + elt: Option, + pos: usize, } +impl<'a, T> Hole<'a, T> { + fn new(data: &'a mut [T], pos: usize) -> Self { + unsafe { + let elt = ptr::read(&data[pos]); + Hole { + data: data, + elt: Some(elt), + pos: pos, + } + } + } + + fn pos(&self) -> usize { self.pos } + + fn removed(&self) -> &T { self.elt.as_ref().unwrap() } + + unsafe fn get(&self, index: usize) -> &T { &self.data[index] } + + unsafe fn move_to(&mut self, index: usize) { + let index_ptr: *const _ = &self.data[index]; + let hole_ptr = &mut self.data[self.pos]; + ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1); + self.pos = index; + } +} + +impl<'a, T> Drop for Hole<'a, T> { + fn drop(&mut self) { + // fill the hole again + unsafe { + let pos = self.pos; + ptr::write(&mut self.data[pos], self.elt.take().unwrap()); + } + } +} + +impl BinaryHeap { + fn sift_up(&mut self, pos: usize) { + unsafe { + // Take out the value at `pos` and create a hole. + let mut hole = Hole::new(&mut self.data, pos); + + while hole.pos() != 0 { + let parent = parent(hole.pos()); + if hole.removed() <= hole.get(parent) { break } + hole.move_to(parent); + } + // Hole will be unconditionally filled here; panic or not! + } + } +} +``` + + + + +## Poisoning + +Although all unsafe code *must* ensure some minimal level of exception safety, +some types may choose to explicitly *poison* themselves if they witness a panic. +The most notable example of this is the standard library's Mutex type. A Mutex +will poison itself if one of its MutexGuards (the thing it returns when a lock +is obtained) is dropped during a panic. Any future attempts to lock the Mutex +will return an `Err`. + +Mutex poisons not for *true* safety in the sense that Rust normally cares about. It +poisons as a safety-guard against blindly using the data that comes out of a Mutex +that has witnessed a panic while locked. The data in such a Mutex was likely in the +middle of being modified, and as such may be in an inconsistent or incomplete state. +It is important to note that one cannot violate memory safety with such a type +if it is correctly written. After all, it must be exception safe! + +However if the Mutex contained, say, a BinaryHeap that does not actually have the +heap property, it's unlikely that any code that uses it will do +what the author intended. As such, the program should not proceed normally. +Still, if you're double-plus-sure that you can do *something* with the value, +the Err exposes a method to get the lock anyway. It *is* safe, after all. + + + +# FFI + +Rust's unwinding strategy is not specified to be fundamentally compatible +with any other language's unwinding. As such, unwinding into Rust from another +language, or unwinding into another language from Rust is Undefined Behaviour. +What you do at that point is up to you, but you must *absolutely* catch any +panics at the FFI boundary! At best, your application will crash and burn. At +worst, your application *won't* crash and burn, and will proceed with completely +clobbered state. From b26958caf745a05b4fa45b655ffeab18445cdb9b Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 29 Jun 2015 21:44:07 -0700 Subject: [PATCH 038/104] add unwinding section to index --- SUMMARY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SUMMARY.md b/SUMMARY.md index d136ebcebd4e..91a07b79e389 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -5,5 +5,6 @@ * [Conversions](conversions.md) * [Uninitialized Memory](uninitialized.md) * [Ownership-oriented resource management (RAII)](raii.md) +* [Unwinding](unwinding.md) * [Concurrency](concurrency.md) * [Example: Implementing Vec](vec.md) \ No newline at end of file From 108a697b1c225dafef16a77076e30149b1d0ebe7 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 29 Jun 2015 22:30:10 -0700 Subject: [PATCH 039/104] conversion corrections --- conversions.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/conversions.md b/conversions.md index ad5d240f2a74..55b7b20e50d1 100644 --- a/conversions.md +++ b/conversions.md @@ -53,7 +53,7 @@ Coercion is allowed between the following types: * `&mut T` to `*mut T` * Unsizing: `T` to `U` if `T` implements `CoerceUnsized` -`CoerceUnsized> for Pointer` where T: Unsize is implemented +`CoerceUnsized> for Pointer where T: Unsize` is implemented for all pointer types (including smart pointers like Box and Rc). Unsize is only implemented automatically, and enables the following transformations: @@ -65,7 +65,6 @@ only implemented automatically, and enables the following transformations: * `Foo` is a struct * Only the last field has type `T` * `T` is not part of the type of any other fields - (note that this also applies to to tuples as an anonymous struct `Tuple3`) Coercions occur at a *coercion site*. Any location that is explicitly typed will cause a coercion to its type. If inference is necessary, the coercion will @@ -106,6 +105,9 @@ fn main() { ^~~ ``` + + + # The Dot Operator The dot operator will perform a lot of magic to convert types. It will perform @@ -113,6 +115,9 @@ auto-referencing, auto-dereferencing, and coercion until types match. TODO: steal information from http://stackoverflow.com/questions/28519997/what-are-rusts-exact-auto-dereferencing-rules/28552082#28552082 + + + # Casts Casts are a superset of coercions: every coercion can be explicitly invoked via a @@ -171,6 +176,8 @@ For numeric casts, there are quite a few cases to consider: + + # Conversion Traits TODO? From 18067e41090938ff5d642bbef05604c939e542dc Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 1 Jul 2015 13:11:13 -0700 Subject: [PATCH 040/104] start on proper atomics --- concurrency.md | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/concurrency.md b/concurrency.md index fc04bd83811a..71cfec3393e5 100644 --- a/concurrency.md +++ b/concurrency.md @@ -154,15 +154,44 @@ only to data races? # Atomics -Rust pretty blatantly just inherits LLVM's model for atomics, which in turn is -largely based off of the C11 model for atomics. This is not due these models -being particularly excellent or easy to understand. Indeed, these models are -quite complex and are known to have several flaws. Rather, it is a pragmatic -concession to the fact that *everyone* is pretty bad at modeling atomics. At very -least, we can benefit from existing tooling and research around C's model. +Rust pretty blatantly just inherits C11's memory model for atomics. This is not +due this model being particularly excellent or easy to understand. Indeed, this +model is quite complex and known to have [several flaws][C11-busted]. Rather, +it is a pragmatic concession to the fact that *everyone* is pretty bad at modeling +atomics. At very least, we can benefit from existing tooling and research around +C. -Trying to fully explain these models is fairly hopeless, so we're just going to -drop that problem in LLVM's lap. +Trying to fully explain the model is fairly hopeless. If you want all the +nitty-gritty details, you should check out [C's specification][C11-model]. +Still, we'll try to cover the basics and some of the problems Rust developers +face. + +The C11 memory model is fundamentally about trying to bridge the gap between C's +single-threaded semantics, common compiler optimizations, and hardware peculiarities +in the face of a multi-threaded environment. It does this by splitting memory +accesses into two worlds: data accesses, and atomic accesses. + +Data accesses are the bread-and-butter of the programming world. They are +fundamentally unsynchronized and compilers are free to aggressively optimize +them. In particular data accesses are free to be reordered by the compiler +on the assumption that the program is single-threaded. The hardware is also free +to propagate the changes made in data accesses as lazily and inconsistently as +it wants to other threads. Mostly critically, data accesses are where we get data +races. These are pretty clearly awful semantics to try to write a multi-threaded +program with. + +Atomic accesses are the answer to this. Each atomic access can be marked with +an *ordering*. The set of orderings Rust exposes are: + +* Sequentially Consistent (SeqCst) +* Release +* Acquire +* Relaxed + +(Note: We explicitly do not expose the C11 *consume* ordering) + +TODO: give simple "basic" explanation of these +TODO: implementing Arc example (why does Drop need the trailing barrier?) @@ -184,5 +213,5 @@ with everyone else's stuff. -[llvm-conc]: http://llvm.org/docs/Atomics.html -[trpl-conc]: https://doc.rust-lang.org/book/concurrency.html +[C11-busted]: http://plv.mpi-sws.org/c11comp/popl15.pdf +[C11-model]: http://en.cppreference.com/w/c/atomic/memory_order From ccb08a52fee9756f39696253e1cd1d1b3b55fc85 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 1 Jul 2015 13:12:11 -0700 Subject: [PATCH 041/104] TODO --- lifetimes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lifetimes.md b/lifetimes.md index 48bfcb029913..cd6f5ad28842 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -9,6 +9,8 @@ language-design problem. # The Tagged Union Problem +TODO: rewrite this to use Box instead? + The core of the lifetime and mutability system derives from a simple problem: internal pointers to tagged unions. For instance, consider the following code: From e4f718ad1c91e4da0438cf925a2baad39fa70181 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 1 Jul 2015 13:37:17 -0700 Subject: [PATCH 042/104] uninit cleanup --- uninitialized.md | 55 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/uninitialized.md b/uninitialized.md index 88cc7deac472..983c320c7382 100644 --- a/uninitialized.md +++ b/uninitialized.md @@ -6,7 +6,7 @@ of bits that may or may not even reflect a valid state for the type that is supposed to inhabit that location of memory. Attempting to interpret this memory as a value of *any* type will cause Undefined Behaviour. Do Not Do This. -Like C, all stack variables in Rust begin their life as uninitialized until a +Like C, all stack variables in Rust are uninitialized until a value is explicitly assigned to them. Unlike C, Rust statically prevents you from ever reading them until you do: @@ -32,9 +32,6 @@ or anything like that. So this compiles: ```rust fn main() { let x: i32; - let y: i32; - - y = 1; if true { x = 1; @@ -42,7 +39,7 @@ fn main() { x = 2; } - println!("{} {}", x, y); + println!("{}", x); } ``` @@ -98,13 +95,13 @@ to call the destructor of a variable that is conditionally initialized? It turns out that Rust actually tracks whether a type should be dropped or not *at runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for that variable is set and unset. When a variable goes out of scope or is assigned -it evaluates whether the current value of the variable should be dropped. Of -course, static analysis can remove these checks. If the compiler can prove that +a value, it evaluates whether the current value of the variable should be dropped. +Of course, static analysis can remove these checks. If the compiler can prove that a value is guaranteed to be either initialized or not, then it can theoretically generate more efficient code! As such it may be desirable to structure code to have *static drop semantics* when possible. -As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a secret +As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden field of any type that implements Drop. The language sets the drop flag by overwriting the entire struct with a particular value. This is pretty obviously Not The Fastest and causes a bunch of trouble with optimizing code. As such work @@ -115,7 +112,7 @@ requires fairly substantial changes to the compiler. So in general, Rust programs don't need to worry about uninitialized values on the stack for correctness. Although they might care for performance. Thankfully, Rust makes it easy to take control here! Uninitialized values are there, and -Safe Rust lets you work with them, but you're never in trouble. +Safe Rust lets you work with them, but you're never in danger. One interesting exception to this rule is working with arrays. Safe Rust doesn't permit you to partially initialize an array. When you initialize an array, you @@ -125,23 +122,23 @@ Unfortunately this is pretty rigid, especially if you need to initialize your array in a more incremental or dynamic way. Unsafe Rust gives us a powerful tool to handle this problem: -`std::mem::uninitialized`. This function pretends to return a value when really +`mem::uninitialized`. This function pretends to return a value when really it does nothing at all. Using it, we can convince Rust that we have initialized a variable, allowing us to do trickier things with conditional and incremental initialization. -Unfortunately, this raises a tricky problem. Assignment has a different meaning -to Rust based on whether it believes that a variable is initialized or not. If -it's uninitialized, then Rust will semantically just memcopy the bits over the -uninit ones, and do nothing else. However if Rust believes a value to be -initialized, it will try to `Drop` the old value! Since we've tricked Rust into -believing that the value is initialized, we can no longer safely use normal -assignment. +Unfortunately, this opens us up to all kinds of problems. Assignment has a +different meaning to Rust based on whether it believes that a variable is +initialized or not. If it's uninitialized, then Rust will semantically just +memcopy the bits over the uninitialized ones, and do nothing else. However if Rust +believes a value to be initialized, it will try to `Drop` the old value! +Since we've tricked Rust into believing that the value is initialized, we +can no longer safely use normal assignment. -This is also a problem if you're working with a raw system allocator, which of -course returns a pointer to uninitialized memory. +This is also a problem if you're working with a raw system allocator, which +returns a pointer to uninitialized memory. -To handle this, we must use the `std::ptr` module. In particular, it provides +To handle this, we must use the `ptr` module. In particular, it provides three functions that allow us to assign bytes to a location in memory without evaluating the old value: `write`, `copy`, and `copy_nonoverlapping`. @@ -157,7 +154,7 @@ evaluating the old value: `write`, `copy`, and `copy_nonoverlapping`. It should go without saying that these functions, if misused, will cause serious havoc or just straight up Undefined Behaviour. The only things that these functions *themselves* require is that the locations you want to read and write -are allocated. However the ways writing arbitrary bit patterns to arbitrary +are allocated. However the ways writing arbitrary bits to arbitrary locations of memory can break things are basically uncountable! Putting this all together, we get the following: @@ -177,6 +174,7 @@ fn main() { x = mem::uninitialized(); for i in 0..SIZE { // very carefully overwrite each index without reading it + // NOTE: exception safety is not a concern; Box can't panic ptr::write(&mut x[i], Box::new(i)); } } @@ -186,15 +184,16 @@ fn main() { ``` It's worth noting that you don't need to worry about ptr::write-style -shenanigans with Plain Old Data (POD; types which don't implement Drop, nor -contain Drop types), because Rust knows not to try to Drop them. Similarly you -should be able to assign the POD fields of partially initialized structs -directly. +shenanigans with types which don't implement Drop or +contain Drop types, because Rust knows not to try to Drop them. Similarly you +should be able to assign to fields of partially initialized structs +directly if those fields don't contain any Drop types. -However when working with uninitialized memory you need to be ever vigilant for +However when working with uninitialized memory you need to be ever-vigilant for Rust trying to Drop values you make like this before they're fully initialized. -So every control path through that variable's scope must initialize the value -before it ends. *This includes code panicking*. Again, POD types need not worry. +Every control path through that variable's scope must initialize the value +before it ends, if has a destructor. +*[This includes code panicking](unwinding.html)*. And that's about it for working with uninitialized memory! Basically nothing anywhere expects to be handed uninitialized memory, so if you're going to pass From dd98edd60e845f0c020526a45bc56103365f121d Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 2 Jul 2015 23:57:28 -0700 Subject: [PATCH 043/104] lifetiiiiimes --- conversions.md | 2 +- lifetimes.md | 388 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 323 insertions(+), 67 deletions(-) diff --git a/conversions.md b/conversions.md index 55b7b20e50d1..25d849dfbc18 100644 --- a/conversions.md +++ b/conversions.md @@ -61,7 +61,7 @@ only implemented automatically, and enables the following transformations: * `T` => `Trait` where `T: Trait` * `SubTrait` => `Trait` where `SubTrait: Trait` (TODO: is this now implied by the previous?) * `Foo<..., T, ...>` => `Foo<..., U, ...>` where: - * T: Unsize + * `T: Unsize` * `Foo` is a struct * Only the last field has type `T` * `T` is not part of the type of any other fields diff --git a/lifetimes.md b/lifetimes.md index cd6f5ad28842..976b4d53e2c9 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -2,106 +2,360 @@ Ownership is the breakout feature of Rust. It allows Rust to be completely memory-safe and efficient, while avoiding garbage collection. Before getting -into the ownership system in detail, we will consider a simple but *fundamental* -language-design problem. +into the ownership system in detail, we will consider the motivation of this +design. + +TODO: Interior Mutability section -# The Tagged Union Problem -TODO: rewrite this to use Box instead? +# Living Without Garbage Collection -The core of the lifetime and mutability system derives from a simple problem: -internal pointers to tagged unions. For instance, consider the following code: +We will assume that you accept that garbage collection is not always an optimal +solution, and that it is desirable to manually manage memory to some extent. +If you do not accept this, might I interest you in a different language? -```rust -enum Foo { - A(u32), - B(f64), -} +Regardless of your feelings on GC, it is pretty clearly a *massive* boon to +making code safe. You never have to worry about things going away *too soon* +(although whether you still *wanted* to be pointing at that thing is a different +issue...). This is a pervasive problem that C and C++ need to deal with. +Consider this simple mistake that all of us who have used a non-GC'd language +have made at one point: -let mut x = B(2.0); -if let B(ref mut y) = x { - *x = A(7); - // OH NO! a u32 has been interpretted as an f64! Type-safety hole! - // (this does not actually compile) - println!("{}", y); +```rust,ignore +fn as_str(data: &u32) -> &str { + // compute the string + let s = format!("{}", data); + // OH NO! We returned a reference to something that + // exists only in this function! + // Dangling pointer! Use after free! Alas! + // (this does not compile in Rust) + &s } ``` -The problem here is an intersection of 3 choices: +This is exactly what Rust's ownership system was built to solve. +Rust knows the scope in which the `&s` lives, and as such can prevent it from +escaping. However this is a simple case that even a C compiler could plausibly +catch. Things get more complicated as code gets bigger and pointers get fed through +various functions. Eventually, a C compiler will fall down and won't be able to +perform sufficient escape analysis to prove your code unsound. It will consequently +be forced to accept your program on the assumption that it is correct. -* data in a tagged union is inline with the tag -* tagged unions are mutable -* being able to take a pointer into a tagged union +This will never happen to Rust. It's up to the programmer to prove to the +compiler that everything is sound. -Remove *any* of these 3 and the problem goes away. Traditionally, functional -languages have avoided this problem by removing the mutable -option. This means that they can in principle keep their data inline (ghc has -a pragma for this). A garbage collected imperative language like Java could alternatively -solve this problem by just keeping all variants elsewhere, so that changing the -variant of a tagged union just overwrites a pointer, and anyone with an outstanding -pointer to the inner data is unaffected thanks to The Magic Of Garbage Collection. +Of course, rust's story around ownership is much more complicated than just +verifying that references don't escape the scope of their referrent. That's +because ensuring pointers are always valid is much more complicated than this. +For instance in this code, -Rust, by contrast, takes a subtler approach. Rust allows mutation, -allows pointers to inner data, and its enums have their data allocated inline. -However it prevents anything from being mutated while there are outstanding -pointers to it! And this is all done at compile time. +```rust,ignore +let mut data = vec![1, 2, 3]; +// get an internal reference +let x = &data[0]; -Interestingly, Rust's `std::cell` module exposes two types that offer an alternative -approach to this problem: +// OH NO! `push` causes the backing storage of `data` to be reallocated. +// Dangling pointer! User after free! Alas! +// (this does not compile in Rust) +data.push(4); -* The `Cell` type allows mutation of aliased data, but -instead forbids internal pointers to that data. The only way to read or write -a Cell is to copy the bits in or out. +println!("{}", x); +``` -* The `RefCell` type allows mutation of aliased data *and* internal pointers, but -manages this through *runtime* checks. It is effectively a thread-unsafe -read-write lock. +naive scope analysis would be insufficient to prevent this bug, because `data` +does in fact live as long as we needed. However it was *changed* while we had +a reference into it. This is why Rust requires any references to freeze the +referrent and its owners. -For more details see Dan Grossman's *Existential Types for Imperative Languages*: -* [paper][grossman-paper] (Advanced) -* [slides][grossman-slides] (Simple) -[grossman-paper]: http://homes.cs.washington.edu/~djg/papers/exists_imp.pdf -[grossman-slides]: https://homes.cs.washington.edu/~djg/slides/esop02_talk.pdf +# References + +There are two kinds of reference: + +* Shared reference: `&` +* Mutable reference: `&mut` + +Which obey the following rules: + +* A reference cannot outlive its referrent +* A mutable reference cannot be aliased + +To define aliasing, we must define the notion of *paths* and *liveness*. + + + + +## Paths + +If all Rust had were values, then every value would be uniquely owned +by a variable or composite structure. From this we naturally derive a *tree* +of ownership. The stack itself is the root of the tree, with every variable +as its direct children. Each variable's direct children would be their fields +(if any), and so on. + +From this view, every value in Rust has a unique *path* in the tree of ownership. +References to a value can subsequently be interpretted as a path in this tree. +Of particular interest are *prefixes*: `x` is a prefix of `y` if `x` owns `y` + +However much data doesn't reside on the stack, and we must also accomodate this. +Globals and thread-locals are simple enough to model as residing at the bottom +of the stack. However data on the heap poses a different problem. + +If all Rust had on the heap was data uniquely by a pointer on the stack, +then we can just treat that pointer as a struct that owns the value on +the heap. Box, Vec, String, and HashMap, are examples of types which uniquely +own data on the heap. + +Unfortunately, data on the heap is not *always* uniquely owned. Rc for instance +introduces a notion of *shared* ownership. Shared ownership means there is no +unique path. A value with no unique path limits what we can do with it. In general, only +shared references can be created to these values. However mechanisms which ensure +mutual exclusion may establish One True Owner temporarily, establishing a unique path +to that value (and therefore all its children). + +The most common way to establish such a path is through *interior mutability*, +in contrast to the *inherited mutability* that everything in Rust normally uses. +Cell, RefCell, Mutex, and RWLock are all examples of interior mutability types. These +types provide exclusive access through runtime restrictions. However it is also +possible to establish unique ownership without interior mutability. For instance, +if an Rc has refcount 1, then it is safe to mutate or move its internals. + + + + +## Liveness + +Roughly, a reference is *live* at some point in a program if it can be +dereferenced. Shared references are always live unless they are literally unreachable +(for instance, they reside in freed or leaked memory). Mutable references can be +reachable but *not* live through the process of *reborrowing*. + +A mutable reference can be reborrowed to either a shared or mutable reference. +Further, the reborrow can produce exactly the same reference, or point to a +path it is a prefix of. For instance, a mutable reference can be reborrowed +to point to a field of its referrent: + +```rust +let x = &mut (1, 2); +{ + // reborrow x to a subfield + let y = &mut x.0; + // y is now live, but x isn't + *y = 3; +} +// y goes out of scope, so x is live again +*x = (5, 7); +``` + +It is also possible to reborrow into *multiple* mutable references, as long as +they are to *disjoint*: no reference is a prefix of another. Rust +explicitly enables this to be done with disjoint struct fields, because +disjointness can be statically proven: + +``` +let x = &mut (1, 2); +{ + // reborrow x to two disjoint subfields + let y = &mut x.0; + let z = &mut x.1; + // y and z are now live, but x isn't + *y = 3; + *z = 4; +} +// y and z go out of scope, so x is live again +*x = (5, 7); +``` + +However it's often the case that Rust isn't sufficiently smart to prove that +multiple borrows are disjoint. *This does not mean it is fundamentally illegal +to make such a borrow*, just that Rust isn't as smart as you want. + +To simplify things, we can model variables as a fake type of reference: *owned* +references. Owned references have much the same semantics as mutable references: +they can be re-borrowed in a mutable or shared manner, which makes them no longer +live. Live owned references have the unique property that they can be moved +out of (though mutable references *can* be swapped out of). This is +only given to *live* owned references because moving its referrent would of +course invalidate all outstanding references prematurely. + +As a local lint against inappropriate mutation, only variables that are marked +as `mut` can be borrowed mutably. + +It is also interesting to note that Box behaves exactly like an owned +reference. It can be moved out of, and Rust understands it sufficiently to +reason about its paths like a normal variable. + + + + +## Aliasing + +With liveness and paths defined, we can now properly define *aliasing*: + +**A mutable reference is aliased if there exists another live reference to it or +one of its prefixes.** + +That's it. Super simple right? Except for the fact that it took us two pages +to define all of the terms in that defintion. You know: Super. Simple. + +Actually it's a bit more complicated than that. In addition to references, +Rust has *raw pointers*: `*const T` and `*mut T`. Raw pointers have no inherent +ownership or aliasing semantics. As a result, Rust makes absolutely no effort +to track that they are used correctly, and they are wildly unsafe. + +**It is an open question to what degree raw pointers have alias semantics. +However it is important for these definitions to be sound that the existence +of a raw pointer does not imply some kind of live path.** # Lifetimes -Rust's static checks are managed by the *borrow checker* (borrowck), which tracks -mutability and outstanding loans. This analysis can in principle be done without -any help locally. However as soon as data starts crossing the function boundary, -we have some serious trouble. In principle, borrowck could be a massive -whole-program analysis engine to handle this problem, but this would be an -atrocious solution. It would be terribly slow, and errors would be horribly -non-local. +Rust enforces these rules through *lifetimes*. Lifetimes are effectively +just names for scopes on the stack, somewhere in the program. Each reference, +and anything that contains a reference, is tagged with a lifetime specifying +the scope it's valid for. -Instead, Rust tracks ownership through *lifetimes*. Every single reference and value -in Rust is tagged with a lifetime that indicates the scope it is valid for. -Rust has two kinds of reference: +Within a function body, Rust generally doesn't let you explicitly name the +lifetimes involved. This is because it's generally not really *necessary* +to talk about lifetimes in a local context; rust has all the information and +can work out everything. -* Shared reference: `&` -* Mutable reference: `&mut` +However once you cross the function boundary, you need to start talking about +lifetimes. Lifetimes are denoted with an apostrophe: `'a`, `'static`. To dip +our toes with lifetimes, we're going to pretend that we're actually allowed +to label scopes with lifetimes, and desugar the examples from the start of +this chapter. -The main rules are as follows: +Our examples made use of *aggressive* sugar around scopes and lifetimes, +because writing everything out explicitly is *extremely noisy*. All rust code +relies on aggressive inference and elision of "obvious" things. -* A shared reference can be aliased -* A mutable reference cannot be aliased -* A reference cannot outlive its referrent (`&'a T -> T: 'a`) +One particularly interesting piece of sugar is that each `let` statement implicitly +introduces a scope. For the most part, this doesn't really matter. However it +does matter for variables that refer to each other. As a simple example, let's +completely desugar this simple piece of Rust code: -However non-mutable variables have some special rules: +```rust +let x = 0; +let y = &x; +let z = &y; +``` -* You cannot mutate or mutably borrow a non-mut variable, +becomes: -Only variables marked as mutable can be borrowed mutably, though this is little -more than a local lint against incorrect usage of a value. +```rust,ignore +// NOTE: `'a:` and `&'a x` is not valid syntax! +'a: { + let x: i32 = 0; + 'b: { + let y: &'a i32 = &'a x; + 'c: { + let z: &'b &'a i32 = &'b y; + } + } +} +``` +Wow. That's... awful. Let's all take a moment to thank Rust for being a huge +pile of sugar with sugar on top. +Anyway, let's look at some of those examples from before: + +```rust,ignore +fn as_str(data: &u32) -> &str { + let s = format!("{}", data); + &s +} +``` + +desugars to: + +```rust,ignore +fn as_str<'a>(data: &'a u32) -> &'a str { + 'b: { + let s = format!("{}", data); + return &'b s + } +} +``` + +This signature of `as_str` takes a reference to a u32 with *some* lifetime, and +promises that it can produce a reference to a str that can live *just as long*. +Already we can see why this signature might be trouble. That basically implies +that we're going to *find* a str somewhere in the scope that u32 originated in, +or somewhere *even* earlier. That's uh... a big ask. + +We then proceed to compute the string `s`, and return a reference to it. +Unfortunately, since `s` was defined in the scope `'b`, the reference we're +returning can only live for that long. From the perspective of the compiler, +we've failed *twice* here. We've failed to fulfill the contract we were asked +to fulfill (`'b` is unrelated to `'a`); and we've also tried to make a reference +outlive its referrent by returning an `&'b`, where `'b` is in our function. + +Shoot! + +Of course, the right way to right this function is as follows: + +```rust +fn to_string(data: &u32) -> String { + format!("{}", data) +} +``` + +We must produce an owned value inside the function to return it! The only way +we could have returned an `&'a str` would have been if it was in a field of the +`&'a u32`, which is obviously not the case. + +(Actually we could have also just returned a string literal, though this limits +the behaviour of our function *just a bit*.) + +How about the other example: + +```rust,ignore +let mut data = vec![1, 2, 3]; +let x = &data[0]; +data.push(4); +println!("{}", x); +``` + +```rust,ignore +'a: { + let mut data: Vec = vec![1, 2, 3]; + 'b: { + let x: &'a i32 = Index::index(&'a data, 0); + 'c: { + // Exactly what the desugar for Vec::push is is up to Rust. + // This particular desugar is a decent approximation for our + // purpose. In particular methods oft invoke a temporary borrow. + let temp: &'c mut Vec = &'c mut data; + // NOTE: Vec::push is not valid syntax + Vec::push(temp, 4); + } + println!("{}", x); + } +} +``` + +Here the problem is that we're trying to mutably borrow the `data` path, while +we have a reference into something it's a prefix of. Rust subsequently throws +up its hands in disgust and rejects our program. The correct way to write this +is to just re-order the code so that we make `x` *after* we push: + +TODO: convince myself of this. + +```rust +let mut data = vec![1, 2, 3]; +data.push(4); + +let x = &data[0]; +println!("{}", x); +``` @@ -213,7 +467,9 @@ these are unstable due to their awkward nature and questionable utility. -# Higher-Rank Lifetimes +# Higher-Rank Trait Bounds + +// TODO: make aturon less mad Generics in Rust generally allow types to be instantiated with arbitrary associated lifetimes, but this fixes the lifetimes they work with once From a42a41520584e28a8fb5e4f0b8b2e89900377011 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 3 Jul 2015 09:49:30 -0700 Subject: [PATCH 044/104] rework unsafe intro to be 1000% more adorable --- README.md | 175 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 126 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index b86f6209f35a..55e4bc5c8727 100644 --- a/README.md +++ b/README.md @@ -13,26 +13,66 @@ Where TRPL introduces the language and teaches the basics, TURPL dives deep into the specification of the language, and all the nasty bits necessary to write Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know the basics of the language and systems programming. We will not explain the -stack or heap, we will not explain the syntax. +stack or heap, we will not explain the basic syntax. -# A Tale Of Two Languages +# Meet Safe and Unsafe + +Safe and Unsafe are Rust's chief engineers. + +TODO: ADORABLE PICTURES OMG + +Unsafe handles all the dangerous internal stuff. They build the foundations +and handle all the dangerous materials. By all accounts, Unsafe is really a bit +unproductive, because the nature of their work means that they have to spend a +lot of time checking and double-checking everything. What if there's an earthquake +on a leap year? Are we ready for that? Unsafe better be, because if they get +*anything* wrong, everything will blow up! What Unsafe brings to the table is +*quality*, not quantity. Still, nothing would ever get done if everything was +built to Unsafe's standards! + +That's where Safe comes in. Safe has to handle *everything else*. Since Safe needs +to *get work done*, they've grown to be fairly carless and clumsy! Safe doesn't worry +about all the crazy eventualities that Unsafe does, because life is too short to deal +with leap-year-earthquakes. Of course, this means there's some jobs that Safe just +can't handle. Safe is all about quantity over quality. + +Unsafe loves Safe to bits, but knows that tey *can never trust them to do the +right thing*. Still, Unsafe acknowledges that not every problem needs quite the +attention to detail that they apply. Indeed, Unsafe would *love* if Safe could do +*everything* for them. To accomplish this, Unsafe spends most of their time +building *safe abstractions*. These abstractions handle all the nitty-gritty +details for Safe, and choose good defaults so that the simplest solution (which +Safe will inevitably use) is usually the *right* one. Once a safe abstraction is +built, Unsafe ideally needs to never work on it again, and Safe can blindly use +it in all their work. + +Unsafe's attention to detail means that all the things that they mark as ok for +Safe to use can be combined in arbitrarily ridiculous ways, and all the rules +that Unsafe is forced to uphold will never be violated. If they *can* be violated +by Safe, that means *Unsafe*'s the one in the wrong. Safe can work carelessly, +knowing that if anything blows up, it's not *their* fault. Safe can also call in +Unsafe at any time if there's a hard problem they can't quite work out, or if they +can't meet the client's quality demands. Of course, Unsafe will beg and plead Safe +to try their latest safe abstraction first! + +In addition to being adorable, Safe and Unsafe are what makes Rust possible. Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust. Any time someone opines the guarantees of Rust, they are almost surely talking about -Safe Rust. However Safe Rust is not sufficient to write every program. For that, -we need the Unsafe Rust superset. +Safe. However Safe is not sufficient to write every program. For that, +we need the Unsafe superset. Most fundamentally, writing bindings to other languages (such as the C exposed by your operating system) is never going to be safe. Rust -can't control what other languages do to program execution! However Unsafe Rust is +can't control what other languages do to program execution! However Unsafe is also necessary to construct fundamental abstractions where the type system is not sufficient to automatically prove what you're doing is sound. Indeed, the Rust standard library is implemented in Rust, and it makes substantial -use of Unsafe Rust for implementing IO, memory allocation, collections, +use of Unsafe for implementing IO, memory allocation, collections, synchronization, and other low-level computational primitives. Upon hearing this, many wonder why they would not simply just use C or C++ in place of @@ -47,46 +87,40 @@ one does not have to suddenly worry about indexing out of bounds on `y`. C and C++, by contrast, have pervasive unsafety baked into the language. Even the modern best practices like `unique_ptr` have various safety pitfalls. -It should also be noted that writing Unsafe Rust should be regarded as an exceptional -action. Unsafe Rust is often the domain of *fundamental libraries*. Anything that needs +It cannot be emphasized enough that Unsafe should be regarded as an exceptional +thing, not a normal one. Unsafe is often the domain of *fundamental libraries*: anything that needs to make FFI bindings or define core abstractions. These fundamental libraries then expose -a *safe* interface for intermediate libraries and applications to build upon. And these +a safe interface for intermediate libraries and applications to build upon. And these safe interfaces make an important promise: if your application segfaults, it's not your fault. *They* have a bug. And really, how is that different from *any* safe language? Python, Ruby, and Java libraries can internally do all sorts of nasty things. The languages themselves are no -different. Safe languages regularly have bugs that cause critical vulnerabilities. -The fact that Rust is written with a healthy spoonful of Unsafe Rust is no different. +different. Safe languages *regularly* have bugs that cause critical vulnerabilities. +The fact that Rust is written with a healthy spoonful of Unsafe is no different. However it *does* mean that Rust doesn't need to fall back to the pervasive unsafety of C to do the nasty things that need to get done. -# What does `unsafe` mean? -Rust tries to model memory safety through the `unsafe` keyword. Interestingly, -the meaning of `unsafe` largely revolves around what -its *absence* means. If the `unsafe` keyword is absent from a program, it should -not be possible to violate memory safety under *any* conditions. The presence -of `unsafe` means that there are conditions under which this code *could* -violate memory safety. +# What do Safe and Unsafe really mean? -To be more concrete, Rust cares about preventing the following things: +Rust cares about preventing the following things: -* Dereferencing null/dangling pointers -* Reading uninitialized memory -* Breaking the pointer aliasing rules (TBD) (llvm rules + noalias on &mut and & w/o UnsafeCell) -* Invoking Undefined Behaviour (in e.g. compiler intrinsics) +* 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` larger than char::MAX + * a `char` larger than char::MAX (TODO: check if stronger restrictions apply) * A non-utf8 `str` -* Unwinding into an FFI function -* Causing a data race +* Unwinding into another language +* Causing a [data race][] +* Invoking Misc. Undefined Behaviour (in e.g. compiler intrinsics) That's it. That's all the Undefined Behaviour in Rust. Libraries are free to declare arbitrary requirements if they could transitively cause memory safety @@ -95,15 +129,17 @@ quite permisive with respect to other dubious operations. Rust considers it "safe" to: * Deadlock +* Have a Race Condition * Leak memory * Fail to call destructors * Overflow integers * Delete the production database -However any program that does such a thing is *probably* incorrect. Rust just isn't -interested in modeling these problems, as they are much harder to prevent in general, -and it's literally impossible to prevent incorrect programs from getting written. +However any program that does such a thing is *probably* incorrect. Rust +provides lots of tools to make doing these things rare, but these problems are +considered impractical to categorically prevent. +Rust models the seperation between Safe and Unsafe with the `unsafe` keyword. There are several places `unsafe` can appear in Rust today, which can largely be grouped into two categories: @@ -112,7 +148,7 @@ you to write `unsafe` elsewhere: * On functions, `unsafe` is declaring the function to be unsafe to call. Users of the function must check the documentation to determine what this means, and then have to write `unsafe` somewhere to identify that they're aware of - the danger. + the danger. * On trait declarations, `unsafe` is declaring that *implementing* the trait is an unsafe operation, as it has contracts that other unsafe code is free to trust blindly. @@ -126,19 +162,19 @@ unchecked contracts: There is also `#[unsafe_no_drop_flag]`, which is a special case that exists for historical reasons and is in the process of being phased out. See the section on -destructors for details. +[destructors][] for details. Some examples of unsafe functions: * `slice::get_unchecked` will perform unchecked indexing, allowing memory safety to be freely violated. -* `ptr::offset` in an intrinsic that invokes Undefined Behaviour if it is +* `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is not "in bounds" as defined by LLVM (see the lifetimes section for details). * `mem::transmute` reinterprets some value as having the given type, - bypassing type safety in arbitrary ways. (see the conversions section for details) + bypassing type safety in arbitrary ways. (see [conversions][] for details) * All FFI functions are `unsafe` because they can do arbitrary things. C being an obvious culprit, but generally any language can do something - that Rust isn't happy about. (see the FFI section for details) + that Rust isn't happy about. As of Rust 1.0 there are exactly two unsafe traits: @@ -147,25 +183,60 @@ As of Rust 1.0 there are exactly two unsafe traits: * `Sync` is a marker trait that promises that threads can safely share implementors through a shared reference. -All other traits that declare any kind of contract *really* can't be trusted -to adhere to their contract when memory-safety is at stake. For instance Rust has -`PartialOrd` and `Ord` to differentiate between types which can "just" be -compared and those that implement a total ordering. However you can't actually -trust an implementor of `Ord` to actually provide a total ordering if failing to -do so causes you to e.g. index out of bounds. But if it just makes your program -do a stupid thing, then it's "fine" to rely on `Ord`. +The need for unsafe traits boils down to the fundamental lack of trust that Unsafe +has for Safe. All safe traits are free to declare arbitrary contracts, but because +implementing them is a job for Safe, Unsafe can't trust those contracts to actually +be upheld. -The reason this is the case is that `Ord` is safe to implement, and it should be -impossible for bad *safe* code to violate memory safety. Rust has traditionally -avoided making traits unsafe because it makes `unsafe` pervasive in the language, -which is not desirable. The only reason `Send` and `Sync` are unsafe is because -thread safety is a sort of fundamental thing that a program can't really guard -against locally (even by-value message passing still requires a notion Send). +For instance Rust has `PartialOrd` and `Ord` traits to try to differentiate +between types which can "just" be compared, and those that actually implement a +*total* ordering. Pretty much every API that wants to work with data that can be +compared *really* wants Ord data. For instance, a sorted map like BTreeMap +*doesn't even make sense* for partially ordered types. If you claim to implement +Ord for a type, but don't actually provide a proper total ordering, BTreeMap will +get *really confused* and start making a total mess of itself. Data that is +inserted may be impossible to find! + +But that's ok. BTreeMap is safe, so it guarantees that even if you give it a +*completely* garbage Ord implementation, it will still do something *safe*. You +won't start reading uninitialized memory or unallocated memory. In fact, BTreeMap +manages to not actually lose any of your data. When the map is dropped, all the +destructors will be successfully called! Hooray! + +However BTreeMap is implemented using a modest spoonful of Unsafe (most collections +are). That means that it is not necessarily *trivially true* that a bad Ord +implementation will make BTreeMap behave safely. Unsafe most be sure not to rely +on Ord *where safety is at stake*, because Ord is provided by Safe, and memory +safety is not Safe's responsibility to uphold. *It must be impossible for Safe +code to violate memory safety*. + +But wouldn't it be grand if there was some way for Unsafe to trust *some* trait +contracts *somewhere*? This is the problem that unsafe traits tackle: by marking +*the trait itself* as unsafe *to implement*, Unsafe can trust the implementation +to be correct (because Unsafe can trust themself). + +Rust has traditionally avoided making traits unsafe because it makes Unsafe +pervasive, which is not desirable. Send and Sync are unsafe is because +thread safety is a *fundamental property* that Unsafe cannot possibly hope to +defend against in the same way it would defend against a bad Ord implementation. +The only way to possibly defend against thread-unsafety would be to *not use +threading at all*. Making every operation atomic isn't even sufficient, because +it's possible for complex invariants between disjoint locations in memory. + +Even concurrent paradigms that are traditionally regarded as Totally Safe like +message passing implicitly rely on some notion of thread safety -- are you +really message-passing if you send a *pointer*? Send and Sync therefore require +some *fundamental* level of trust that Safe code can't provide, so they must be +unsafe to implement. To help obviate the pervasive unsafety that this would +introduce, Send (resp. Sync) is *automatically* derived for all types composed only +of Send (resp. Sync) values. 99% of types are Send and Sync, and 99% of those +never actually say it (the remaining 1% is overwhelmingly synchronization +primitives). -# Working with unsafe +# Working with Unsafe Rust generally only gives us the tools to talk about safety in a scoped and binary manner. Unfortunately reality is significantly more complicated than that. @@ -254,5 +325,11 @@ trust the capacity field because there's no way to verify it. Generally, the only bullet-proof way to limit the scope of unsafe code is at the module boundary with privacy. -[trpl]: https://doc.rust-lang.org/book/ + +[trpl]: https://doc.rust-lang.org/book/ +[pointer aliasing rules]: lifetimes.html#references +[uninitialized memory]: uninitialized.html +[data race]: concurrency.html +[destructors]: raii.html +[conversions]: conversions.html From 31adad6aad5b0fbff85a6effcfc5e11ba611493d Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 6 Jul 2015 18:36:16 -0700 Subject: [PATCH 045/104] SHARD ALL THE CHAPTERS --- README.md | 319 +--------- SUMMARY.md | 40 +- casts.md | 55 ++ checked-uninit.md | 109 ++++ coercions.md | 72 +++ constructors.md | 26 + conversions.md | 185 ------ data.md | 292 --------- destructors.md | 140 +++++ dot-operator.md | 6 + exotic-sizes.md | 69 ++ hrtb.md | 72 +++ leaking.md | 229 +++++++ lifetime-elision.md | 64 ++ lifetime-misc.md | 229 +++++++ lifetime-mismatch.md | 81 +++ lifetimes.md | 1025 ++++-------------------------- meet-safe-and-unsafe.md | 82 +++ other-reprs.md | 61 ++ ownership.md | 66 ++ raii.md | 410 ------------ references.md | 139 +++++ repr-rust.md | 124 ++++ safe-unsafe-meaning.md | 135 ++++ subtyping.md | 177 ++++++ transmutes.md | 29 + unbounded-lifetimes.md | 37 ++ unchecked-uninit.md | 86 +++ uninitialized.md | 194 +----- vec-alloc.md | 117 ++++ vec-dealloc.md | 29 + vec-deref.md | 40 ++ vec-drain.md | 318 ++++++++++ vec-final.md | 309 +++++++++ vec-insert-remove.md | 50 ++ vec-into-iter.md | 293 +++++++++ vec-layout.md | 61 ++ vec-push-pop.md | 55 ++ vec.md | 1317 --------------------------------------- working-with-unsafe.md | 88 +++ 40 files changed, 3616 insertions(+), 3614 deletions(-) create mode 100644 casts.md create mode 100644 checked-uninit.md create mode 100644 coercions.md create mode 100644 constructors.md create mode 100644 destructors.md create mode 100644 dot-operator.md create mode 100644 exotic-sizes.md create mode 100644 hrtb.md create mode 100644 leaking.md create mode 100644 lifetime-elision.md create mode 100644 lifetime-misc.md create mode 100644 lifetime-mismatch.md create mode 100644 meet-safe-and-unsafe.md create mode 100644 other-reprs.md create mode 100644 ownership.md create mode 100644 references.md create mode 100644 repr-rust.md create mode 100644 safe-unsafe-meaning.md create mode 100644 subtyping.md create mode 100644 transmutes.md create mode 100644 unbounded-lifetimes.md create mode 100644 unchecked-uninit.md create mode 100644 vec-alloc.md create mode 100644 vec-dealloc.md create mode 100644 vec-deref.md create mode 100644 vec-drain.md create mode 100644 vec-final.md create mode 100644 vec-insert-remove.md create mode 100644 vec-into-iter.md create mode 100644 vec-layout.md create mode 100644 vec-push-pop.md create mode 100644 working-with-unsafe.md diff --git a/README.md b/README.md index 55e4bc5c8727..a801a21db3d5 100644 --- a/README.md +++ b/README.md @@ -13,323 +13,8 @@ Where TRPL introduces the language and teaches the basics, TURPL dives deep into the specification of the language, and all the nasty bits necessary to write Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know the basics of the language and systems programming. We will not explain the -stack or heap, we will not explain the basic syntax. +stack or heap. We will not explain the basic syntax. - - -# Meet Safe and Unsafe - -Safe and Unsafe are Rust's chief engineers. - -TODO: ADORABLE PICTURES OMG - -Unsafe handles all the dangerous internal stuff. They build the foundations -and handle all the dangerous materials. By all accounts, Unsafe is really a bit -unproductive, because the nature of their work means that they have to spend a -lot of time checking and double-checking everything. What if there's an earthquake -on a leap year? Are we ready for that? Unsafe better be, because if they get -*anything* wrong, everything will blow up! What Unsafe brings to the table is -*quality*, not quantity. Still, nothing would ever get done if everything was -built to Unsafe's standards! - -That's where Safe comes in. Safe has to handle *everything else*. Since Safe needs -to *get work done*, they've grown to be fairly carless and clumsy! Safe doesn't worry -about all the crazy eventualities that Unsafe does, because life is too short to deal -with leap-year-earthquakes. Of course, this means there's some jobs that Safe just -can't handle. Safe is all about quantity over quality. - -Unsafe loves Safe to bits, but knows that tey *can never trust them to do the -right thing*. Still, Unsafe acknowledges that not every problem needs quite the -attention to detail that they apply. Indeed, Unsafe would *love* if Safe could do -*everything* for them. To accomplish this, Unsafe spends most of their time -building *safe abstractions*. These abstractions handle all the nitty-gritty -details for Safe, and choose good defaults so that the simplest solution (which -Safe will inevitably use) is usually the *right* one. Once a safe abstraction is -built, Unsafe ideally needs to never work on it again, and Safe can blindly use -it in all their work. - -Unsafe's attention to detail means that all the things that they mark as ok for -Safe to use can be combined in arbitrarily ridiculous ways, and all the rules -that Unsafe is forced to uphold will never be violated. If they *can* be violated -by Safe, that means *Unsafe*'s the one in the wrong. Safe can work carelessly, -knowing that if anything blows up, it's not *their* fault. Safe can also call in -Unsafe at any time if there's a hard problem they can't quite work out, or if they -can't meet the client's quality demands. Of course, Unsafe will beg and plead Safe -to try their latest safe abstraction first! - -In addition to being adorable, Safe and Unsafe are what makes Rust possible. -Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust. -Any time someone opines the guarantees of Rust, they are almost surely talking about -Safe. However Safe is not sufficient to write every program. For that, -we need the Unsafe superset. - -Most fundamentally, writing bindings to other languages -(such as the C exposed by your operating system) is never going to be safe. Rust -can't control what other languages do to program execution! However Unsafe is -also necessary to construct fundamental abstractions where the type system is not -sufficient to automatically prove what you're doing is sound. - -Indeed, the Rust standard library is implemented in Rust, and it makes substantial -use of Unsafe for implementing IO, memory allocation, collections, -synchronization, and other low-level computational primitives. - -Upon hearing this, many wonder why they would not simply just use C or C++ in place of -Rust (or just use a "real" safe language). If we're going to do unsafe things, why not -lean on these much more established languages? - -The most important difference between C++ and Rust is a matter of defaults: -Rust is 100% safe by default. Even when you *opt out* of safety in Rust, it is a modular -action. In deciding to work with unchecked uninitialized memory, this does not -suddenly make dangling or null pointers a problem. When using unchecked indexing on `x`, -one does not have to suddenly worry about indexing out of bounds on `y`. -C and C++, by contrast, have pervasive unsafety baked into the language. Even the -modern best practices like `unique_ptr` have various safety pitfalls. - -It cannot be emphasized enough that Unsafe should be regarded as an exceptional -thing, not a normal one. Unsafe is often the domain of *fundamental libraries*: anything that needs -to make FFI bindings or define core abstractions. These fundamental libraries then expose -a safe interface for intermediate libraries and applications to build upon. And these -safe interfaces make an important promise: if your application segfaults, it's not your -fault. *They* have a bug. - -And really, how is that different from *any* safe language? Python, Ruby, and Java libraries -can internally do all sorts of nasty things. The languages themselves are no -different. Safe languages *regularly* have bugs that cause critical vulnerabilities. -The fact that Rust is written with a healthy spoonful of Unsafe is no different. -However it *does* mean that Rust doesn't need to fall back to the pervasive unsafety of -C to do the nasty things that need to get done. - - - - - -# What do Safe and Unsafe really mean? - -Rust cares about 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` larger than char::MAX (TODO: check if stronger restrictions apply) - * A non-utf8 `str` -* Unwinding into another language -* Causing a [data race][] -* Invoking Misc. Undefined Behaviour (in e.g. compiler intrinsics) - -That's it. That's all the Undefined Behaviour in Rust. Libraries are free to -declare arbitrary requirements if they could transitively cause memory safety -issues, but it all boils down to the above actions. Rust is otherwise -quite permisive with respect to other dubious operations. Rust considers it -"safe" to: - -* Deadlock -* Have a Race Condition -* Leak memory -* Fail to call destructors -* Overflow integers -* Delete the production database - -However any program that does such a thing is *probably* incorrect. Rust -provides lots of tools to make doing these things rare, but these problems are -considered impractical to categorically prevent. - -Rust models the seperation between Safe and Unsafe with the `unsafe` keyword. -There are several places `unsafe` can appear in Rust today, which can largely be -grouped into two categories: - -* There are unchecked contracts here. To declare you understand this, I require -you to write `unsafe` elsewhere: - * On functions, `unsafe` is declaring the function to be unsafe to call. Users - of the function must check the documentation to determine what this means, - and then have to write `unsafe` somewhere to identify that they're aware of - the danger. - * On trait declarations, `unsafe` is declaring that *implementing* the trait - is an unsafe operation, as it has contracts that other unsafe code is free to - trust blindly. - -* I am declaring that I have, to the best of my knowledge, adhered to the -unchecked contracts: - * On trait implementations, `unsafe` is declaring that the contract of the - `unsafe` trait has been upheld. - * On blocks, `unsafe` is declaring any unsafety from an unsafe - operation within to be handled, and therefore the parent function is safe. - -There is also `#[unsafe_no_drop_flag]`, which is a special case that exists for -historical reasons and is in the process of being phased out. See the section on -[destructors][] for details. - -Some examples of unsafe functions: - -* `slice::get_unchecked` will perform unchecked indexing, allowing memory - safety to be freely violated. -* `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is - not "in bounds" as defined by LLVM (see the lifetimes section for details). -* `mem::transmute` reinterprets some value as having the given type, - bypassing type safety in arbitrary ways. (see [conversions][] for details) -* All FFI functions are `unsafe` because they can do arbitrary things. - C being an obvious culprit, but generally any language can do something - that Rust isn't happy about. - -As of Rust 1.0 there are exactly two unsafe traits: - -* `Send` is a marker trait (it has no actual API) that promises implementors - are safe to send to another thread. -* `Sync` is a marker trait that promises that threads can safely share - implementors through a shared reference. - -The need for unsafe traits boils down to the fundamental lack of trust that Unsafe -has for Safe. All safe traits are free to declare arbitrary contracts, but because -implementing them is a job for Safe, Unsafe can't trust those contracts to actually -be upheld. - -For instance Rust has `PartialOrd` and `Ord` traits to try to differentiate -between types which can "just" be compared, and those that actually implement a -*total* ordering. Pretty much every API that wants to work with data that can be -compared *really* wants Ord data. For instance, a sorted map like BTreeMap -*doesn't even make sense* for partially ordered types. If you claim to implement -Ord for a type, but don't actually provide a proper total ordering, BTreeMap will -get *really confused* and start making a total mess of itself. Data that is -inserted may be impossible to find! - -But that's ok. BTreeMap is safe, so it guarantees that even if you give it a -*completely* garbage Ord implementation, it will still do something *safe*. You -won't start reading uninitialized memory or unallocated memory. In fact, BTreeMap -manages to not actually lose any of your data. When the map is dropped, all the -destructors will be successfully called! Hooray! - -However BTreeMap is implemented using a modest spoonful of Unsafe (most collections -are). That means that it is not necessarily *trivially true* that a bad Ord -implementation will make BTreeMap behave safely. Unsafe most be sure not to rely -on Ord *where safety is at stake*, because Ord is provided by Safe, and memory -safety is not Safe's responsibility to uphold. *It must be impossible for Safe -code to violate memory safety*. - -But wouldn't it be grand if there was some way for Unsafe to trust *some* trait -contracts *somewhere*? This is the problem that unsafe traits tackle: by marking -*the trait itself* as unsafe *to implement*, Unsafe can trust the implementation -to be correct (because Unsafe can trust themself). - -Rust has traditionally avoided making traits unsafe because it makes Unsafe -pervasive, which is not desirable. Send and Sync are unsafe is because -thread safety is a *fundamental property* that Unsafe cannot possibly hope to -defend against in the same way it would defend against a bad Ord implementation. -The only way to possibly defend against thread-unsafety would be to *not use -threading at all*. Making every operation atomic isn't even sufficient, because -it's possible for complex invariants between disjoint locations in memory. - -Even concurrent paradigms that are traditionally regarded as Totally Safe like -message passing implicitly rely on some notion of thread safety -- are you -really message-passing if you send a *pointer*? Send and Sync therefore require -some *fundamental* level of trust that Safe code can't provide, so they must be -unsafe to implement. To help obviate the pervasive unsafety that this would -introduce, Send (resp. Sync) is *automatically* derived for all types composed only -of Send (resp. Sync) values. 99% of types are Send and Sync, and 99% of those -never actually say it (the remaining 1% is overwhelmingly synchronization -primitives). - - - - -# Working with Unsafe - -Rust generally only gives us the tools to talk about safety in a scoped and -binary manner. Unfortunately reality is significantly more complicated than that. -For instance, consider the following toy function: - -```rust -fn do_idx(idx: usize, arr: &[u8]) -> Option { - if idx < arr.len() { - unsafe { - Some(*arr.get_unchecked(idx)) - } - } else { - None - } -} -``` - -Clearly, this function is safe. We check that the index is in bounds, and if it -is, index into the array in an unchecked manner. But even in such a trivial -function, the scope of the unsafe block is questionable. Consider changing the -`<` to a `<=`: - -```rust -fn do_idx(idx: usize, arr: &[u8]) -> Option { - if idx <= arr.len() { - unsafe { - Some(*arr.get_unchecked(idx)) - } - } else { - None - } -} -``` - -This program is now unsound, an yet *we only modified safe code*. This is the -fundamental problem of safety: it's non-local. The soundness of our unsafe -operations necessarily depends on the state established by "safe" operations. -Although safety *is* modular (we *still* don't need to worry about about -unrelated safety issues like uninitialized memory), it quickly contaminates the -surrounding code. - -Trickier than that is when we get into actual statefulness. Consider a simple -implementation of `Vec`: - -```rust -// Note this defintion is insufficient. See the section on lifetimes. -struct Vec { - ptr: *mut T, - len: usize, - cap: usize, -} - -// Note this implementation does not correctly handle zero-sized types. -// We currently live in a nice imaginary world of only positive fixed-size -// types. -impl Vec { - fn push(&mut self, elem: T) { - if self.len == self.cap { - // not important for this example - self.reallocate(); - } - unsafe { - ptr::write(self.ptr.offset(len as isize), elem); - self.len += 1; - } - } -} -``` - -This code is simple enough to reasonably audit and verify. Now consider -adding the following method: - -```rust - fn make_room(&mut self) { - // grow the capacity - self.cap += 1; - } -``` - -This code is safe, but it is also completely unsound. Changing the capacity -violates the invariants of Vec (that `cap` reflects the allocated space in the -Vec). This is not something the rest of `Vec` can guard against. It *has* to -trust the capacity field because there's no way to verify it. - -`unsafe` does more than pollute a whole function: it pollutes a whole *module*. -Generally, the only bullet-proof way to limit the scope of unsafe code is at the -module boundary with privacy. - - - -[trpl]: https://doc.rust-lang.org/book/ -[pointer aliasing rules]: lifetimes.html#references -[uninitialized memory]: uninitialized.html -[data race]: concurrency.html -[destructors]: raii.html -[conversions]: conversions.html +[trpl]: https://doc.rust-lang.org/book/ \ No newline at end of file diff --git a/SUMMARY.md b/SUMMARY.md index 91a07b79e389..225708e21869 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,10 +1,42 @@ # Summary +* [Meet Safe and Unsafe](meet-safe-and-unsafe.md) + * [What Do Safe and Unsafe Mean](safe-unsafe-meaning.md) + * [Working with Unsafe](working-with-unsafe.md) * [Data Layout](data.md) -* [Ownership and Lifetimes](lifetimes.md) -* [Conversions](conversions.md) + * [repr(Rust)](repr-rust.md) + * [Exotically Sized Types](exotic-sizes.md) + * [Other reprs](other-reprs.md) +* [Ownership](ownership.md) + * [References](references.md) + * [Lifetimes](lifetimes.md) + * [Limits of lifetimes](lifetime-mismatch.md) + * [Lifetime Elision](lifetime-elision.md) + * [Unbounded Lifetimes](unbounded-lifetimes.md) + * [Higher-Rank Trait Bounds](hrtb.md) + * [Subtyping and Variance](subtyping.md) + * [Misc](lifetime-misc.md) +* [Type Conversions](conversions.md) + * [Coercions](coercions.md) + * [The Dot Operator](dot-operator.md) + * [Casts](casts.md) + * [Transmutes](transmutes.md) * [Uninitialized Memory](uninitialized.md) -* [Ownership-oriented resource management (RAII)](raii.md) + * [Checked](checked-uninit.md) + * [Unchecked](unchecked-uninit.md) +* [Ownership-Oriented Resource Management](raii.md) + * [Constructors](constructors.md) + * [Destructors](destructors.md) + * [Leaking](leaking.md) * [Unwinding](unwinding.md) * [Concurrency](concurrency.md) -* [Example: Implementing Vec](vec.md) \ No newline at end of file +* [Example: Implementing Vec](vec.md) + * [Layout](vec-layout.md) + * [Allocating](vec-alloc.md) + * [Push and Pop](vec-push-pop.md) + * [Deallocating](vec-dealloc.md) + * [Deref](vec-deref.md) + * [Insert and Remove](vec-insert-remove.md) + * [IntoIter](vec-into-iter.md) + * [Drain](vec-drain.md) + * [Final Code](vec-final.md) \ No newline at end of file diff --git a/casts.md b/casts.md new file mode 100644 index 000000000000..730d8499acfe --- /dev/null +++ b/casts.md @@ -0,0 +1,55 @@ +% Casts + +Casts are a superset of coercions: every coercion can be explicitly invoked via a +cast, but some conversions *require* a cast. These "true casts" are generally regarded +as dangerous or problematic actions. True casts revolve around raw pointers and +the primitive numeric types. True casts aren't checked. + +Here's an exhaustive list of all the true casts. For brevity, we will use `*` +to denote either a `*const` or `*mut`, and `integer` to denote any integral primitive: + + * `*T as *U` where `T, U: Sized` + * `*T as *U` TODO: explain unsized situation + * `*T as integer` + * `integer as *T` + * `number as number` + * `C-like-enum as integer` + * `bool as integer` + * `char as integer` + * `u8 as char` + * `&[T; n] as *const T` + * `fn as *T` where `T: Sized` + * `fn as integer` + +where `&.T` and `*T` are references of either mutability, +and where unsize_kind(`T`) is the kind of the unsize info +in `T` - the vtable for a trait definition (e.g. `fmt::Display` or +`Iterator`, not `Iterator`) or a length (or `()` if `T: Sized`). + +Note that lengths are not adjusted when casting raw slices - +`T: *const [u16] as *const [u8]` creates a slice that only includes +half of the original memory. + +Casting is not transitive, that is, even if `e as U1 as U2` is a valid +expression, `e as U2` is not necessarily so (in fact it will only be valid if +`U1` coerces to `U2`). + +For numeric casts, there are quite a few cases to consider: + +* casting between two integers of the same size (e.g. i32 -> u32) is a no-op +* casting from a larger integer to a smaller integer (e.g. u32 -> u8) will truncate +* casting from a smaller integer to a larger integer (e.g. u8 -> u32) will + * zero-extend if the source is unsigned + * sign-extend if the source is signed +* casting from a float to an integer will round the float towards zero + * **NOTE: currently this will cause Undefined Behaviour if the rounded + value cannot be represented by the target integer type**. This is a bug + and will be fixed. (TODO: figure out what Inf and NaN do) +* casting from an integer to float will produce the floating point representation + of the integer, rounded if necessary (rounding strategy unspecified). +* casting from an f32 to an f64 is perfect and lossless. +* casting from an f64 to an f32 will produce the closest possible value + (rounding strategy unspecified). + * **NOTE: currently this will cause Undefined Behaviour if the value + is finite but larger or smaller than the largest or smallest finite + value representable by f32**. This is a bug and will be fixed. diff --git a/checked-uninit.md b/checked-uninit.md new file mode 100644 index 000000000000..e39a329bfd29 --- /dev/null +++ b/checked-uninit.md @@ -0,0 +1,109 @@ +% Checked Uninitialized Memory + +Like C, all stack variables in Rust are uninitialized until a +value is explicitly assigned to them. Unlike C, Rust statically prevents you +from ever reading them until you do: + +```rust +fn main() { + let x: i32; + println!("{}", x); +} +``` + +```text +src/main.rs:3:20: 3:21 error: use of possibly uninitialized variable: `x` +src/main.rs:3 println!("{}", x); + ^ +``` + +This is based off of a basic branch analysis: every branch must assign a value +to `x` before it is first used. Interestingly, Rust doesn't require the variable +to be mutable to perform a delayed initialization if every branch assigns +exactly once. However the analysis does not take advantage of constant analysis +or anything like that. So this compiles: + +```rust +fn main() { + let x: i32; + + if true { + x = 1; + } else { + x = 2; + } + + println!("{}", x); +} +``` + +but this doesn't: + +```rust +fn main() { + let x: i32; + if true { + x = 1; + } + println!("{}", x); +} +``` + +```text +src/main.rs:6:17: 6:18 error: use of possibly uninitialized variable: `x` +src/main.rs:6 println!("{}", x); +``` + +while this does: + +```rust +fn main() { + let x: i32; + if true { + x = 1; + println!("{}", x); + } + // Don't care that there are branches where it's not initialized + // since we don't use the value in those branches +} +``` + +If a value is moved out of a variable, that variable becomes logically +uninitialized if the type of the value isn't Copy. That is: + +```rust +fn main() { + let x = 0; + let y = Box::new(0); + let z1 = x; // x is still valid because i32 is Copy + let z2 = y; // y is now logically uninitialized because Box isn't Copy +} +``` + +However reassigning `y` in this example *would* require `y` to be marked as +mutable, as a Safe Rust program could observe that the value of `y` changed. +Otherwise the variable is exactly like new. + +This raises an interesting question with respect to `Drop`: where does Rust try +to call the destructor of a variable that is conditionally initialized? It turns +out that Rust actually tracks whether a type should be dropped or not *at +runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for +that variable is set and unset. When a variable goes out of scope or is assigned +a value, it evaluates whether the current value of the variable should be dropped. +Of course, static analysis can remove these checks. If the compiler can prove that +a value is guaranteed to be either initialized or not, then it can theoretically +generate more efficient code! As such it may be desirable to structure code to +have *static drop semantics* when possible. + +As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden +field of any type that implements Drop. The language sets the drop flag by +overwriting the entire struct with a particular value. This is pretty obviously +Not The Fastest and causes a bunch of trouble with optimizing code. As such work +is currently under way to move the flags out onto the stack frame where they +more reasonably belong. Unfortunately this work will take some time as it +requires fairly substantial changes to the compiler. + +So in general, Rust programs don't need to worry about uninitialized values on +the stack for correctness. Although they might care for performance. Thankfully, +Rust makes it easy to take control here! Uninitialized values are there, and +Safe Rust lets you work with them, but you're never in danger. diff --git a/coercions.md b/coercions.md new file mode 100644 index 000000000000..fad9b09c3c38 --- /dev/null +++ b/coercions.md @@ -0,0 +1,72 @@ +% Coercions + +Types can implicitly be coerced to change in certain contexts. These changes are +generally just *weakening* of types, largely focused around pointers and lifetimes. +They mostly exist to make Rust "just work" in more cases, and are largely harmless. + +Here's all the kinds of coercion: + + +Coercion is allowed between the following types: + +* Subtyping: `T` to `U` if `T` is a [subtype](lifetimes.html#subtyping-and-variance) + of `U` +* Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` +* Pointer Weakening: + * `&mut T` to `&T` + * `*mut T` to `*const T` + * `&T` to `*const T` + * `&mut T` to `*mut T` +* Unsizing: `T` to `U` if `T` implements `CoerceUnsized` + +`CoerceUnsized> for Pointer where T: Unsize` is implemented +for all pointer types (including smart pointers like Box and Rc). Unsize is +only implemented automatically, and enables the following transformations: + +* `[T, ..n]` => `[T]` +* `T` => `Trait` where `T: Trait` +* `SubTrait` => `Trait` where `SubTrait: Trait` (TODO: is this now implied by the previous?) +* `Foo<..., T, ...>` => `Foo<..., U, ...>` where: + * `T: Unsize` + * `Foo` is a struct + * Only the last field has type `T` + * `T` is not part of the type of any other fields + +Coercions occur at a *coercion site*. Any location that is explicitly typed +will cause a coercion to its type. If inference is necessary, the coercion will +not be performed. Exhaustively, the coercion sites for an expression `e` to +type `U` are: + +* let statements, statics, and consts: `let x: U = e` +* Arguments to functions: `takes_a_U(e)` +* Any expression that will be returned: `fn foo() -> U { e }` +* Struct literals: `Foo { some_u: e }` +* Array literals: `let x: [U; 10] = [e, ..]` +* Tuple literals: `let x: (U, ..) = (e, ..)` +* The last expression in a block: `let x: U = { ..; e }` + +Note that we do not perform coercions when matching traits (except for +receivers, see below). If there is an impl for some type `U` and `T` coerces to +`U`, that does not constitute an implementation for `T`. For example, the +following will not type check, even though it is OK to coerce `t` to `&T` and +there is an impl for `&T`: + +```rust +trait Trait {} + +fn foo(t: X) {} + +impl<'a> Trait for &'a i32 {} + + +fn main() { + let t: &mut i32 = &mut 0; + foo(t); +} +``` + +```text +:10:5: 10:8 error: the trait `Trait` is not implemented for the type `&mut i32` [E0277] +:10 foo(t); + ^~~ +``` diff --git a/constructors.md b/constructors.md new file mode 100644 index 000000000000..8069776c0aaf --- /dev/null +++ b/constructors.md @@ -0,0 +1,26 @@ +% Constructors + +Unlike C++, Rust does not come with a slew of builtin +kinds of constructor. There are no Copy, Default, Assignment, Move, or whatever constructors. +This largely has to do with Rust's philosophy of being explicit. + +Move constructors are meaningless in Rust because we don't enable types to "care" about their +location in memory. Every type must be ready for it to be blindly memcopied to somewhere else +in memory. This means pure on-the-stack-but-still-movable intrusive linked lists are simply +not happening in Rust (safely). + +Assignment and copy constructors similarly don't exist because move semantics are the *default* +in rust. At most `x = y` just moves the bits of y into the x variable. Rust does provide two +facilities for going back to C++'s copy-oriented semantics: `Copy` and `Clone`. Clone is our +moral equivalent of a copy constructor, but it's never implicitly invoked. You have to explicitly +call `clone` on an element you want to be cloned. Copy is a special case of Clone where the +implementation is just "copy the bits". Copy types *are* implicitly +cloned whenever they're moved, but because of the definition of Copy this just means *not* +treating the old copy as uninitialized -- a no-op. + +While Rust provides a `Default` trait for specifying the moral equivalent of a default +constructor, it's incredibly rare for this trait to be used. This is because variables +[aren't implicitly initialized][uninit]. Default is basically only useful for generic +programming. In concrete contexts, a type will provide a static `new` method for any +kind of "default" constructor. This has no relation to `new` in other +languages and has no special meaning. It's just a naming convention. \ No newline at end of file diff --git a/conversions.md b/conversions.md index 25d849dfbc18..388516fc7e9e 100644 --- a/conversions.md +++ b/conversions.md @@ -29,188 +29,3 @@ fn reinterpret(foo: Foo) -> Bar { But this is, at best, annoying to do. For common conversions, rust provides more ergonomic alternatives. - - - -# Coercions - -Types can implicitly be coerced to change in certain contexts. These changes are -generally just *weakening* of types, largely focused around pointers and lifetimes. -They mostly exist to make Rust "just work" in more cases, and are largely harmless. - -Here's all the kinds of coercion: - - -Coercion is allowed between the following types: - -* Subtyping: `T` to `U` if `T` is a [subtype](lifetimes.html#subtyping-and-variance) - of `U` -* Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` -* Pointer Weakening: - * `&mut T` to `&T` - * `*mut T` to `*const T` - * `&T` to `*const T` - * `&mut T` to `*mut T` -* Unsizing: `T` to `U` if `T` implements `CoerceUnsized` - -`CoerceUnsized> for Pointer where T: Unsize` is implemented -for all pointer types (including smart pointers like Box and Rc). Unsize is -only implemented automatically, and enables the following transformations: - -* `[T, ..n]` => `[T]` -* `T` => `Trait` where `T: Trait` -* `SubTrait` => `Trait` where `SubTrait: Trait` (TODO: is this now implied by the previous?) -* `Foo<..., T, ...>` => `Foo<..., U, ...>` where: - * `T: Unsize` - * `Foo` is a struct - * Only the last field has type `T` - * `T` is not part of the type of any other fields - -Coercions occur at a *coercion site*. Any location that is explicitly typed -will cause a coercion to its type. If inference is necessary, the coercion will -not be performed. Exhaustively, the coercion sites for an expression `e` to -type `U` are: - -* let statements, statics, and consts: `let x: U = e` -* Arguments to functions: `takes_a_U(e)` -* Any expression that will be returned: `fn foo() -> U { e }` -* Struct literals: `Foo { some_u: e }` -* Array literals: `let x: [U; 10] = [e, ..]` -* Tuple literals: `let x: (U, ..) = (e, ..)` -* The last expression in a block: `let x: U = { ..; e }` - -Note that we do not perform coercions when matching traits (except for -receivers, see below). If there is an impl for some type `U` and `T` coerces to -`U`, that does not constitute an implementation for `T`. For example, the -following will not type check, even though it is OK to coerce `t` to `&T` and -there is an impl for `&T`: - -```rust -trait Trait {} - -fn foo(t: X) {} - -impl<'a> Trait for &'a i32 {} - - -fn main() { - let t: &mut i32 = &mut 0; - foo(t); -} -``` - -```text -:10:5: 10:8 error: the trait `Trait` is not implemented for the type `&mut i32` [E0277] -:10 foo(t); - ^~~ -``` - - - - -# The Dot Operator - -The dot operator will perform a lot of magic to convert types. It will perform -auto-referencing, auto-dereferencing, and coercion until types match. - -TODO: steal information from http://stackoverflow.com/questions/28519997/what-are-rusts-exact-auto-dereferencing-rules/28552082#28552082 - - - - -# Casts - -Casts are a superset of coercions: every coercion can be explicitly invoked via a -cast, but some conversions *require* a cast. These "true casts" are generally regarded -as dangerous or problematic actions. True casts revolve around raw pointers and -the primitive numeric types. True casts aren't checked. - -Here's an exhaustive list of all the true casts. For brevity, we will use `*` -to denote either a `*const` or `*mut`, and `integer` to denote any integral primitive: - - * `*T as *U` where `T, U: Sized` - * `*T as *U` TODO: explain unsized situation - * `*T as integer` - * `integer as *T` - * `number as number` - * `C-like-enum as integer` - * `bool as integer` - * `char as integer` - * `u8 as char` - * `&[T; n] as *const T` - * `fn as *T` where `T: Sized` - * `fn as integer` - -where `&.T` and `*T` are references of either mutability, -and where unsize_kind(`T`) is the kind of the unsize info -in `T` - the vtable for a trait definition (e.g. `fmt::Display` or -`Iterator`, not `Iterator`) or a length (or `()` if `T: Sized`). - -Note that lengths are not adjusted when casting raw slices - -`T: *const [u16] as *const [u8]` creates a slice that only includes -half of the original memory. - -Casting is not transitive, that is, even if `e as U1 as U2` is a valid -expression, `e as U2` is not necessarily so (in fact it will only be valid if -`U1` coerces to `U2`). - -For numeric casts, there are quite a few cases to consider: - -* casting between two integers of the same size (e.g. i32 -> u32) is a no-op -* casting from a larger integer to a smaller integer (e.g. u32 -> u8) will truncate -* casting from a smaller integer to a larger integer (e.g. u8 -> u32) will - * zero-extend if the source is unsigned - * sign-extend if the source is signed -* casting from a float to an integer will round the float towards zero - * **NOTE: currently this will cause Undefined Behaviour if the rounded - value cannot be represented by the target integer type**. This is a bug - and will be fixed. (TODO: figure out what Inf and NaN do) -* casting from an integer to float will produce the floating point representation - of the integer, rounded if necessary (rounding strategy unspecified). -* casting from an f32 to an f64 is perfect and lossless. -* casting from an f64 to an f32 will produce the closest possible value - (rounding strategy unspecified). - * **NOTE: currently this will cause Undefined Behaviour if the value - is finite but larger or smaller than the largest or smallest finite - value representable by f32**. This is a bug and will be fixed. - - - - - -# Conversion Traits - -TODO? - - - - -# Transmuting Types - -Get out of our way type system! We're going to reinterpret these bits or die -trying! Even though this book is all about doing things that are unsafe, I really -can't emphasize that you should deeply think about finding Another Way than the -operations covered in this section. This is really, truly, the most horribly -unsafe thing you can do in Rust. The railguards here are dental floss. - -`mem::transmute` takes a value of type `T` and reinterprets it to have -type `U`. The only restriction is that the `T` and `U` are verified to have the -same size. The ways to cause Undefined Behaviour with this are mind boggling. - -* First and foremost, creating an instance of *any* type with an invalid state - is going to cause arbitrary chaos that can't really be predicted. -* Transmute has an overloaded return type. If you do not specify the return type - it may produce a surprising type to satisfy inference. -* Making a primitive with an invalid value is UB -* Transmuting between non-repr(C) types is UB -* Transmuting an & to &mut is UB -* Transmuting to a reference without an explicitly provided lifetime - produces an [unbound lifetime](lifetimes.html#unbounded-lifetimes) - -`mem::transmute_copy` somehow manages to be *even more* wildly unsafe than -this. It copies `size_of` bytes out of an `&T` and interprets them as a `U`. -The size check that `mem::transmute` has is gone (as it may be valid to copy -out a prefix), though it is Undefined Behaviour for `U` to be larger than `T`. - -Also of course you can get most of the functionality of these functions using -pointer casts. diff --git a/data.md b/data.md index 599415bfe4b9..88d169c3709a 100644 --- a/data.md +++ b/data.md @@ -3,295 +3,3 @@ Low-level programming cares a lot about data layout. It's a big deal. It also pervasively influences the rest of the language, so we're going to start by digging into how data is represented in Rust. - - - - -# The Rust repr - -Rust gives you the following ways to lay out composite data: - -* structs (named product types) -* tuples (anonymous product types) -* arrays (homogeneous product types) -* enums (named sum types -- tagged unions) - -An enum is said to be *C-like* if none of its variants have associated data. - -For all these, individual fields are aligned to their preferred alignment. For -primitives this is usually equal to their size. For instance, a u32 will be -aligned to a multiple of 32 bits, and a u16 will be aligned to a multiple of 16 -bits. Composite structures will have a preferred alignment equal to the maximum -of their fields' preferred alignment, and a size equal to a multiple of their -preferred alignment. This ensures that arrays of T can be correctly iterated -by offsetting by their size. So for instance, - -```rust -struct A { - a: u8, - c: u32, - b: u16, -} -``` - -will have a size that is a multiple of 32-bits, and 32-bit alignment. - -There is *no indirection* for these types; all data is stored contiguously as you would -expect in C. However with the exception of arrays (which are densely packed and -in-order), the layout of data is not by default specified in Rust. Given the two -following struct definitions: - -```rust -struct A { - a: i32, - b: u64, -} - -struct B { - x: i32, - b: u64, -} -``` - -Rust *does* guarantee that two instances of A have their data laid out in exactly -the same way. However Rust *does not* guarantee that an instance of A has the same -field ordering or padding as an instance of B (in practice there's no *particular* -reason why they wouldn't, other than that its not currently guaranteed). - -With A and B as written, this is basically nonsensical, but several other features -of Rust make it desirable for the language to play with data layout in complex ways. - -For instance, consider this struct: - -```rust -struct Foo { - count: u16, - data1: T, - data2: U, -} -``` - -Now consider the monomorphizations of `Foo` and `Foo`. If Rust lays out the -fields in the order specified, we expect it to *pad* the values in the struct to satisfy -their *alignment* requirements. So if Rust didn't reorder fields, we would expect Rust to -produce the following: - -```rust -struct Foo { - count: u16, - data1: u16, - data2: u32, -} - -struct Foo { - count: u16, - _pad1: u16, - data1: u32, - data2: u16, - _pad2: u16, -} -``` - -The latter case quite simply wastes space. An optimal use of space therefore requires -different monomorphizations to have *different field orderings*. - -**Note: this is a hypothetical optimization that is not yet implemented in Rust 1.0** - -Enums make this consideration even more complicated. Naively, an enum such as: - -```rust -enum Foo { - A(u32), - B(u64), - C(u8), -} -``` - -would be laid out as: - -```rust -struct FooRepr { - data: u64, // this is *really* either a u64, u32, or u8 based on `tag` - tag: u8, // 0 = A, 1 = B, 2 = C -} -``` - -And indeed this is approximately how it would be laid out in general -(modulo the size and position of `tag`). However there are several cases where -such a representation is ineffiecient. The classic case of this is Rust's -"null pointer optimization". Given a pointer that is known to not be null -(e.g. `&u32`), an enum can *store* a discriminant bit *inside* the pointer -by using null as a special value. The net result is that -`size_of::>() == size_of::<&T>()` - -There are many types in Rust that are, or contain, "not null" pointers such as -`Box`, `Vec`, `String`, `&T`, and `&mut T`. Similarly, one can imagine -nested enums pooling their tags into a single descriminant, as they are by -definition known to have a limited range of valid values. In principle enums can -use fairly elaborate algorithms to cache bits throughout nested types with -special constrained representations. As such it is *especially* desirable that -we leave enum layout unspecified today. - - - - -# Dynamically Sized Types (DSTs) - -Rust also supports types without a statically known size. On the surface, -this is a bit nonsensical: Rust *must* know the size of something in order to -work with it! DSTs are generally produced as views, or through type-erasure -of types that *do* have a known size. Due to their lack of a statically known -size, these types can only exist *behind* some kind of pointer. They consequently -produce a *fat* pointer consisting of the pointer and the information that -*completes* them. - -For instance, the slice type, `[T]`, is some statically unknown number of elements -stored contiguously. `&[T]` consequently consists of a `(&T, usize)` pair that specifies -where the slice starts, and how many elements it contains. Similarly, Trait Objects -support interface-oriented type erasure through a `(data_ptr, vtable_ptr)` pair. - -Structs can actually store a single DST directly as their last field, but this -makes them a DST as well: - -```rust -// Can't be stored on the stack directly -struct Foo { - info: u32, - data: [u8], -} -``` - -**NOTE: As of Rust 1.0 struct DSTs are broken if the last field has -a variable position based on its alignment.** - - - -# Zero Sized Types (ZSTs) - -Rust actually allows types to be specified that occupy *no* space: - -```rust -struct Foo; // No fields = no size -enum Bar; // No variants = no size - -// All fields have no size = no size -struct Baz { - foo: Foo, - bar: Bar, - qux: (), // empty tuple has no size -} -``` - -On their own, ZSTs are, for obvious reasons, pretty useless. However -as with many curious layout choices in Rust, their potential is realized in a generic -context. - -Rust largely understands that any operation that produces or stores a ZST -can be reduced to a no-op. For instance, a `HashSet` can be effeciently implemented -as a thin wrapper around `HashMap` because all the operations `HashMap` normally -does to store and retrieve keys will be completely stripped in monomorphization. - -Similarly `Result<(), ()>` and `Option<()>` are effectively just fancy `bool`s. - -Safe code need not worry about ZSTs, but *unsafe* code must be careful about the -consequence of types with no size. In particular, pointer offsets are no-ops, and -standard allocators (including jemalloc, the one used by Rust) generally consider -passing in `0` as Undefined Behaviour. - - - - -# Drop Flags - -For unfortunate legacy implementation reasons, Rust as of 1.0.0 will do a nasty trick to -any type that implements the `Drop` trait (has a destructor): it will insert a secret field -in the type. That is, - -```rust -struct Foo { - a: u32, - b: u32, -} - -impl Drop for Foo { - fn drop(&mut self) { } -} -``` - -will cause Foo to secretly become: - -```rust -struct Foo { - a: u32, - b: u32, - _drop_flag: u8, -} -``` - -For details as to *why* this is done, and how to make it not happen, check out -[TODO: SOME OTHER SECTION]. - - - - -# Alternative representations - -Rust allows you to specify alternative data layout strategies from the default. - - - - -## repr(C) - -This is the most important `repr`. It has fairly simple intent: do what C does. -The order, size, and alignment of fields is exactly what you would expect from -C or C++. Any type you expect to pass through an FFI boundary should have `repr(C)`, -as C is the lingua-franca of the programming world. This is also necessary -to soundly do more elaborate tricks with data layout such as reintepretting values -as a different type. - -However, the interaction with Rust's more exotic data layout features must be kept -in mind. Due to its dual purpose as "for FFI" and "for layout control", `repr(C)` -can be applied to types that will be nonsensical or problematic if passed through -the FFI boundary. - -* ZSTs are still zero-sized, even though this is not a standard behaviour - in C, and is explicitly contrary to the behaviour of an empty type in C++, which - still consumes a byte of space. - -* DSTs, tuples, and tagged unions are not a concept in C and as such are never - FFI safe. - -* **The drop flag will still be added** - -* This is equivalent to `repr(u32)` for enums (see below) - - - - -## repr(packed) - -`repr(packed)` forces rust to strip any padding, and only align the type to a -byte. This may improve the memory footprint, but will likely have other -negative side-effects. - -In particular, most architectures *strongly* prefer values to be aligned. This -may mean the unaligned loads are penalized (x86), or even fault (ARM). In -particular, the compiler may have trouble with references to unaligned fields. - -`repr(packed)` is not to be used lightly. Unless you have extreme requirements, -this should not be used. - -This repr is a modifier on `repr(C)` and `repr(rust)`. - - - - -## repr(u8), repr(u16), repr(u32), repr(u64) - -These specify the size to make a C-like enum. If the discriminant overflows the -integer it has to fit in, it will be an error. You can manually ask Rust to -allow this by setting the overflowing element to explicitly be 0. However Rust -will not allow you to create an enum where two variants. - -These reprs have no affect on a struct or non-C-like enum. diff --git a/destructors.md b/destructors.md new file mode 100644 index 000000000000..3bc75c132bf6 --- /dev/null +++ b/destructors.md @@ -0,0 +1,140 @@ +% Destructors + +What the language *does* provide is full-blown automatic destructors through the `Drop` trait, +which provides the following method: + +```rust +fn drop(&mut self); +``` + +This method gives the type time to somehow finish what it was doing. **After `drop` is run, +Rust will recursively try to drop all of the fields of `self`**. This is a +convenience feature so that you don't have to write "destructor boilerplate" to drop +children. If a struct has no special logic for being dropped other than dropping its +children, then it means `Drop` doesn't need to be implemented at all! + +**There is no stable way to prevent this behaviour in Rust 1.0**. + +Note that taking `&mut self` means that even if you *could* suppress recursive Drop, +Rust will prevent you from e.g. moving fields out of self. For most types, this +is totally fine. + +For instance, a custom implementation of `Box` might write `Drop` like this: + +```rust +struct Box{ ptr: *mut T } + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + (*self.ptr).drop(); + heap::deallocate(self.ptr); + } + } +} +``` + +and this works fine because when Rust goes to drop the `ptr` field it just sees a *mut that +has no actual `Drop` implementation. Similarly nothing can use-after-free the `ptr` because +the Box is immediately marked as uninitialized. + +However this wouldn't work: + +```rust +struct Box{ ptr: *mut T } + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + (*self.ptr).drop(); + heap::deallocate(self.ptr); + } + } +} + +struct SuperBox { box: Box } + +impl Drop for SuperBox { + fn drop(&mut self) { + unsafe { + // Hyper-optimized: deallocate the box's contents for it + // without `drop`ing the contents + heap::deallocate(self.box.ptr); + } + } +} +``` + +After we deallocate the `box`'s ptr in SuperBox's destructor, Rust will +happily proceed to tell the box to Drop itself and everything will blow up with +use-after-frees and double-frees. + +Note that the recursive drop behaviour applies to *all* structs and enums +regardless of whether they implement Drop. Therefore something like + +```rust +struct Boxy { + data1: Box, + data2: Box, + info: u32, +} +``` + +will have its data1 and data2's fields destructors whenever it "would" be +dropped, even though it itself doesn't implement Drop. We say that such a type +*needs Drop*, even though it is not itself Drop. + +Similarly, + +```rust +enum Link { + Next(Box), + None, +} +``` + +will have its inner Box field dropped *if and only if* an instance stores the Next variant. + +In general this works really nice because you don't need to worry about adding/removing +drops when you refactor your data layout. Still there's certainly many valid usecases for +needing to do trickier things with destructors. + +The classic safe solution to overriding recursive drop and allowing moving out +of Self during `drop` is to use an Option: + +```rust +struct Box{ ptr: *mut T } + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + (*self.ptr).drop(); + heap::deallocate(self.ptr); + } + } +} + +struct SuperBox { box: Option> } + +impl Drop for SuperBox { + fn drop(&mut self) { + unsafe { + // Hyper-optimized: deallocate the box's contents for it + // without `drop`ing the contents. Need to set the `box` + // field as `None` to prevent Rust from trying to Drop it. + heap::deallocate(self.box.take().unwrap().ptr); + } + } +} +``` + +However this has fairly odd semantics: you're saying that a field that *should* always +be Some may be None, just because that happens in the destructor. Of course this +conversely makes a lot of sense: you can call arbitrary methods on self during +the destructor, and this should prevent you from ever doing so after deinitializing +the field. Not that it will prevent you from producing any other +arbitrarily invalid state in there. + +On balance this is an ok choice. Certainly what you should reach for by default. +However, in the future we expect there to be a first-class way to announce that +a field shouldn't be automatically dropped. \ No newline at end of file diff --git a/dot-operator.md b/dot-operator.md new file mode 100644 index 000000000000..5d2010d15a80 --- /dev/null +++ b/dot-operator.md @@ -0,0 +1,6 @@ +% The Dot Operator + +The dot operator will perform a lot of magic to convert types. It will perform +auto-referencing, auto-dereferencing, and coercion until types match. + +TODO: steal information from http://stackoverflow.com/questions/28519997/what-are-rusts-exact-auto-dereferencing-rules/28552082#28552082 diff --git a/exotic-sizes.md b/exotic-sizes.md new file mode 100644 index 000000000000..8e05485055f7 --- /dev/null +++ b/exotic-sizes.md @@ -0,0 +1,69 @@ +% Exotically Sized Types + +Most of the time, we think in terms of types with a fixed, positive size. This +is not always the case, however. + +# Dynamically Sized Types (DSTs) + +Rust also supports types without a statically known size. On the surface, +this is a bit nonsensical: Rust *must* know the size of something in order to +work with it! DSTs are generally produced as views, or through type-erasure +of types that *do* have a known size. Due to their lack of a statically known +size, these types can only exist *behind* some kind of pointer. They consequently +produce a *fat* pointer consisting of the pointer and the information that +*completes* them. + +For instance, the slice type, `[T]`, is some statically unknown number of elements +stored contiguously. `&[T]` consequently consists of a `(&T, usize)` pair that specifies +where the slice starts, and how many elements it contains. Similarly, Trait Objects +support interface-oriented type erasure through a `(data_ptr, vtable_ptr)` pair. + +Structs can actually store a single DST directly as their last field, but this +makes them a DST as well: + +```rust +// Can't be stored on the stack directly +struct Foo { + info: u32, + data: [u8], +} +``` + +**NOTE: As of Rust 1.0 struct DSTs are broken if the last field has +a variable position based on its alignment.** + + + +# Zero Sized Types (ZSTs) + +Rust actually allows types to be specified that occupy *no* space: + +```rust +struct Foo; // No fields = no size +enum Bar; // No variants = no size + +// All fields have no size = no size +struct Baz { + foo: Foo, + bar: Bar, + qux: (), // empty tuple has no size +} +``` + +On their own, ZSTs are, for obvious reasons, pretty useless. However +as with many curious layout choices in Rust, their potential is realized in a generic +context. + +Rust largely understands that any operation that produces or stores a ZST +can be reduced to a no-op. For instance, a `HashSet` can be effeciently implemented +as a thin wrapper around `HashMap` because all the operations `HashMap` normally +does to store and retrieve keys will be completely stripped in monomorphization. + +Similarly `Result<(), ()>` and `Option<()>` are effectively just fancy `bool`s. + +Safe code need not worry about ZSTs, but *unsafe* code must be careful about the +consequence of types with no size. In particular, pointer offsets are no-ops, and +standard allocators (including jemalloc, the one used by Rust) generally consider +passing in `0` as Undefined Behaviour. + + diff --git a/hrtb.md b/hrtb.md new file mode 100644 index 000000000000..c3f25026ef48 --- /dev/null +++ b/hrtb.md @@ -0,0 +1,72 @@ +% Higher-Rank Trait Bounds (HRTBs) + +Rust's Fn traits are a little bit magic. For instance, we can write the +following code: + +```rust +struct Closure { + data: (u8, u16), + func: F, +} + +impl Closure + where F: Fn(&(u8, u16)) -> &u8, +{ + fn call(&self) -> &u8 { + (self.func)(&self.data) + } +} + +fn do_it(data: &(u8, u16)) -> &u8 { &data.0 } + +fn main() { + let clo = Closure { data: (0, 1), func: do_it }; + println!("{}", clo.call()); +} +``` + +If we try to naively desugar this code in the same way that we did in the +lifetimes section, we run into some trouble: + +```rust +struct Closure { + data: (u8, u16), + func: F, +} + +impl Closure + // where F: Fn(&'??? (u8, u16)) -> &'??? u8, +{ + fn call<'a>(&'a self) -> &'a u8 { + (self.func)(&self.data) + } +} + +fn do_it<'b>(data: &'b (u8, u16)) -> &'b u8 { &'b data.0 } + +fn main() { + 'x: { + let clo = Closure { data: (0, 1), func: do_it }; + println!("{}", clo.call()); + } +} +``` + +How on earth are we supposed to express the lifetimes on F's trait bound? We need +to provide some lifetime there, but the lifetime we care about can't be named until +we enter the body of `call`! Also, that isn't some fixed lifetime; call works with +*any* lifetime `&self` happens to have at that point. + +This job requires The Magic of Higher-Rank Trait Bounds. The way we desugar +this is as follows: + +```rust +where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, +``` + +(Where `Fn(a, b, c) -> d` is itself just sugar for the unstable *real* Fn trait) + +`for<'a>` can be read as "for all choices of `'a`", and basically produces an +*inifinite list* of trait bounds that F must satisfy. Intense. There aren't many +places outside of the Fn traits where we encounter HRTBs, and even for those we +have a nice magic sugar for the common cases. \ No newline at end of file diff --git a/leaking.md b/leaking.md new file mode 100644 index 000000000000..5d66b1a424c4 --- /dev/null +++ b/leaking.md @@ -0,0 +1,229 @@ +% Leaking + +Ownership based resource management is intended to simplify composition. You +acquire resources when you create the object, and you release the resources +when it gets destroyed. Since destruction is handled for you, it means you +can't forget to release the resources, and it happens as soon as possible! +Surely this is perfect and all of our problems are solved. + +Everything is terrible and we have new and exotic problems to try to solve. + +Many people like to believe that Rust eliminates resource leaks, but this +is absolutely not the case, no matter how you look at it. In the strictest +sense, "leaking" is so abstract as to be unpreventable. It's quite trivial +to initialize a collection at the start of a program, fill it with tons of +objects with destructors, and then enter an infinite event loop that never +refers to it. The collection will sit around uselessly, holding on to its +precious resources until the program terminates (at which point all those +resources would have been reclaimed by the OS anyway). + +We may consider a more restricted form of leak: failing to drop a value that +is unreachable. Rust also doesn't prevent this. In fact Rust has a *function +for doing this*: `mem::forget`. This function consumes the value it is passed +*and then doesn't run its destructor*. + +In the past `mem::forget` was marked as unsafe as a sort of lint against using +it, since failing to call a destructor is generally not a well-behaved thing to +do (though useful for some special unsafe code). However this was generally +determined to be an untenable stance to take: there are *many* ways to fail to +call a destructor in safe code. The most famous example is creating a cycle +of reference counted pointers using interior mutability. + +It is reasonable for safe code to assume that destructor leaks do not happen, +as any program that leaks destructors is probably wrong. However *unsafe* code +cannot rely on destructors to be run to be *safe*. For most types this doesn't +matter: if you leak the destructor then the type is *by definition* inaccessible, +so it doesn't matter, right? For instance, if you leak a `Box` then you +waste some memory but that's hardly going to violate memory-safety. + +However where we must be careful with destructor leaks are *proxy* types. +These are types which manage access to a distinct object, but don't actually +own it. Proxy objects are quite rare. Proxy objects you'll need to care about +are even rarer. However we'll focus on three interesting examples in the +standard library: + +* `vec::Drain` +* `Rc` +* `thread::scoped::JoinGuard` + + + +## Drain + +`drain` is a collections API that moves data out of the container without +consuming the container. This enables us to reuse the allocation of a `Vec` +after claiming ownership over all of its contents. It produces an iterator +(Drain) that returns the contents of the Vec by-value. + +Now, consider Drain in the middle of iteration: some values have been moved out, +and others haven't. This means that part of the Vec is now full of logically +uninitialized data! We could backshift all the elements in the Vec every time we +remove a value, but this would have pretty catastrophic performance consequences. + +Instead, we would like Drain to *fix* the Vec's backing storage when it is +dropped. It should run itself to completion, backshift any elements that weren't +removed (drain supports subranges), and then fix Vec's `len`. It's even +unwinding-safe! Easy! + +Now consider the following: + +``` +let mut vec = vec![Box::new(0); 4]; + +{ + // start draining, vec can no longer be accessed + let mut drainer = vec.drain(..); + + // pull out two elements and immediately drop them + drainer.next(); + drainer.next(); + + // get rid of drainer, but don't call its destructor + mem::forget(drainer); +} + +// Oops, vec[0] was dropped, we're reading a pointer into free'd memory! +println!("{}", vec[0]); +``` + +This is pretty clearly Not Good. Unfortunately, we're kind've stuck between +a rock and a hard place: maintaining consistent state at every step has +an enormous cost (and would negate any benefits of the API). Failing to maintain +consistent state gives us Undefined Behaviour in safe code (making the API +unsound). + +So what can we do? Well, we can pick a trivially consistent state: set the Vec's +len to be 0 when we *start* the iteration, and fix it up if necessary in the +destructor. That way, if everything executes like normal we get the desired +behaviour with minimal overhead. But if someone has the *audacity* to mem::forget +us in the middle of the iteration, all that does is *leak even more* (and possibly +leave the Vec in an *unexpected* but consistent state). Since we've +accepted that mem::forget is safe, this is definitely safe. We call leaks causing +more leaks a *leak amplification*. + + + + +## Rc + +Rc is an interesting case because at first glance it doesn't appear to be a +proxy value at all. After all, it manages the data it points to, and dropping +all the Rcs for a value will drop that value. leaking an Rc doesn't seem like +it would be particularly dangerous. It will leave the refcount permanently +incremented and prevent the data from being freed or dropped, but that seems +just like Box, right? + +Nope. + +Let's consider a simplified implementation of Rc: + +```rust +struct Rc { + ptr: *mut RcBox, +} + +struct RcBox { + data: T, + ref_count: usize, +} + +impl Rc { + fn new(data: T) -> Self { + unsafe { + // Wouldn't it be nice if heap::allocate worked like this? + let ptr = heap::allocate>(); + ptr::write(ptr, RcBox { + data: data, + ref_count: 1, + }); + Rc { ptr: ptr } + } + } + + fn clone(&self) -> Self { + unsafe { + (*self.ptr).ref_count += 1; + } + Rc { ptr: self.ptr } + } +} + +impl Drop for Rc { + fn drop(&mut self) { + unsafe { + let inner = &mut ; + (*self.ptr).ref_count -= 1; + if (*self.ptr).ref_count == 0 { + // drop the data and then free it + ptr::read(self.ptr); + heap::deallocate(self.ptr); + } + } + } +} +``` + +This code contains an implicit and subtle assumption: ref_count can fit in a +`usize`, because there can't be more than `usize::MAX` Rcs in memory. However +this itself assumes that the ref_count accurately reflects the number of Rcs +in memory, which we know is false with mem::forget. Using mem::forget we can +overflow the ref_count, and then get it down to 0 with outstanding Rcs. Then we +can happily use-after-free the inner data. Bad Bad Not Good. + +This can be solved by *saturating* the ref_count, which is sound because +decreasing the refcount by `n` still requires `n` Rcs simultaneously living +in memory. + + + + +## thread::scoped::JoinGuard + +The thread::scoped API intends to allow threads to be spawned that reference +data on the stack without any synchronization over that data. Usage looked like: + +```rust +let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +{ + let guards = vec![]; + for x in &mut data { + // Move the mutable reference into the closure, and execute + // it on a different thread. The closure has a lifetime bound + // by the lifetime of the mutable reference `x` we store in it. + // The guard that is returned is in turn assigned the lifetime + // of the closure, so it also mutably borrows `data` as `x` did. + // This means we cannot access `data` until the guard goes away. + let guard = thread::scoped(move || { + *x *= 2; + }); + // store the thread's guard for later + guards.push(guard); + } + // All guards are dropped here, forcing the threads to join + // (this thread blocks here until the others terminate). + // Once the threads join, the borrow expires and the data becomes + // accessible again in this thread. +} +// data is definitely mutated here. +``` + +In principle, this totally works! Rust's ownership system perfectly ensures it! +...except it relies on a destructor being called to be safe. + +``` +let mut data = Box::new(0); +{ + let guard = thread::scoped(|| { + // This is at best a data race. At worst, it's *also* a use-after-free. + *data += 1; + }); + // Because the guard is forgotten, expiring the loan without blocking this + // thread. + mem::forget(guard); +} +// So the Box is dropped here while the scoped thread may or may not be trying +// to access it. +``` + +Dang. Here the destructor running was pretty fundamental to the API, and it had +to be scrapped in favour of a completely different design. \ No newline at end of file diff --git a/lifetime-elision.md b/lifetime-elision.md new file mode 100644 index 000000000000..eac24330911f --- /dev/null +++ b/lifetime-elision.md @@ -0,0 +1,64 @@ +% Lifetime Elision + +In order to make common patterns more ergonomic, Rust allows lifetimes to be +*elided* in function signatures. + +A *lifetime position* is anywhere you can write a lifetime in a type: + +```rust +&'a T +&'a mut T +T<'a> +``` + +Lifetime positions can appear as either "input" or "output": + +* For `fn` definitions, input refers to the types of the formal arguments + in the `fn` definition, while output refers to + result types. So `fn foo(s: &str) -> (&str, &str)` has elided one lifetime in + input position and two lifetimes in output position. + Note that the input positions of a `fn` method definition do not + include the lifetimes that occur in the method's `impl` header + (nor lifetimes that occur in the trait header, for a default method). + +* In the future, it should be possible to elide `impl` headers in the same manner. + +Elision rules are as follows: + +* Each elided lifetime in input position becomes a distinct lifetime + parameter. + +* If there is exactly one input lifetime position (elided or not), that lifetime + is assigned to *all* elided output lifetimes. + +* If there are multiple input lifetime positions, but one of them is `&self` or + `&mut self`, the lifetime of `self` is assigned to *all* elided output lifetimes. + +* Otherwise, it is an error to elide an output lifetime. + +Examples: + +```rust +fn print(s: &str); // elided +fn print<'a>(s: &'a str); // expanded + +fn debug(lvl: uint, s: &str); // elided +fn debug<'a>(lvl: uint, s: &'a str); // expanded + +fn substr(s: &str, until: uint) -> &str; // elided +fn substr<'a>(s: &'a str, until: uint) -> &'a str; // expanded + +fn get_str() -> &str; // ILLEGAL + +fn frob(s: &str, t: &str) -> &str; // ILLEGAL + +fn get_mut(&mut self) -> &mut T; // elided +fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded + +fn args(&mut self, args: &[T]) -> &mut Command // elided +fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded + +fn new(buf: &mut [u8]) -> BufWriter; // elided +fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded + +``` \ No newline at end of file diff --git a/lifetime-misc.md b/lifetime-misc.md new file mode 100644 index 000000000000..faf7f9a1f60b --- /dev/null +++ b/lifetime-misc.md @@ -0,0 +1,229 @@ +% misc + +This is just a dumping ground while I work out what to do with this stuff + + +# PhantomData + +When working with unsafe code, we can often end up in a situation where +types or lifetimes are logically associated with a struct, but not actually +part of a field. This most commonly occurs with lifetimes. For instance, the `Iter` +for `&'a [T]` is (approximately) defined as follows: + +```rust +pub struct Iter<'a, T: 'a> { + ptr: *const T, + end: *const T, +} +``` + +However because `'a` is unused within the struct's body, it's *unbound*. +Because of the troubles this has historically caused, unbound lifetimes and +types are *illegal* in struct definitions. Therefore we must somehow refer +to these types in the body. Correctly doing this is necessary to have +correct variance and drop checking. + +We do this using *PhantomData*, which is a special marker type. PhantomData +consumes no space, but simulates a field of the given type for the purpose of +static analysis. This was deemed to be less error-prone than explicitly telling +the type-system the kind of variance that you want, while also providing other +useful information. + +Iter logically contains `&'a T`, so this is exactly what we tell +the PhantomData to simulate: + +``` +pub struct Iter<'a, T: 'a> { + ptr: *const T, + end: *const T, + _marker: marker::PhantomData<&'a T>, +} +``` + + + + +# Dropck + +When a type is going out of scope, Rust will try to Drop it. Drop executes +arbitrary code, and in fact allows us to "smuggle" arbitrary code execution +into many places. As such additional soundness checks (dropck) are necessary to +ensure that a type T can be safely instantiated and dropped. It turns out that we +*really* don't need to care about dropck in practice, as it often "just works". + +However the one exception is with PhantomData. Given a struct like Vec: + +``` +struct Vec { + data: *const T, // *const for variance! + len: usize, + cap: usize, +} +``` + +dropck will generously determine that Vec does not own any values of +type T. This will unfortunately allow people to construct unsound Drop +implementations that access data that has already been dropped. In order to +tell dropck that we *do* own values of type T, and may call destructors of that +type, we must add extra PhantomData: + +``` +struct Vec { + data: *const T, // *const for covariance! + len: usize, + cap: usize, + _marker: marker::PhantomData, +} +``` + +Raw pointers that own an allocation is such a pervasive pattern that the +standard library made a utility for itself called `Unique` which: + +* wraps a `*const T`, +* includes a `PhantomData`, +* auto-derives Send/Sync as if T was contained +* marks the pointer as NonZero for the null-pointer optimization + + + + +# Splitting Lifetimes + +The mutual exclusion property of mutable references can be very limiting when +working with a composite structure. The borrow checker understands some basic stuff, but +will fall over pretty easily. It *does* understand structs sufficiently to +know that it's possible to borrow disjoint fields of a struct simultaneously. +So this works today: + +```rust +struct Foo { + a: i32, + b: i32, + c: i32, +} + +let mut x = Foo {a: 0, b: 0, c: 0}; +let a = &mut x.a; +let b = &mut x.b; +let c = &x.c; +*b += 1; +let c2 = &x.c; +*a += 10; +println!("{} {} {} {}", a, b, c, c2); +``` + +However borrowck doesn't understand arrays or slices in any way, so this doesn't +work: + +```rust +let x = [1, 2, 3]; +let a = &mut x[0]; +let b = &mut x[1]; +println!("{} {}", a, b); +``` + +```text +:3:18: 3:22 error: cannot borrow immutable indexed content `x[..]` as mutable +:3 let a = &mut x[0]; + ^~~~ +:4:18: 4:22 error: cannot borrow immutable indexed content `x[..]` as mutable +:4 let b = &mut x[1]; + ^~~~ +error: aborting due to 2 previous errors +``` + +While it was plausible that borrowck could understand this simple case, it's +pretty clearly hopeless for borrowck to understand disjointness in general +container types like a tree, especially if distinct keys actually *do* map +to the same value. + +In order to "teach" borrowck that what we're doing is ok, we need to drop down +to unsafe code. For instance, mutable slices expose a `split_at_mut` function that +consumes the slice and returns *two* mutable slices. One for everything to the +left of the index, and one for everything to the right. Intuitively we know this +is safe because the slices don't alias. However the implementation requires some +unsafety: + +```rust +fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + unsafe { + let self2: &mut [T] = mem::transmute_copy(&self); + + (ops::IndexMut::index_mut(self, ops::RangeTo { end: mid } ), + ops::IndexMut::index_mut(self2, ops::RangeFrom { start: mid } )) + } +} +``` + +This is pretty plainly dangerous. We use transmute to duplicate the slice with an +*unbounded* lifetime, so that it can be treated as disjoint from the other until +we unify them when we return. + +However more subtle is how iterators that yield mutable references work. +The iterator trait is defined as follows: + +```rust +trait Iterator { + type Item; + + fn next(&mut self) -> Option; +} +``` + +Given this definition, Self::Item has *no* connection to `self`. This means +that we can call `next` several times in a row, and hold onto all the results +*concurrently*. This is perfectly fine for by-value iterators, which have exactly +these semantics. It's also actually fine for shared references, as they admit +arbitrarily many references to the same thing (although the +iterator needs to be a separate object from the thing being shared). But mutable +references make this a mess. At first glance, they might seem completely +incompatible with this API, as it would produce multiple mutable references to +the same object! + +However it actually *does* work, exactly because iterators are one-shot objects. +Everything an IterMut yields will be yielded *at most* once, so we don't *actually* +ever yield multiple mutable references to the same piece of data. + +In general all mutable iterators require *some* unsafe code *somewhere*, though. +Whether it's raw pointers, or safely composing on top of *another* IterMut. + +For instance, VecDeque's IterMut: + +```rust +pub struct IterMut<'a, T:'a> { + // The whole backing array. Some of these indices are initialized! + ring: &'a mut [T], + tail: usize, + head: usize, +} + +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + fn next(&mut self) -> Option<&'a mut T> { + if self.tail == self.head { + return None; + } + let tail = self.tail; + self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); + + unsafe { + // might as well do unchecked indexing since wrap_index has us + // in-bounds, and many of the "middle" indices are uninitialized + // anyway. + let elem = self.ring.get_unchecked_mut(tail); + + // round-trip through a raw pointer to unbound the lifetime from + // ourselves + Some(&mut *(elem as *mut _)) + } + } +} +``` + +A very subtle but interesting detail in this design is that it *relies on +privacy to be sound*. Borrowck works on some very simple rules. One of those rules +is that if we have a live &mut Foo and Foo contains an &mut Bar, then that &mut +Bar is *also* live. Since IterMut is always live when `next` can be called, if +`ring` were public then we could mutate `ring` while outstanding mutable borrows +to it exist! diff --git a/lifetime-mismatch.md b/lifetime-mismatch.md new file mode 100644 index 000000000000..93ecb51c010d --- /dev/null +++ b/lifetime-mismatch.md @@ -0,0 +1,81 @@ +% Limits of Lifetimes + +Given the following code: + +```rust,ignore +struct Foo; + +impl Foo { + fn mutate_and_share(&mut self) -> &Self { &*self } + fn share(&self) {} +} + +fn main() { + let mut foo = Foo; + let loan = foo.mutate_and_share(); + foo.share(); +} +``` + +One might expect it to compile. We call `mutate_and_share`, which mutably borrows +`foo` *temporarily*, but then returns *only* a shared reference. Therefore we +would expect `foo.share()` to succeed as `foo` shouldn't be mutably borrowed. + +However when we try to compile it: + +```text +:11:5: 11:8 error: cannot borrow `foo` as immutable because it is also borrowed as mutable +:11 foo.share(); + ^~~ +:10:16: 10:19 note: previous borrow of `foo` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foo` until the borrow ends +:10 let loan = foo.mutate_and_share(); + ^~~ +:12:2: 12:2 note: previous borrow ends here +:8 fn main() { +:9 let mut foo = Foo; +:10 let loan = foo.mutate_and_share(); +:11 foo.share(); +:12 } + ^ +``` + +What happened? Well, we got the exact same reasoning as we did for +[Example 2 in the previous section][ex2]. We desugar the program and we get +the following: + +```rust,ignore +struct Foo; + +impl Foo { + fn mutate_and_share<'a>(&'a mut self) -> &'a Self { &'a *self } + fn share<'a>(&'a self) {} +} + +fn main() { + 'b: { + let mut foo: Foo = Foo; + 'c: { + let loan: &'c Foo = Foo::mutate_and_share::<'c>(&'c mut foo); + 'd: { + Foo::share::<'d>(&'d foo); + } + } + } +} +``` + +The lifetime system is forced to extend the `&mut foo` to have lifetime `'c`, +due to the lifetime of `loan` and mutate_and_share's signature. Then when we +try to call `share`, and it sees we're trying to alias that `&'c mut foo` and +blows up in our face! + +This program is clearly correct according to the reference semantics we *actually* +care about, but the lifetime system is too coarse-grained to handle that. + + +TODO: other common problems? SEME regions stuff, mostly? + + + + +[ex2]: lifetimes.html#example-2:-aliasing-a-mutable-reference \ No newline at end of file diff --git a/lifetimes.md b/lifetimes.md index 976b4d53e2c9..a06363a92d73 100644 --- a/lifetimes.md +++ b/lifetimes.md @@ -1,230 +1,17 @@ -% Ownership and Lifetimes - -Ownership is the breakout feature of Rust. It allows Rust to be completely -memory-safe and efficient, while avoiding garbage collection. Before getting -into the ownership system in detail, we will consider the motivation of this -design. - -TODO: Interior Mutability section - - - - -# Living Without Garbage Collection - -We will assume that you accept that garbage collection is not always an optimal -solution, and that it is desirable to manually manage memory to some extent. -If you do not accept this, might I interest you in a different language? - -Regardless of your feelings on GC, it is pretty clearly a *massive* boon to -making code safe. You never have to worry about things going away *too soon* -(although whether you still *wanted* to be pointing at that thing is a different -issue...). This is a pervasive problem that C and C++ need to deal with. -Consider this simple mistake that all of us who have used a non-GC'd language -have made at one point: - -```rust,ignore -fn as_str(data: &u32) -> &str { - // compute the string - let s = format!("{}", data); - - // OH NO! We returned a reference to something that - // exists only in this function! - // Dangling pointer! Use after free! Alas! - // (this does not compile in Rust) - &s -} -``` - -This is exactly what Rust's ownership system was built to solve. -Rust knows the scope in which the `&s` lives, and as such can prevent it from -escaping. However this is a simple case that even a C compiler could plausibly -catch. Things get more complicated as code gets bigger and pointers get fed through -various functions. Eventually, a C compiler will fall down and won't be able to -perform sufficient escape analysis to prove your code unsound. It will consequently -be forced to accept your program on the assumption that it is correct. - -This will never happen to Rust. It's up to the programmer to prove to the -compiler that everything is sound. - -Of course, rust's story around ownership is much more complicated than just -verifying that references don't escape the scope of their referrent. That's -because ensuring pointers are always valid is much more complicated than this. -For instance in this code, - -```rust,ignore -let mut data = vec![1, 2, 3]; -// get an internal reference -let x = &data[0]; - -// OH NO! `push` causes the backing storage of `data` to be reallocated. -// Dangling pointer! User after free! Alas! -// (this does not compile in Rust) -data.push(4); - -println!("{}", x); -``` - -naive scope analysis would be insufficient to prevent this bug, because `data` -does in fact live as long as we needed. However it was *changed* while we had -a reference into it. This is why Rust requires any references to freeze the -referrent and its owners. - - - -# References - -There are two kinds of reference: - -* Shared reference: `&` -* Mutable reference: `&mut` - -Which obey the following rules: - -* A reference cannot outlive its referrent -* A mutable reference cannot be aliased - -To define aliasing, we must define the notion of *paths* and *liveness*. - - - - -## Paths - -If all Rust had were values, then every value would be uniquely owned -by a variable or composite structure. From this we naturally derive a *tree* -of ownership. The stack itself is the root of the tree, with every variable -as its direct children. Each variable's direct children would be their fields -(if any), and so on. - -From this view, every value in Rust has a unique *path* in the tree of ownership. -References to a value can subsequently be interpretted as a path in this tree. -Of particular interest are *prefixes*: `x` is a prefix of `y` if `x` owns `y` - -However much data doesn't reside on the stack, and we must also accomodate this. -Globals and thread-locals are simple enough to model as residing at the bottom -of the stack. However data on the heap poses a different problem. - -If all Rust had on the heap was data uniquely by a pointer on the stack, -then we can just treat that pointer as a struct that owns the value on -the heap. Box, Vec, String, and HashMap, are examples of types which uniquely -own data on the heap. - -Unfortunately, data on the heap is not *always* uniquely owned. Rc for instance -introduces a notion of *shared* ownership. Shared ownership means there is no -unique path. A value with no unique path limits what we can do with it. In general, only -shared references can be created to these values. However mechanisms which ensure -mutual exclusion may establish One True Owner temporarily, establishing a unique path -to that value (and therefore all its children). - -The most common way to establish such a path is through *interior mutability*, -in contrast to the *inherited mutability* that everything in Rust normally uses. -Cell, RefCell, Mutex, and RWLock are all examples of interior mutability types. These -types provide exclusive access through runtime restrictions. However it is also -possible to establish unique ownership without interior mutability. For instance, -if an Rc has refcount 1, then it is safe to mutate or move its internals. - - - - -## Liveness - -Roughly, a reference is *live* at some point in a program if it can be -dereferenced. Shared references are always live unless they are literally unreachable -(for instance, they reside in freed or leaked memory). Mutable references can be -reachable but *not* live through the process of *reborrowing*. - -A mutable reference can be reborrowed to either a shared or mutable reference. -Further, the reborrow can produce exactly the same reference, or point to a -path it is a prefix of. For instance, a mutable reference can be reborrowed -to point to a field of its referrent: - -```rust -let x = &mut (1, 2); -{ - // reborrow x to a subfield - let y = &mut x.0; - // y is now live, but x isn't - *y = 3; -} -// y goes out of scope, so x is live again -*x = (5, 7); -``` - -It is also possible to reborrow into *multiple* mutable references, as long as -they are to *disjoint*: no reference is a prefix of another. Rust -explicitly enables this to be done with disjoint struct fields, because -disjointness can be statically proven: - -``` -let x = &mut (1, 2); -{ - // reborrow x to two disjoint subfields - let y = &mut x.0; - let z = &mut x.1; - // y and z are now live, but x isn't - *y = 3; - *z = 4; -} -// y and z go out of scope, so x is live again -*x = (5, 7); -``` - -However it's often the case that Rust isn't sufficiently smart to prove that -multiple borrows are disjoint. *This does not mean it is fundamentally illegal -to make such a borrow*, just that Rust isn't as smart as you want. - -To simplify things, we can model variables as a fake type of reference: *owned* -references. Owned references have much the same semantics as mutable references: -they can be re-borrowed in a mutable or shared manner, which makes them no longer -live. Live owned references have the unique property that they can be moved -out of (though mutable references *can* be swapped out of). This is -only given to *live* owned references because moving its referrent would of -course invalidate all outstanding references prematurely. - -As a local lint against inappropriate mutation, only variables that are marked -as `mut` can be borrowed mutably. - -It is also interesting to note that Box behaves exactly like an owned -reference. It can be moved out of, and Rust understands it sufficiently to -reason about its paths like a normal variable. - - - - -## Aliasing - -With liveness and paths defined, we can now properly define *aliasing*: - -**A mutable reference is aliased if there exists another live reference to it or -one of its prefixes.** - -That's it. Super simple right? Except for the fact that it took us two pages -to define all of the terms in that defintion. You know: Super. Simple. - -Actually it's a bit more complicated than that. In addition to references, -Rust has *raw pointers*: `*const T` and `*mut T`. Raw pointers have no inherent -ownership or aliasing semantics. As a result, Rust makes absolutely no effort -to track that they are used correctly, and they are wildly unsafe. - -**It is an open question to what degree raw pointers have alias semantics. -However it is important for these definitions to be sound that the existence -of a raw pointer does not imply some kind of live path.** - - - - -# Lifetimes +% Lifetimes Rust enforces these rules through *lifetimes*. Lifetimes are effectively -just names for scopes on the stack, somewhere in the program. Each reference, +just names for scopes somewhere in the program. Each reference, and anything that contains a reference, is tagged with a lifetime specifying the scope it's valid for. Within a function body, Rust generally doesn't let you explicitly name the lifetimes involved. This is because it's generally not really *necessary* to talk about lifetimes in a local context; rust has all the information and -can work out everything. +can work out everything. It's also a good thing because the scope of a borrow +is often significantly smaller than the scope its referent is *actually* valid +for. Rust will introduce *many* anonymous scopes and temporaries to make your +code *just work*. However once you cross the function boundary, you need to start talking about lifetimes. Lifetimes are denoted with an apostrophe: `'a`, `'static`. To dip @@ -232,9 +19,10 @@ our toes with lifetimes, we're going to pretend that we're actually allowed to label scopes with lifetimes, and desugar the examples from the start of this chapter. -Our examples made use of *aggressive* sugar around scopes and lifetimes, -because writing everything out explicitly is *extremely noisy*. All rust code -relies on aggressive inference and elision of "obvious" things. +Our examples made use of *aggressive* sugar -- high fructose corn syrup even -- +around scopes and lifetimes, because writing everything out explicitly is +*extremely noisy*. All Rust code relies on aggressive inference and elision of +"obvious" things. One particularly interesting piece of sugar is that each `let` statement implicitly introduces a scope. For the most part, this doesn't really matter. However it @@ -247,25 +35,61 @@ let y = &x; let z = &y; ``` -becomes: +The borrow checker always tries to minimize the extent of a lifetime, so it will +likely desugar to the following: -```rust,ignore -// NOTE: `'a:` and `&'a x` is not valid syntax! +```rust +// NOTE: `'a: {` and `&'b x` is not valid syntax! 'a: { let x: i32 = 0; 'b: { - let y: &'a i32 = &'a x; + // lifetime used is 'b because that's *good enough*. + let y: &'b i32 = &'b x; 'c: { - let z: &'b &'a i32 = &'b y; + // ditto on 'c + let z: &'c &'b i32 = &'c y; } } } ``` -Wow. That's... awful. Let's all take a moment to thank Rust for being a huge -pile of sugar with sugar on top. +Wow. That's... awful. Let's all take a moment to thank Rust for being a +diabetes-inducing torrent of syrupy-goodness. -Anyway, let's look at some of those examples from before: +Actually passing references to outer scopes will cause Rust to infer +a larger lifetime: + +```rust +let x = 0; +let z; +let y = &x; +z = y; +``` + +The borrow checker always tries to minimize the extent of a lifetime, so it will +likely desugar to something like the following: + +```rust +// NOTE: `'a: {` and `&'b x` is not valid syntax! +'a: { + let x: i32 = 0; + 'b: { + let z: &'b i32; + 'c: { + // Must use 'b here because this reference is + // being passed to that scope. + let y: &'b i32 = &'b x; + z = y; + } + } +} +``` + + + +# Example: references that outlive referents + +Alright, let's look at some of those examples from before: ```rust,ignore fn as_str(data: &u32) -> &str { @@ -280,7 +104,7 @@ desugars to: fn as_str<'a>(data: &'a u32) -> &'a str { 'b: { let s = format!("{}", data); - return &'b s + return &'a s; } } ``` @@ -288,19 +112,45 @@ fn as_str<'a>(data: &'a u32) -> &'a str { This signature of `as_str` takes a reference to a u32 with *some* lifetime, and promises that it can produce a reference to a str that can live *just as long*. Already we can see why this signature might be trouble. That basically implies -that we're going to *find* a str somewhere in the scope that u32 originated in, -or somewhere *even* earlier. That's uh... a big ask. +that we're going to *find* a str somewhere in the scope the scope the reference +to the u32 originated in, or somewhere *even* earlier. That's a *bit* of a big ask. -We then proceed to compute the string `s`, and return a reference to it. -Unfortunately, since `s` was defined in the scope `'b`, the reference we're -returning can only live for that long. From the perspective of the compiler, -we've failed *twice* here. We've failed to fulfill the contract we were asked -to fulfill (`'b` is unrelated to `'a`); and we've also tried to make a reference -outlive its referrent by returning an `&'b`, where `'b` is in our function. +We then proceed to compute the string `s`, and return a reference to it. Since +the contract of our function says the reference must outlive `'a`, that's the +lifetime we infer for the reference. Unfortunately, `s` was defined in the +scope `'b`, so the only way this is sound is if `'b` contains `'a` -- which is +clearly false since `'a` must contain the function call itself. We have therefore +created a reference whose lifetime outlives its referent, which is *literally* +the first thing we said that references can't do. The compiler rightfully blows +up in our face. + +To make this more clear, we can expand the example: + +```rust,ignore +fn as_str<'a>(data: &'a u32) -> &'a str { + 'b: { + let s = format!("{}", data); + return &'a s + } +} + +fn main() { + 'c: { + let x: u32 = 0; + 'd: { + // An anonymous scope is introduced because the borrow does not + // need to last for the whole scope x is valid for. The return + // of as_str must find a str somewhere *before* this function + // call. Obviously not happening. + println!("{}", as_str::<'d>(&'d temp)); + } + } +} +``` Shoot! -Of course, the right way to right this function is as follows: +Of course, the right way to write this function is as follows: ```rust fn to_string(data: &u32) -> String { @@ -312,680 +162,61 @@ We must produce an owned value inside the function to return it! The only way we could have returned an `&'a str` would have been if it was in a field of the `&'a u32`, which is obviously not the case. -(Actually we could have also just returned a string literal, though this limits -the behaviour of our function *just a bit*.) +(Actually we could have also just returned a string literal, which as a global +can be considered to reside at the bottom of the stack; though this limits +our implementation *just a bit*.) + + + + + +# Example 2: aliasing a mutable reference How about the other example: -```rust,ignore +```rust let mut data = vec![1, 2, 3]; let x = &data[0]; data.push(4); println!("{}", x); ``` -```rust,ignore +```rust 'a: { let mut data: Vec = vec![1, 2, 3]; 'b: { - let x: &'a i32 = Index::index(&'a data, 0); + // 'b is as big as we need this borrow to be + // (just need to get to `println!`) + let x: &'b i32 = Index::index::<'b>(&'b data, 0); 'c: { - // Exactly what the desugar for Vec::push is is up to Rust. - // This particular desugar is a decent approximation for our - // purpose. In particular methods oft invoke a temporary borrow. - let temp: &'c mut Vec = &'c mut data; + // Temporary scope because we don't need the + // &mut to last any longer. + // NOTE: Vec::push is not valid syntax - Vec::push(temp, 4); + Vec::push(&'c mut data, 4); } println!("{}", x); } } ``` -Here the problem is that we're trying to mutably borrow the `data` path, while -we have a reference into something it's a prefix of. Rust subsequently throws -up its hands in disgust and rejects our program. The correct way to write this -is to just re-order the code so that we make `x` *after* we push: - -TODO: convince myself of this. - -```rust -let mut data = vec![1, 2, 3]; -data.push(4); - -let x = &data[0]; -println!("{}", x); -``` - - - -# Lifetime Elision - -In order to make common patterns more ergonomic, Rust allows lifetimes to be -*elided* in function signatures. - -A *lifetime position* is anywhere you can write a lifetime in a type: - -```rust -&'a T -&'a mut T -T<'a> -``` - -Lifetime positions can appear as either "input" or "output": - -* For `fn` definitions, input refers to the types of the formal arguments - in the `fn` definition, while output refers to - result types. So `fn foo(s: &str) -> (&str, &str)` has elided one lifetime in - input position and two lifetimes in output position. - Note that the input positions of a `fn` method definition do not - include the lifetimes that occur in the method's `impl` header - (nor lifetimes that occur in the trait header, for a default method). - -* In the future, it should be possible to elide `impl` headers in the same manner. - -Elision rules are as follows: - -* Each elided lifetime in input position becomes a distinct lifetime - parameter. - -* If there is exactly one input lifetime position (elided or not), that lifetime - is assigned to *all* elided output lifetimes. - -* If there are multiple input lifetime positions, but one of them is `&self` or - `&mut self`, the lifetime of `self` is assigned to *all* elided output lifetimes. - -* Otherwise, it is an error to elide an output lifetime. - -Examples: - -```rust -fn print(s: &str); // elided -fn print<'a>(s: &'a str); // expanded - -fn debug(lvl: uint, s: &str); // elided -fn debug<'a>(lvl: uint, s: &'a str); // expanded - -fn substr(s: &str, until: uint) -> &str; // elided -fn substr<'a>(s: &'a str, until: uint) -> &'a str; // expanded - -fn get_str() -> &str; // ILLEGAL - -fn frob(s: &str, t: &str) -> &str; // ILLEGAL - -fn get_mut(&mut self) -> &mut T; // elided -fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded - -fn args(&mut self, args: &[T]) -> &mut Command // elided -fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded - -fn new(buf: &mut [u8]) -> BufWriter; // elided -fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded - -``` - - - -# Unbounded Lifetimes - -Unsafe code can often end up producing references or lifetimes out of thin air. -Such lifetimes come into the world as *unbounded*. The most common source of this -is derefencing a raw pointer, which produces a reference with an unbounded lifetime. -Such a lifetime becomes as big as context demands. This is in fact more powerful -than simply becoming `'static`, because for instance `&'static &'a T` -will fail to typecheck, but the unbound lifetime will perfectly mold into -`&'a &'a T` as needed. However for most intents and purposes, such an unbounded -lifetime can be regarded as `'static`. - -Almost no reference is `'static`, so this is probably wrong. `transmute` and -`transmute_copy` are the two other primary offenders. One should endeavour to -bound an unbounded lifetime as quick as possible, especially across function -boundaries. - -Given a function, any output lifetimes that don't derive from inputs are -unbounded. For instance: - -``` -fn get_str<'a>() -> &'a str; -``` - -will produce an `&str` with an unbounded lifetime. The easiest way to avoid -unbounded lifetimes is to use lifetime elision at the function boundary. -If an output lifetime is elided, then it *must* be bounded by an input lifetime. -Of course, it might be bounded by the *wrong* lifetime, but this will usually -just cause a compiler error, rather than allow memory safety to be trivially -violated. - -Within a function, bounding lifetimes is more error-prone. The safest and easiest -way to bound a lifetime is to return it from a function with a bound lifetime. -However if this is unacceptable, the reference can be placed in a location with -a specific lifetime. Unfortunately it's impossible to name all lifetimes involved -in a function. To get around this, you can in principle use `copy_lifetime`, though -these are unstable due to their awkward nature and questionable utility. - - - - - -# Higher-Rank Trait Bounds - -// TODO: make aturon less mad - -Generics in Rust generally allow types to be instantiated with arbitrary -associated lifetimes, but this fixes the lifetimes they work with once -instantiated. For almost all types, this is exactly the desired behaviour. -For example slice::Iter can work with arbitrary lifetimes, determined by the -slice that instantiates it. However *once* Iter is instantiated the lifetimes -it works with cannot be changed. It returns references that live for some -particular `'a`. - -However some types are more flexible than this. In particular, a single -instantiation of a function can process arbitrary lifetimes: - -```rust -fn identity(input: &u8) -> &u8 { input } -``` - -What is *the* lifetime that identity works with? There is none. If you think -this is "cheating" because functions are statically instantiated, then you need -only consider the equivalent closure: - -```rust -let identity = |input: &u8| input; -``` - -These functions are *higher ranked* over the lifetimes they work with. This means -that they're generic over what they handle *after instantiation*. For most things -this would pose a massive problem, but because lifetimes don't *exist* at runtime, -this is really just a compile-time mechanism. The Fn traits contain sugar that -allows higher-rank lifetimes to simply be expressed by simply omitting lifetimes: - - -```rust -fn main() { - foo(|input| input); -} - -fn foo(f: F) - // F is higher-ranked over the lifetime these references have - where F: Fn(&u8) -> &u8 -{ - f(&0); - f(&1); -} -``` - -The desugaring of this is actually unstable: - -``` -#![feature(unboxed_closures)] - -fn main() { - foo(|input| input); -} - -fn foo(f: F) - where F: for<'a> Fn<(&'a u8,), Output=&'a u8> -{ - f(&0); - f(&1); -} -``` - -`for<'a>` is how we declare a higher-ranked lifetime. Unfortunately higher-ranked -lifetimes are still fairly new, and are missing a few features to make them -maximally useful outside of the Fn traits. - - - - -# Subtyping and Variance - -Although Rust doesn't have any notion of inheritance, it *does* include subtyping. -In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes are derived -from scopes, we can partially order them based on an *outlives* relationship. We -can even express this as a generic bound: `T: 'a` specifies that `T` *outlives* `'a`. - -We can then define subtyping on lifetimes in terms of lifetimes: if `'a : 'b` -("a outlives b"), then `'a` is a subtype of `b`. This is a -large source of confusion, because a bigger scope is a *sub type* of a smaller scope. -This does in fact make sense. The intuitive reason for this is that if you expect an -`&'a u8`, then it's totally fine for me to hand you an `&'static u8` in the same way -that if you expect an Animal in Java, it's totally fine for me to hand you a Cat. - -(Note, the subtyping relationship and typed-ness of lifetimes is a fairly arbitrary -construct that some disagree with. I just find that it simplifies this analysis.) - -TODO: higher rank lifetime subtyping - -Variance is where things get really harsh. - -Variance is a property that *type constructors* have. A type constructor in Rust -is a generic type with unbound arguments. For instance `Vec` is a type constructor -that takes a `T` and returns a `Vec`. `&` and `&mut` are type constructors that -take a lifetime and a type. - -A type constructor's *variance* is how the subtypes of its inputs affects the -subtypes of its outputs. There are three kinds of variance: - -* F is *variant* if `T` being a subtype of `U` implies `F` is a subtype of `F` -* F is *invariant* otherwise (no subtyping relation can be derived) - -(For those of you who are familiar with variance from other languages, what we refer -to as "just" variant is in fact *covariant*. Rust does not have contravariance. -Historically Rust did have some contravariance but it was scrapped due to poor -interactions with other features.) - -Some important variances: - -* `&` is variant (as is *const by metaphor) -* `&mut` is invariant (as is *mut by metaphor) -* `Fn(T) -> U` is invariant with respect to `T`, but variant with respect to `U` -* `Box`, `Vec`, and all other collections are variant -* `UnsafeCell`, `Cell`, `RefCell`, `Mutex` and all "interior mutability" - types are invariant - -To understand why these variances are correct and desirable, we will consider several -examples. We have already covered why `&` should be variant when introducing subtyping: -it's desirable to be able to pass longer-lived things where shorter-lived things are -needed. - -To see why `&mut` should be invariant, consider the following code: - -```rust -fn main() { - let mut forever_str: &'static str = "hello"; - { - let string = String::from("world"); - overwrite(&mut forever_str, &mut &*string); - } - println!("{}", forever_str); -} - -fn overwrite(input: &mut T, new: &mut T) { - *input = *new; -} -``` - -The signature of `overwrite` is clearly valid: it takes mutable references to two values -of the same type, and replaces one with the other. We have seen already that `&` is -variant, and `'static` is a subtype of *any* `'a`, so `&'static str` is a -subtype of `&'a str`. Therefore, if `&mut` was -*also* variant, then the lifetime of the `&'static str` would successfully be -"shrunk" down to the shorter lifetime of the string, and `replace` would be -called successfully. The string would subsequently be dropped, and `forever_str` -would point to freed memory when we print it! - -Therefore `&mut` should be invariant. This is the general theme of variance vs -invariance: if variance would allow you to *store* a short-lived value in a -longer-lived slot, then you must be invariant. - -`Box` and `Vec` are interesting cases because they're variant, but you can -definitely store values in them! This is fine because *you can only store values -in them through a mutable reference*! The mutable reference makes the whole type -invariant, and therefore prevents you from getting in trouble. - -Being variant allows them to be variant when shared immutably (so you can pass -a `&Box<&'static str>` where a `&Box<&'a str>` is expected). It also allows you to -forever weaken the type by moving it into a weaker slot. That is, you can do: - -```rust -fn get_box<'a>(&'a u8) -> Box<&'a str> { - // string literals are `&'static str`s - Box::new("hello") -} -``` - -which is fine because unlike the mutable borrow case, there's no one else who -"remembers" the old lifetime in the box. - -The variance of the cell types similarly follows. `&` is like an `&mut` for a -cell, because you can still store values in them through an `&`. Therefore cells -must be invariant to avoid lifetime smuggling. - -`Fn` is the most subtle case, because it has mixed variance. To see why -`Fn(T) -> U` should be invariant over T, consider the following function -signature: - -```rust -// 'a is derived from some parent scope -fn foo(&'a str) -> usize; -``` - -This signature claims that it can handle any &str that lives *at least* as long -as `'a`. Now if this signature was variant with respect to &str, that would mean - -```rust -fn foo(&'static str) -> usize; -``` - -could be provided in its place, as it would be a subtype. However this function -has a *stronger* requirement: it says that it can *only* handle `&'static str`s, -and nothing else. Therefore functions are not variant over their arguments. - -To see why `Fn(T) -> U` should be *variant* over U, consider the following -function signature: - -```rust -// 'a is derived from some parent scope -fn foo(usize) -> &'a str; -``` - -This signature claims that it will return something that outlives `'a`. It is -therefore completely reasonable to provide - -```rust -fn foo(usize) -> &'static str; -``` - -in its place. Therefore functions *are* variant over their return type. - -`*const` has the exact same semantics as &, so variance follows. `*mut` on the -other hand can dereference to an &mut whether shared or not, so it is marked -as invariant in analogy to cells. - -This is all well and good for the types the standard library provides, but -how is variance determined for type that *you* define? A struct, informally -speaking, inherits the variance of its fields. If a struct `Foo` -has a generic argument `A` that is used in a field `a`, then Foo's variance -over `A` is exactly `a`'s variance. However this is complicated if `A` is used -in multiple fields. - -* If all uses of A are variant, then Foo is variant over A -* Otherwise, Foo is invariant over A - -```rust -struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { - a: &'a A, // variant over 'a and A - b: &'b mut B, // invariant over 'b and B - c: *const C, // variant over C - d: *mut D, // invariant over D - e: Vec, // variant over E - f: Cell, // invariant over F - g: G // variant over G - h1: H // would also be variant over H except... - h2: Cell // invariant over H, because invariance wins -} -``` - - - -# PhantomData - -When working with unsafe code, we can often end up in a situation where -types or lifetimes are logically associated with a struct, but not actually -part of a field. This most commonly occurs with lifetimes. For instance, the `Iter` -for `&'a [T]` is (approximately) defined as follows: - -``` -pub struct Iter<'a, T: 'a> { - ptr: *const T, - end: *const T, -} -``` - -However because `'a` is unused within the struct's body, it's *unbound*. -Because of the troubles this has historically caused, unbound lifetimes and -types are *illegal* in struct definitions. Therefore we must somehow refer -to these types in the body. Correctly doing this is necessary to have -correct variance and drop checking. - -We do this using *PhantomData*, which is a special marker type. PhantomData -consumes no space, but simulates a field of the given type for the purpose of -static analysis. This was deemed to be less error-prone than explicitly telling -the type-system the kind of variance that you want, while also providing other -useful information. - -Iter logically contains `&'a T`, so this is exactly what we tell -the PhantomData to simulate: - -``` -pub struct Iter<'a, T: 'a> { - ptr: *const T, - end: *const T, - _marker: marker::PhantomData<&'a T>, -} -``` - - - - -# Dropck - -When a type is going out of scope, Rust will try to Drop it. Drop executes -arbitrary code, and in fact allows us to "smuggle" arbitrary code execution -into many places. As such additional soundness checks (dropck) are necessary to -ensure that a type T can be safely instantiated and dropped. It turns out that we -*really* don't need to care about dropck in practice, as it often "just works". - -However the one exception is with PhantomData. Given a struct like Vec: - -``` -struct Vec { - data: *const T, // *const for variance! - len: usize, - cap: usize, -} -``` - -dropck will generously determine that Vec does not own any values of -type T. This will unfortunately allow people to construct unsound Drop -implementations that access data that has already been dropped. In order to -tell dropck that we *do* own values of type T, and may call destructors of that -type, we must add extra PhantomData: - -``` -struct Vec { - data: *const T, // *const for covariance! - len: usize, - cap: usize, - _marker: marker::PhantomData, -} -``` - -Raw pointers that own an allocation is such a pervasive pattern that the -standard library made a utility for itself called `Unique` which: - -* wraps a `*const T`, -* includes a PhantomData, -* auto-derives Send/Sync as if T was contained -* marks the pointer as NonZero for the null-pointer optimization - - - - -# Splitting Lifetimes - -The mutual exclusion property of mutable references can be very limiting when -working with a composite structure. Borrowck understands some basic stuff, but -will fall over pretty easily. Borrowck understands structs sufficiently to -understand that it's possible to borrow disjoint fields of a struct simultaneously. -So this works today: - -```rust -struct Foo { - a: i32, - b: i32, - c: i32, -} - -let mut x = Foo {a: 0, b: 0, c: 0}; -let a = &mut x.a; -let b = &mut x.b; -let c = &x.c; -*b += 1; -let c2 = &x.c; -*a += 10; -println!("{} {} {} {}", a, b, c, c2); -``` - -However borrowck doesn't understand arrays or slices in any way, so this doesn't -work: - -```rust -let x = [1, 2, 3]; -let a = &mut x[0]; -let b = &mut x[1]; -println!("{} {}", a, b); -``` - -```text -:3:18: 3:22 error: cannot borrow immutable indexed content `x[..]` as mutable -:3 let a = &mut x[0]; - ^~~~ -:4:18: 4:22 error: cannot borrow immutable indexed content `x[..]` as mutable -:4 let b = &mut x[1]; - ^~~~ -error: aborting due to 2 previous errors -``` - -While it was plausible that borrowck could understand this simple case, it's -pretty clearly hopeless for borrowck to understand disjointness in general -container types like a tree, especially if distinct keys actually *do* map -to the same value. - -In order to "teach" borrowck that what we're doing is ok, we need to drop down -to unsafe code. For instance, mutable slices expose a `split_at_mut` function that -consumes the slice and returns *two* mutable slices. One for everything to the -left of the index, and one for everything to the right. Intuitively we know this -is safe because the slices don't alias. However the implementation requires some -unsafety: - -```rust -fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { - unsafe { - let self2: &mut [T] = mem::transmute_copy(&self); - - (ops::IndexMut::index_mut(self, ops::RangeTo { end: mid } ), - ops::IndexMut::index_mut(self2, ops::RangeFrom { start: mid } )) - } -} -``` - -This is pretty plainly dangerous. We use transmute to duplicate the slice with an -*unbounded* lifetime, so that it can be treated as disjoint from the other until -we unify them when we return. - -However more subtle is how iterators that yield mutable references work. -The iterator trait is defined as follows: - -```rust -trait Iterator { - type Item; - - fn next(&mut self) -> Option; -} -``` - -Given this definition, Self::Item has *no* connection to `self`. This means -that we can call `next` several times in a row, and hold onto all the results -*concurrently*. This is perfectly fine for by-value iterators, which have exactly -these semantics. It's also actually fine for shared references, as they admit -arbitrarily many references to the same thing (although the -iterator needs to be a separate object from the thing being shared). But mutable -references make this a mess. At first glance, they might seem completely -incompatible with this API, as it would produce multiple mutable references to -the same object! - -However it actually *does* work, exactly because iterators are one-shot objects. -Everything an IterMut yields will be yielded *at most* once, so we don't *actually* -ever yield multiple mutable references to the same piece of data. - -In general all mutable iterators require *some* unsafe code *somewhere*, though. -Whether it's raw pointers, or safely composing on top of *another* IterMut. - -For instance, VecDeque's IterMut: - -```rust -pub struct IterMut<'a, T:'a> { - // The whole backing array. Some of these indices are initialized! - ring: &'a mut [T], - tail: usize, - head: usize, -} - -impl<'a, T> Iterator for IterMut<'a, T> { - type Item = &'a mut T; - - fn next(&mut self) -> Option<&'a mut T> { - if self.tail == self.head { - return None; - } - let tail = self.tail; - self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); - - unsafe { - // might as well do unchecked indexing since wrap_index has us - // in-bounds, and many of the "middle" indices are uninitialized - // anyway. - let elem = self.ring.get_unchecked_mut(tail); - - // round-trip through a raw pointer to unbound the lifetime from - // ourselves - Some(&mut *(elem as *mut _)) - } - } -} -``` - -A very subtle but interesting detail in this design is that it *relies on -privacy to be sound*. Borrowck works on some very simple rules. One of those rules -is that if we have a live &mut Foo and Foo contains an &mut Bar, then that &mut -Bar is *also* live. Since IterMut is always live when `next` can be called, if -`ring` were public then we could mutate `ring` while outstanding mutable borrows -to it exist! - - - - - -# Weird Lifetimes - -Given the following code: - -```rust -struct Foo; - -impl Foo { - fn mutate_and_share(&mut self) -> &Self { &*self } - fn share(&self) {} -} - -fn main() { - let mut foo = Foo; - let loan = foo.mutate_and_share(); - foo.share(); -} -``` - -One might expect it to compile. We call `mutate_and_share`, which mutably borrows -`foo` *temporarily*, but then returns *only* a shared reference. Therefore we -would expect `foo.share()` to succeed as `foo` shouldn't be mutably borrowed. - -However when we try to compile it: - -```text -:11:5: 11:8 error: cannot borrow `foo` as immutable because it is also borrowed as mutable -:11 foo.share(); - ^~~ -:10:16: 10:19 note: previous borrow of `foo` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foo` until the borrow ends -:10 let loan = foo.mutate_and_share(); - ^~~ -:12:2: 12:2 note: previous borrow ends here -:8 fn main() { -:9 let mut foo = Foo; -:10 let loan = foo.mutate_and_share(); -:11 foo.share(); -:12 } - ^ -``` - -What happened? Well, the lifetime of `loan` is derived from a *mutable* borrow. -This makes the type system believe that `foo` is mutably borrowed as long as -`loan` exists, even though it's a shared reference. This isn't a bug, although -one could argue it is a limitation of the design. In particular, to know if -the mutable part of the borrow is *really* expired we'd have to peek into -implementation details of the function. Currently, type-checking a function -does not need to inspect the bodies of any other functions or types. - - +The problem here is is bit more subtle and interesting. We want Rust to +reject this program for the following reason: We have a live shared reference `x` +to a descendent of `data` when try to take a *mutable* reference to `data` +when we call `push`. This would create an aliased mutable reference, which would +violate the *second* rule of references. + +However this is *not at all* how Rust reasons that this program is bad. Rust +doesn't understand that `x` is a reference to a subpath of `data`. It doesn't +understand Vec at all. What it *does* see is that `x` has to live for `'b` to +be printed. The signature of `Index::index` subsequently demands that the +reference we take to *data* has to survive for `'b`. When we try to call `push`, +it then sees us try to make an `&'c mut data`. Rust knows that `'c` is contained +within `'b`, and rejects our program because the `&'b data` must still be live! + +Here we see that the lifetime system is *much* more coarse than the reference +semantics we're actually interested in preserving. For the most part, *that's +totally ok*, because it keeps us from spending all day explaining our program +to the compiler. However it does mean that several programs that are *totally* +correct with respect to Rust's *true* semantics are rejected because lifetimes +are too dumb. \ No newline at end of file diff --git a/meet-safe-and-unsafe.md b/meet-safe-and-unsafe.md new file mode 100644 index 000000000000..e12997f6f246 --- /dev/null +++ b/meet-safe-and-unsafe.md @@ -0,0 +1,82 @@ +% Meet Safe and Unsafe + +Safe and Unsafe are Rust's chief engineers. + +TODO: ADORABLE PICTURES OMG + +Unsafe handles all the dangerous internal stuff. They build the foundations +and handle all the dangerous materials. By all accounts, Unsafe is really a bit +unproductive, because the nature of their work means that they have to spend a +lot of time checking and double-checking everything. What if there's an earthquake +on a leap year? Are we ready for that? Unsafe better be, because if they get +*anything* wrong, everything will blow up! What Unsafe brings to the table is +*quality*, not quantity. Still, nothing would ever get done if everything was +built to Unsafe's standards! + +That's where Safe comes in. Safe has to handle *everything else*. Since Safe needs +to *get work done*, they've grown to be fairly carless and clumsy! Safe doesn't worry +about all the crazy eventualities that Unsafe does, because life is too short to deal +with leap-year-earthquakes. Of course, this means there's some jobs that Safe just +can't handle. Safe is all about quantity over quality. + +Unsafe loves Safe to bits, but knows that tey *can never trust them to do the +right thing*. Still, Unsafe acknowledges that not every problem needs quite the +attention to detail that they apply. Indeed, Unsafe would *love* if Safe could do +*everything* for them. To accomplish this, Unsafe spends most of their time +building *safe abstractions*. These abstractions handle all the nitty-gritty +details for Safe, and choose good defaults so that the simplest solution (which +Safe will inevitably use) is usually the *right* one. Once a safe abstraction is +built, Unsafe ideally needs to never work on it again, and Safe can blindly use +it in all their work. + +Unsafe's attention to detail means that all the things that they mark as ok for +Safe to use can be combined in arbitrarily ridiculous ways, and all the rules +that Unsafe is forced to uphold will never be violated. If they *can* be violated +by Safe, that means *Unsafe*'s the one in the wrong. Safe can work carelessly, +knowing that if anything blows up, it's not *their* fault. Safe can also call in +Unsafe at any time if there's a hard problem they can't quite work out, or if they +can't meet the client's quality demands. Of course, Unsafe will beg and plead Safe +to try their latest safe abstraction first! + +In addition to being adorable, Safe and Unsafe are what makes Rust possible. +Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust. +Any time someone opines the guarantees of Rust, they are almost surely talking about +Safe. However Safe is not sufficient to write every program. For that, +we need the Unsafe superset. + +Most fundamentally, writing bindings to other languages +(such as the C exposed by your operating system) is never going to be safe. Rust +can't control what other languages do to program execution! However Unsafe is +also necessary to construct fundamental abstractions where the type system is not +sufficient to automatically prove what you're doing is sound. + +Indeed, the Rust standard library is implemented in Rust, and it makes substantial +use of Unsafe for implementing IO, memory allocation, collections, +synchronization, and other low-level computational primitives. + +Upon hearing this, many wonder why they would not simply just use C or C++ in place of +Rust (or just use a "real" safe language). If we're going to do unsafe things, why not +lean on these much more established languages? + +The most important difference between C++ and Rust is a matter of defaults: +Rust is 100% safe by default. Even when you *opt out* of safety in Rust, it is a modular +action. In deciding to work with unchecked uninitialized memory, this does not +suddenly make dangling or null pointers a problem. When using unchecked indexing on `x`, +one does not have to suddenly worry about indexing out of bounds on `y`. +C and C++, by contrast, have pervasive unsafety baked into the language. Even the +modern best practices like `unique_ptr` have various safety pitfalls. + +It cannot be emphasized enough that Unsafe should be regarded as an exceptional +thing, not a normal one. Unsafe is often the domain of *fundamental libraries*: anything that needs +to make FFI bindings or define core abstractions. These fundamental libraries then expose +a safe interface for intermediate libraries and applications to build upon. And these +safe interfaces make an important promise: if your application segfaults, it's not your +fault. *They* have a bug. + +And really, how is that different from *any* safe language? Python, Ruby, and Java libraries +can internally do all sorts of nasty things. The languages themselves are no +different. Safe languages *regularly* have bugs that cause critical vulnerabilities. +The fact that Rust is written with a healthy spoonful of Unsafe is no different. +However it *does* mean that Rust doesn't need to fall back to the pervasive unsafety of +C to do the nasty things that need to get done. + diff --git a/other-reprs.md b/other-reprs.md new file mode 100644 index 000000000000..068d30c5e3da --- /dev/null +++ b/other-reprs.md @@ -0,0 +1,61 @@ +% Alternative representations + +Rust allows you to specify alternative data layout strategies from the default. + + + + +# repr(C) + +This is the most important `repr`. It has fairly simple intent: do what C does. +The order, size, and alignment of fields is exactly what you would expect from +C or C++. Any type you expect to pass through an FFI boundary should have `repr(C)`, +as C is the lingua-franca of the programming world. This is also necessary +to soundly do more elaborate tricks with data layout such as reintepretting values +as a different type. + +However, the interaction with Rust's more exotic data layout features must be kept +in mind. Due to its dual purpose as "for FFI" and "for layout control", `repr(C)` +can be applied to types that will be nonsensical or problematic if passed through +the FFI boundary. + +* ZSTs are still zero-sized, even though this is not a standard behaviour + in C, and is explicitly contrary to the behaviour of an empty type in C++, which + still consumes a byte of space. + +* DSTs, tuples, and tagged unions are not a concept in C and as such are never + FFI safe. + +* **The drop flag will still be added** + +* This is equivalent to `repr(u32)` for enums (see below) + + + + +# repr(packed) + +`repr(packed)` forces rust to strip any padding, and only align the type to a +byte. This may improve the memory footprint, but will likely have other +negative side-effects. + +In particular, most architectures *strongly* prefer values to be aligned. This +may mean the unaligned loads are penalized (x86), or even fault (ARM). In +particular, the compiler may have trouble with references to unaligned fields. + +`repr(packed)` is not to be used lightly. Unless you have extreme requirements, +this should not be used. + +This repr is a modifier on `repr(C)` and `repr(rust)`. + + + + +# repr(u8), repr(u16), repr(u32), repr(u64) + +These specify the size to make a C-like enum. If the discriminant overflows the +integer it has to fit in, it will be an error. You can manually ask Rust to +allow this by setting the overflowing element to explicitly be 0. However Rust +will not allow you to create an enum where two variants. + +These reprs have no affect on a struct or non-C-like enum. \ No newline at end of file diff --git a/ownership.md b/ownership.md new file mode 100644 index 000000000000..9c4f92a4394e --- /dev/null +++ b/ownership.md @@ -0,0 +1,66 @@ +% Ownership and Lifetimes + +Ownership is the breakout feature of Rust. It allows Rust to be completely +memory-safe and efficient, while avoiding garbage collection. Before getting +into the ownership system in detail, we will consider the motivation of this +design. + +We will assume that you accept that garbage collection is not always an optimal +solution, and that it is desirable to manually manage memory to some extent. +If you do not accept this, might I interest you in a different language? + +Regardless of your feelings on GC, it is pretty clearly a *massive* boon to +making code safe. You never have to worry about things going away *too soon* +(although whether you still *wanted* to be pointing at that thing is a different +issue...). This is a pervasive problem that C and C++ need to deal with. +Consider this simple mistake that all of us who have used a non-GC'd language +have made at one point: + +```rust +fn as_str(data: &u32) -> &str { + // compute the string + let s = format!("{}", data); + + // OH NO! We returned a reference to something that + // exists only in this function! + // Dangling pointer! Use after free! Alas! + // (this does not compile in Rust) + &s +} +``` + +This is exactly what Rust's ownership system was built to solve. +Rust knows the scope in which the `&s` lives, and as such can prevent it from +escaping. However this is a simple case that even a C compiler could plausibly +catch. Things get more complicated as code gets bigger and pointers get fed through +various functions. Eventually, a C compiler will fall down and won't be able to +perform sufficient escape analysis to prove your code unsound. It will consequently +be forced to accept your program on the assumption that it is correct. + +This will never happen to Rust. It's up to the programmer to prove to the +compiler that everything is sound. + +Of course, rust's story around ownership is much more complicated than just +verifying that references don't escape the scope of their referent. That's +because ensuring pointers are always valid is much more complicated than this. +For instance in this code, + +```rust +let mut data = vec![1, 2, 3]; +// get an internal reference +let x = &data[0]; + +// OH NO! `push` causes the backing storage of `data` to be reallocated. +// Dangling pointer! User after free! Alas! +// (this does not compile in Rust) +data.push(4); + +println!("{}", x); +``` + +naive scope analysis would be insufficient to prevent this bug, because `data` +does in fact live as long as we needed. However it was *changed* while we had +a reference into it. This is why Rust requires any references to freeze the +referent and its owners. + + diff --git a/raii.md b/raii.md index f85562bd809b..e9b92c69ccd2 100644 --- a/raii.md +++ b/raii.md @@ -12,413 +12,3 @@ important in Rust because we have no pervasive GC to rely on for memory manageme point, really: Rust is about control. However we are not limited to just memory. Pretty much every other system resource like a thread, file, or socket is exposed through this kind of API. - - - - -# Constructors - -Unlike C++, Rust does not come with a slew of builtin -kinds of constructor. There are no Copy, Default, Assignment, Move, or whatever constructors. -This largely has to do with Rust's philosophy of being explicit. - -Move constructors are meaningless in Rust because we don't enable types to "care" about their -location in memory. Every type must be ready for it to be blindly memcopied to somewhere else -in memory. This means pure on-the-stack-but-still-movable intrusive linked lists are simply -not happening in Rust (safely). - -Assignment and copy constructors similarly don't exist because move semantics are the *default* -in rust. At most `x = y` just moves the bits of y into the x variable. Rust does provide two -facilities for going back to C++'s copy-oriented semantics: `Copy` and `Clone`. Clone is our -moral equivalent of a copy constructor, but it's never implicitly invoked. You have to explicitly -call `clone` on an element you want to be cloned. Copy is a special case of Clone where the -implementation is just "copy the bits". Copy types *are* implicitly -cloned whenever they're moved, but because of the definition of Copy this just means *not* -treating the old copy as uninitialized -- a no-op. - -While Rust provides a `Default` trait for specifying the moral equivalent of a default -constructor, it's incredibly rare for this trait to be used. This is because variables -[aren't implicitly initialized][uninit]. Default is basically only useful for generic -programming. In concrete contexts, a type will provide a static `new` method for any -kind of "default" constructor. This has no relation to `new` in other -languages and has no special meaning. It's just a naming convention. - - - - - -# Destructors - -What the language *does* provide is full-blown automatic destructors through the `Drop` trait, -which provides the following method: - -```rust -fn drop(&mut self); -``` - -This method gives the type time to somehow finish what it was doing. **After `drop` is run, -Rust will recursively try to drop all of the fields of `self`**. This is a -convenience feature so that you don't have to write "destructor boilerplate" to drop -children. If a struct has no special logic for being dropped other than dropping its -children, then it means `Drop` doesn't need to be implemented at all! - -**There is no stable way to prevent this behaviour in Rust 1.0**. - -Note that taking `&mut self` means that even if you *could* suppress recursive Drop, -Rust will prevent you from e.g. moving fields out of self. For most types, this -is totally fine. - -For instance, a custom implementation of `Box` might write `Drop` like this: - -```rust -struct Box{ ptr: *mut T } - -impl Drop for Box { - fn drop(&mut self) { - unsafe { - (*self.ptr).drop(); - heap::deallocate(self.ptr); - } - } -} -``` - -and this works fine because when Rust goes to drop the `ptr` field it just sees a *mut that -has no actual `Drop` implementation. Similarly nothing can use-after-free the `ptr` because -the Box is immediately marked as uninitialized. - -However this wouldn't work: - -```rust -struct Box{ ptr: *mut T } - -impl Drop for Box { - fn drop(&mut self) { - unsafe { - (*self.ptr).drop(); - heap::deallocate(self.ptr); - } - } -} - -struct SuperBox { box: Box } - -impl Drop for SuperBox { - fn drop(&mut self) { - unsafe { - // Hyper-optimized: deallocate the box's contents for it - // without `drop`ing the contents - heap::deallocate(self.box.ptr); - } - } -} -``` - -After we deallocate the `box`'s ptr in SuperBox's destructor, Rust will -happily proceed to tell the box to Drop itself and everything will blow up with -use-after-frees and double-frees. - -Note that the recursive drop behaviour applies to *all* structs and enums -regardless of whether they implement Drop. Therefore something like - -```rust -struct Boxy { - data1: Box, - data2: Box, - info: u32, -} -``` - -will have its data1 and data2's fields destructors whenever it "would" be -dropped, even though it itself doesn't implement Drop. We say that such a type -*needs Drop*, even though it is not itself Drop. - -Similarly, - -```rust -enum Link { - Next(Box), - None, -} -``` - -will have its inner Box field dropped *if and only if* an instance stores the Next variant. - -In general this works really nice because you don't need to worry about adding/removing -drops when you refactor your data layout. Still there's certainly many valid usecases for -needing to do trickier things with destructors. - -The classic safe solution to overriding recursive drop and allowing moving out -of Self during `drop` is to use an Option: - -```rust -struct Box{ ptr: *mut T } - -impl Drop for Box { - fn drop(&mut self) { - unsafe { - (*self.ptr).drop(); - heap::deallocate(self.ptr); - } - } -} - -struct SuperBox { box: Option> } - -impl Drop for SuperBox { - fn drop(&mut self) { - unsafe { - // Hyper-optimized: deallocate the box's contents for it - // without `drop`ing the contents. Need to set the `box` - // field as `None` to prevent Rust from trying to Drop it. - heap::deallocate(self.box.take().unwrap().ptr); - } - } -} -``` - -However this has fairly odd semantics: you're saying that a field that *should* always -be Some may be None, just because that happens in the destructor. Of course this -conversely makes a lot of sense: you can call arbitrary methods on self during -the destructor, and this should prevent you from ever doing so after deinitializing -the field. Not that it will prevent you from producing any other -arbitrarily invalid state in there. - -On balance this is an ok choice. Certainly what you should reach for by default. -However, in the future we expect there to be a first-class way to announce that -a field shouldn't be automatically dropped. - - - - -# Leaking - -Ownership based resource management is intended to simplify composition. You -acquire resources when you create the object, and you release the resources -when it gets destroyed. Since destruction is handled for you, it means you -can't forget to release the resources, and it happens as soon as possible! -Surely this is perfect and all of our problems are solved. - -Everything is terrible and we have new and exotic problems to try to solve. - -Many people like to believe that Rust eliminates resource leaks, but this -is absolutely not the case, no matter how you look at it. In the strictest -sense, "leaking" is so abstract as to be unpreventable. It's quite trivial -to initialize a collection at the start of a program, fill it with tons of -objects with destructors, and then enter an infinite event loop that never -refers to it. The collection will sit around uselessly, holding on to its -precious resources until the program terminates (at which point all those -resources would have been reclaimed by the OS anyway). - -We may consider a more restricted form of leak: failing to drop a value that -is unreachable. Rust also doesn't prevent this. In fact Rust has a *function -for doing this*: `mem::forget`. This function consumes the value it is passed -*and then doesn't run its destructor*. - -In the past `mem::forget` was marked as unsafe as a sort of lint against using -it, since failing to call a destructor is generally not a well-behaved thing to -do (though useful for some special unsafe code). However this was generally -determined to be an untenable stance to take: there are *many* ways to fail to -call a destructor in safe code. The most famous example is creating a cycle -of reference counted pointers using interior mutability. - -It is reasonable for safe code to assume that destructor leaks do not happen, -as any program that leaks destructors is probably wrong. However *unsafe* code -cannot rely on destructors to be run to be *safe*. For most types this doesn't -matter: if you leak the destructor then the type is *by definition* inaccessible, -so it doesn't matter, right? For instance, if you leak a `Box` then you -waste some memory but that's hardly going to violate memory-safety. - -However where we must be careful with destructor leaks are *proxy* types. -These are types which manage access to a distinct object, but don't actually -own it. Proxy objects are quite rare. Proxy objects you'll need to care about -are even rarer. However we'll focus on three interesting examples in the -standard library: - -* `vec::Drain` -* `Rc` -* `thread::scoped::JoinGuard` - - - -## Drain - -`drain` is a collections API that moves data out of the container without -consuming the container. This enables us to reuse the allocation of a `Vec` -after claiming ownership over all of its contents. It produces an iterator -(Drain) that returns the contents of the Vec by-value. - -Now, consider Drain in the middle of iteration: some values have been moved out, -and others haven't. This means that part of the Vec is now full of logically -uninitialized data! We could backshift all the elements in the Vec every time we -remove a value, but this would have pretty catastrophic performance consequences. - -Instead, we would like Drain to *fix* the Vec's backing storage when it is -dropped. It should run itself to completion, backshift any elements that weren't -removed (drain supports subranges), and then fix Vec's `len`. It's even -unwinding-safe! Easy! - -Now consider the following: - -``` -let mut vec = vec![Box::new(0); 4]; - -{ - // start draining, vec can no longer be accessed - let mut drainer = vec.drain(..); - - // pull out two elements and immediately drop them - drainer.next(); - drainer.next(); - - // get rid of drainer, but don't call its destructor - mem::forget(drainer); -} - -// Oops, vec[0] was dropped, we're reading a pointer into free'd memory! -println!("{}", vec[0]); -``` - -This is pretty clearly Not Good. Unfortunately, we're kind've stuck between -a rock and a hard place: maintaining consistent state at every step has -an enormous cost (and would negate any benefits of the API). Failing to maintain -consistent state gives us Undefined Behaviour in safe code (making the API -unsound). - -So what can we do? Well, we can pick a trivially consistent state: set the Vec's -len to be 0 when we *start* the iteration, and fix it up if necessary in the -destructor. That way, if everything executes like normal we get the desired -behaviour with minimal overhead. But if someone has the *audacity* to mem::forget -us in the middle of the iteration, all that does is *leak even more* (and possibly -leave the Vec in an *unexpected* but consistent state). Since we've -accepted that mem::forget is safe, this is definitely safe. We call leaks causing -more leaks a *leak amplification*. - - - - -## Rc - -Rc is an interesting case because at first glance it doesn't appear to be a -proxy value at all. After all, it manages the data it points to, and dropping -all the Rcs for a value will drop that value. leaking an Rc doesn't seem like -it would be particularly dangerous. It will leave the refcount permanently -incremented and prevent the data from being freed or dropped, but that seems -just like Box, right? - -Nope. - -Let's consider a simplified implementation of Rc: - -```rust -struct Rc { - ptr: *mut RcBox, -} - -struct RcBox { - data: T, - ref_count: usize, -} - -impl Rc { - fn new(data: T) -> Self { - unsafe { - // Wouldn't it be nice if heap::allocate worked like this? - let ptr = heap::allocate>(); - ptr::write(ptr, RcBox { - data: data, - ref_count: 1, - }); - Rc { ptr: ptr } - } - } - - fn clone(&self) -> Self { - unsafe { - (*self.ptr).ref_count += 1; - } - Rc { ptr: self.ptr } - } -} - -impl Drop for Rc { - fn drop(&mut self) { - unsafe { - let inner = &mut ; - (*self.ptr).ref_count -= 1; - if (*self.ptr).ref_count == 0 { - // drop the data and then free it - ptr::read(self.ptr); - heap::deallocate(self.ptr); - } - } - } -} -``` - -This code contains an implicit and subtle assumption: ref_count can fit in a -`usize`, because there can't be more than `usize::MAX` Rcs in memory. However -this itself assumes that the ref_count accurately reflects the number of Rcs -in memory, which we know is false with mem::forget. Using mem::forget we can -overflow the ref_count, and then get it down to 0 with outstanding Rcs. Then we -can happily use-after-free the inner data. Bad Bad Not Good. - -This can be solved by *saturating* the ref_count, which is sound because -decreasing the refcount by `n` still requires `n` Rcs simultaneously living -in memory. - - - - -## thread::scoped::JoinGuard - -The thread::scoped API intends to allow threads to be spawned that reference -data on the stack without any synchronization over that data. Usage looked like: - -```rust -let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; -{ - let guards = vec![]; - for x in &mut data { - // Move the mutable reference into the closure, and execute - // it on a different thread. The closure has a lifetime bound - // by the lifetime of the mutable reference `x` we store in it. - // The guard that is returned is in turn assigned the lifetime - // of the closure, so it also mutably borrows `data` as `x` did. - // This means we cannot access `data` until the guard goes away. - let guard = thread::scoped(move || { - *x *= 2; - }); - // store the thread's guard for later - guards.push(guard); - } - // All guards are dropped here, forcing the threads to join - // (this thread blocks here until the others terminate). - // Once the threads join, the borrow expires and the data becomes - // accessible again in this thread. -} -// data is definitely mutated here. -``` - -In principle, this totally works! Rust's ownership system perfectly ensures it! -...except it relies on a destructor being called to be safe. - -``` -let mut data = Box::new(0); -{ - let guard = thread::scoped(|| { - // This is at best a data race. At worst, it's *also* a use-after-free. - *data += 1; - }); - // Because the guard is forgotten, expiring the loan without blocking this - // thread. - mem::forget(guard); -} -// So the Box is dropped here while the scoped thread may or may not be trying -// to access it. -``` - -Dang. Here the destructor running was pretty fundamental to the API, and it had -to be scrapped in favour of a completely different design. - -[uninit]: uninitialized.html \ No newline at end of file diff --git a/references.md b/references.md new file mode 100644 index 000000000000..fa47a69a7eaa --- /dev/null +++ b/references.md @@ -0,0 +1,139 @@ +% References + +There are two kinds of reference: + +* Shared reference: `&` +* Mutable reference: `&mut` + +Which obey the following rules: + +* A reference cannot outlive its referent +* A mutable reference cannot be aliased + +To define aliasing, we must define the notion of *paths* and *liveness*. + + + + +# Paths + +If all Rust had were values, then every value would be uniquely owned +by a variable or composite structure. From this we naturally derive a *tree* +of ownership. The stack itself is the root of the tree, with every variable +as its direct children. Each variable's direct children would be their fields +(if any), and so on. + +From this view, every value in Rust has a unique *path* in the tree of ownership. +References to a value can subsequently be interpreted as a path in this tree. +Of particular interest are *prefixes*: `x` is a prefix of `y` if `x` owns `y` + +However much data doesn't reside on the stack, and we must also accommodate this. +Globals and thread-locals are simple enough to model as residing at the bottom +of the stack (though we must be careful with mutable globals). Data on +the heap poses a different problem. + +If all Rust had on the heap was data uniquely by a pointer on the stack, +then we can just treat that pointer as a struct that owns the value on +the heap. Box, Vec, String, and HashMap, are examples of types which uniquely +own data on the heap. + +Unfortunately, data on the heap is not *always* uniquely owned. Rc for instance +introduces a notion of *shared* ownership. Shared ownership means there is no +unique path. A value with no unique path limits what we can do with it. In general, only +shared references can be created to these values. However mechanisms which ensure +mutual exclusion may establish One True Owner temporarily, establishing a unique path +to that value (and therefore all its children). + +The most common way to establish such a path is through *interior mutability*, +in contrast to the *inherited mutability* that everything in Rust normally uses. +Cell, RefCell, Mutex, and RWLock are all examples of interior mutability types. These +types provide exclusive access through runtime restrictions. However it is also +possible to establish unique ownership without interior mutability. For instance, +if an Rc has refcount 1, then it is safe to mutate or move its internals. + + + + +# Liveness + +Roughly, a reference is *live* at some point in a program if it can be +dereferenced. Shared references are always live unless they are literally unreachable +(for instance, they reside in freed or leaked memory). Mutable references can be +reachable but *not* live through the process of *reborrowing*. + +A mutable reference can be reborrowed to either a shared or mutable reference. +Further, the reborrow can produce exactly the same reference, or point to a +path it is a prefix of. For instance, a mutable reference can be reborrowed +to point to a field of its referent: + +```rust +let x = &mut (1, 2); +{ + // reborrow x to a subfield + let y = &mut x.0; + // y is now live, but x isn't + *y = 3; +} +// y goes out of scope, so x is live again +*x = (5, 7); +``` + +It is also possible to reborrow into *multiple* mutable references, as long as +they are *disjoint*: no reference is a prefix of another. Rust +explicitly enables this to be done with disjoint struct fields, because +disjointness can be statically proven: + +```rust +let x = &mut (1, 2); +{ + // reborrow x to two disjoint subfields + let y = &mut x.0; + let z = &mut x.1; + // y and z are now live, but x isn't + *y = 3; + *z = 4; +} +// y and z go out of scope, so x is live again +*x = (5, 7); +``` + +However it's often the case that Rust isn't sufficiently smart to prove that +multiple borrows are disjoint. *This does not mean it is fundamentally illegal +to make such a borrow*, just that Rust isn't as smart as you want. + +To simplify things, we can model variables as a fake type of reference: *owned* +references. Owned references have much the same semantics as mutable references: +they can be re-borrowed in a mutable or shared manner, which makes them no longer +live. Live owned references have the unique property that they can be moved +out of (though mutable references *can* be swapped out of). This is +only given to *live* owned references because moving its referent would of +course invalidate all outstanding references prematurely. + +As a local lint against inappropriate mutation, only variables that are marked +as `mut` can be borrowed mutably. + +It is also interesting to note that Box behaves exactly like an owned +reference. It can be moved out of, and Rust understands it sufficiently to +reason about its paths like a normal variable. + + + + +# Aliasing + +With liveness and paths defined, we can now properly define *aliasing*: + +**A mutable reference is aliased if there exists another live reference to it or +one of its prefixes.** + +That's it. Super simple right? Except for the fact that it took us two pages +to define all of the terms in that defintion. You know: Super. Simple. + +Actually it's a bit more complicated than that. In addition to references, +Rust has *raw pointers*: `*const T` and `*mut T`. Raw pointers have no inherent +ownership or aliasing semantics. As a result, Rust makes absolutely no effort +to track that they are used correctly, and they are wildly unsafe. + +**It is an open question to what degree raw pointers have alias semantics. +However it is important for these definitions to be sound that the existence +of a raw pointer does not imply some kind of live path.** diff --git a/repr-rust.md b/repr-rust.md new file mode 100644 index 000000000000..caf60bed8c53 --- /dev/null +++ b/repr-rust.md @@ -0,0 +1,124 @@ +% repr(Rust) + +Rust gives you the following ways to lay out composite data: + +* structs (named product types) +* tuples (anonymous product types) +* arrays (homogeneous product types) +* enums (named sum types -- tagged unions) + +An enum is said to be *C-like* if none of its variants have associated data. + +For all these, individual fields are aligned to their preferred alignment. For +primitives this is usually equal to their size. For instance, a u32 will be +aligned to a multiple of 32 bits, and a u16 will be aligned to a multiple of 16 +bits. Composite structures will have a preferred alignment equal to the maximum +of their fields' preferred alignment, and a size equal to a multiple of their +preferred alignment. This ensures that arrays of T can be correctly iterated +by offsetting by their size. So for instance, + +```rust +struct A { + a: u8, + c: u32, + b: u16, +} +``` + +will have a size that is a multiple of 32-bits, and 32-bit alignment. + +There is *no indirection* for these types; all data is stored contiguously as you would +expect in C. However with the exception of arrays (which are densely packed and +in-order), the layout of data is not by default specified in Rust. Given the two +following struct definitions: + +```rust +struct A { + a: i32, + b: u64, +} + +struct B { + x: i32, + b: u64, +} +``` + +Rust *does* guarantee that two instances of A have their data laid out in exactly +the same way. However Rust *does not* guarantee that an instance of A has the same +field ordering or padding as an instance of B (in practice there's no *particular* +reason why they wouldn't, other than that its not currently guaranteed). + +With A and B as written, this is basically nonsensical, but several other features +of Rust make it desirable for the language to play with data layout in complex ways. + +For instance, consider this struct: + +```rust +struct Foo { + count: u16, + data1: T, + data2: U, +} +``` + +Now consider the monomorphizations of `Foo` and `Foo`. If Rust lays out the +fields in the order specified, we expect it to *pad* the values in the struct to satisfy +their *alignment* requirements. So if Rust didn't reorder fields, we would expect Rust to +produce the following: + +```rust +struct Foo { + count: u16, + data1: u16, + data2: u32, +} + +struct Foo { + count: u16, + _pad1: u16, + data1: u32, + data2: u16, + _pad2: u16, +} +``` + +The latter case quite simply wastes space. An optimal use of space therefore requires +different monomorphizations to have *different field orderings*. + +**Note: this is a hypothetical optimization that is not yet implemented in Rust 1.0** + +Enums make this consideration even more complicated. Naively, an enum such as: + +```rust +enum Foo { + A(u32), + B(u64), + C(u8), +} +``` + +would be laid out as: + +```rust +struct FooRepr { + data: u64, // this is *really* either a u64, u32, or u8 based on `tag` + tag: u8, // 0 = A, 1 = B, 2 = C +} +``` + +And indeed this is approximately how it would be laid out in general +(modulo the size and position of `tag`). However there are several cases where +such a representation is ineffiecient. The classic case of this is Rust's +"null pointer optimization". Given a pointer that is known to not be null +(e.g. `&u32`), an enum can *store* a discriminant bit *inside* the pointer +by using null as a special value. The net result is that +`size_of::>() == size_of::<&T>()` + +There are many types in Rust that are, or contain, "not null" pointers such as +`Box`, `Vec`, `String`, `&T`, and `&mut T`. Similarly, one can imagine +nested enums pooling their tags into a single descriminant, as they are by +definition known to have a limited range of valid values. In principle enums can +use fairly elaborate algorithms to cache bits throughout nested types with +special constrained representations. As such it is *especially* desirable that +we leave enum layout unspecified today. \ No newline at end of file diff --git a/safe-unsafe-meaning.md b/safe-unsafe-meaning.md new file mode 100644 index 000000000000..8a6300a061d2 --- /dev/null +++ b/safe-unsafe-meaning.md @@ -0,0 +1,135 @@ +% What do Safe and Unsafe really mean? + +Rust cares about 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` larger than char::MAX (TODO: check if stronger restrictions apply) + * A non-utf8 `str` +* Unwinding into another language +* Causing a [data race][] +* Invoking Misc. Undefined Behaviour (in e.g. compiler intrinsics) + +That's it. That's all the Undefined Behaviour in Rust. Libraries are free to +declare arbitrary requirements if they could transitively cause memory safety +issues, but it all boils down to the above actions. Rust is otherwise +quite permisive with respect to other dubious operations. Rust considers it +"safe" to: + +* Deadlock +* Have a Race Condition +* Leak memory +* Fail to call destructors +* Overflow integers +* Delete the production database + +However any program that does such a thing is *probably* incorrect. Rust +provides lots of tools to make doing these things rare, but these problems are +considered impractical to categorically prevent. + +Rust models the seperation between Safe and Unsafe with the `unsafe` keyword. +There are several places `unsafe` can appear in Rust today, which can largely be +grouped into two categories: + +* There are unchecked contracts here. To declare you understand this, I require +you to write `unsafe` elsewhere: + * On functions, `unsafe` is declaring the function to be unsafe to call. Users + of the function must check the documentation to determine what this means, + and then have to write `unsafe` somewhere to identify that they're aware of + the danger. + * On trait declarations, `unsafe` is declaring that *implementing* the trait + is an unsafe operation, as it has contracts that other unsafe code is free to + trust blindly. + +* I am declaring that I have, to the best of my knowledge, adhered to the +unchecked contracts: + * On trait implementations, `unsafe` is declaring that the contract of the + `unsafe` trait has been upheld. + * On blocks, `unsafe` is declaring any unsafety from an unsafe + operation within to be handled, and therefore the parent function is safe. + +There is also `#[unsafe_no_drop_flag]`, which is a special case that exists for +historical reasons and is in the process of being phased out. See the section on +[destructors][] for details. + +Some examples of unsafe functions: + +* `slice::get_unchecked` will perform unchecked indexing, allowing memory + safety to be freely violated. +* `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is + not "in bounds" as defined by LLVM (see the lifetimes section for details). +* `mem::transmute` reinterprets some value as having the given type, + bypassing type safety in arbitrary ways. (see [conversions][] for details) +* All FFI functions are `unsafe` because they can do arbitrary things. + C being an obvious culprit, but generally any language can do something + that Rust isn't happy about. + +As of Rust 1.0 there are exactly two unsafe traits: + +* `Send` is a marker trait (it has no actual API) that promises implementors + are safe to send to another thread. +* `Sync` is a marker trait that promises that threads can safely share + implementors through a shared reference. + +The need for unsafe traits boils down to the fundamental lack of trust that Unsafe +has for Safe. All safe traits are free to declare arbitrary contracts, but because +implementing them is a job for Safe, Unsafe can't trust those contracts to actually +be upheld. + +For instance Rust has `PartialOrd` and `Ord` traits to try to differentiate +between types which can "just" be compared, and those that actually implement a +*total* ordering. Pretty much every API that wants to work with data that can be +compared *really* wants Ord data. For instance, a sorted map like BTreeMap +*doesn't even make sense* for partially ordered types. If you claim to implement +Ord for a type, but don't actually provide a proper total ordering, BTreeMap will +get *really confused* and start making a total mess of itself. Data that is +inserted may be impossible to find! + +But that's ok. BTreeMap is safe, so it guarantees that even if you give it a +*completely* garbage Ord implementation, it will still do something *safe*. You +won't start reading uninitialized memory or unallocated memory. In fact, BTreeMap +manages to not actually lose any of your data. When the map is dropped, all the +destructors will be successfully called! Hooray! + +However BTreeMap is implemented using a modest spoonful of Unsafe (most collections +are). That means that it is not necessarily *trivially true* that a bad Ord +implementation will make BTreeMap behave safely. Unsafe most be sure not to rely +on Ord *where safety is at stake*, because Ord is provided by Safe, and memory +safety is not Safe's responsibility to uphold. *It must be impossible for Safe +code to violate memory safety*. + +But wouldn't it be grand if there was some way for Unsafe to trust *some* trait +contracts *somewhere*? This is the problem that unsafe traits tackle: by marking +*the trait itself* as unsafe *to implement*, Unsafe can trust the implementation +to be correct (because Unsafe can trust themself). + +Rust has traditionally avoided making traits unsafe because it makes Unsafe +pervasive, which is not desirable. Send and Sync are unsafe is because +thread safety is a *fundamental property* that Unsafe cannot possibly hope to +defend against in the same way it would defend against a bad Ord implementation. +The only way to possibly defend against thread-unsafety would be to *not use +threading at all*. Making every operation atomic isn't even sufficient, because +it's possible for complex invariants between disjoint locations in memory. + +Even concurrent paradigms that are traditionally regarded as Totally Safe like +message passing implicitly rely on some notion of thread safety -- are you +really message-passing if you send a *pointer*? Send and Sync therefore require +some *fundamental* level of trust that Safe code can't provide, so they must be +unsafe to implement. To help obviate the pervasive unsafety that this would +introduce, Send (resp. Sync) is *automatically* derived for all types composed only +of Send (resp. Sync) values. 99% of types are Send and Sync, and 99% of those +never actually say it (the remaining 1% is overwhelmingly synchronization +primitives). + + + +[pointer aliasing rules]: lifetimes.html#references +[uninitialized memory]: uninitialized.html +[data race]: concurrency.html +[destructors]: raii.html +[conversions]: conversions.html \ No newline at end of file diff --git a/subtyping.md b/subtyping.md new file mode 100644 index 000000000000..733e015dbd7d --- /dev/null +++ b/subtyping.md @@ -0,0 +1,177 @@ +% Subtyping and Variance + +Although Rust doesn't have any notion of inheritance, it *does* include subtyping. +In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes are scopes, +we can partially order them based on a *contains* (outlives) relationship. We +can even express this as a generic bound: `T: 'a` specifies that whatever scope `T` +is valid for must contain the scope `'a` ("T outlives `'a`"). + +We can then define subtyping on lifetimes in terms of that relationship: if `'a: 'b` +("a contains b" or "a outlives b"), then `'a` is a subtype of `'b`. This is a +large source of confusion, because it seems intuitively backwards to many: +the bigger scope is a *sub type* of the smaller scope. + +This does in fact make sense. The intuitive reason for this is that if you expect an +`&'a u8`, then it's totally fine for me to hand you an `&'static u8`, in the same way +that if you expect an Animal in Java, it's totally fine for me to hand you a Cat. +Cats are just Animals *and more*, just as `'static` is just `'a` *and more*. + +(Note, the subtyping relationship and typed-ness of lifetimes is a fairly arbitrary +construct that some disagree with. I just find that it simplifies this analysis.) + +Higher-ranked lifetimes are also subtypes of every concrete lifetime. This is because +taking an arbitrary lifetime is strictly more general than taking a specific one. + + + +# Variance + +Variance is where things get really harsh. + +Variance is a property that *type constructors* have. A type constructor in Rust +is a generic type with unbound arguments. For instance `Vec` is a type constructor +that takes a `T` and returns a `Vec`. `&` and `&mut` are type constructors that +take a lifetime and a type. + +A type constructor's *variance* is how the subtypes of its inputs affects the +subtypes of its outputs. There are three kinds of variance: + +* F is *variant* if `T` being a subtype of `U` implies `F` is a subtype of `F` +* F is *invariant* otherwise (no subtyping relation can be derived) + +(For those of you who are familiar with variance from other languages, what we refer +to as "just" variance is in fact *covariance*. Rust does not have contravariance. +Historically Rust did have some contravariance but it was scrapped due to poor +interactions with other features.) + +Some important variances: + +* `&` is variant (as is `*const` by metaphor) +* `&mut` is invariant (as is `*mut` by metaphor) +* `Fn(T) -> U` is invariant with respect to `T`, but variant with respect to `U` +* `Box`, `Vec`, and all other collections are variant +* `UnsafeCell`, `Cell`, `RefCell`, `Mutex` and all "interior mutability" + types are invariant + +To understand why these variances are correct and desirable, we will consider several +examples. We have already covered why `&` should be variant when introducing subtyping: +it's desirable to be able to pass longer-lived things where shorter-lived things are +needed. + +To see why `&mut` should be invariant, consider the following code: + +```rust +fn main() { + let mut forever_str: &'static str = "hello"; + { + let string = String::from("world"); + overwrite(&mut forever_str, &mut &*string); + } + println!("{}", forever_str); +} + +fn overwrite(input: &mut T, new: &mut T) { + *input = *new; +} +``` + +The signature of `overwrite` is clearly valid: it takes mutable references to two values +of the same type, and overwrites one with the other. We have seen already that `&` is +variant, and `'static` is a subtype of *any* `'a`, so `&'static str` is a +subtype of `&'a str`. Therefore, if `&mut` was +*also* variant, then the lifetime of the `&'static str` would successfully be +"shrunk" down to the shorter lifetime of the string, and `overwrite` would be +called successfully. The string would subsequently be dropped, and `forever_str` +would point to freed memory when we print it! + +Therefore `&mut` should be invariant. This is the general theme of variance vs +invariance: if variance would allow you to *store* a short-lived value in a +longer-lived slot, then you must be invariant. + +`Box` and `Vec` are interesting cases because they're variant, but you can +definitely store values in them! This is fine because *you can only store values +in them through a mutable reference*! The mutable reference makes the whole type +invariant, and therefore prevents you from getting in trouble. + +Being variant allows them to be variant when shared immutably (so you can pass +a `&Box<&'static str>` where a `&Box<&'a str>` is expected). It also allows you to +forever weaken the type by moving it into a weaker slot. That is, you can do: + +```rust +fn get_box<'a>(&'a u8) -> Box<&'a str> { + // string literals are `&'static str`s + Box::new("hello") +} +``` + +which is fine because unlike the mutable borrow case, there's no one else who +"remembers" the old lifetime in the box. + +The variance of the cell types similarly follows. `&` is like an `&mut` for a +cell, because you can still store values in them through an `&`. Therefore cells +must be invariant to avoid lifetime smuggling. + +`Fn` is the most subtle case, because it has mixed variance. To see why +`Fn(T) -> U` should be invariant over T, consider the following function +signature: + +```rust +// 'a is derived from some parent scope +fn foo(&'a str) -> usize; +``` + +This signature claims that it can handle any &str that lives *at least* as long +as `'a`. Now if this signature was variant with respect to `&str`, that would mean + +```rust +fn foo(&'static str) -> usize; +``` + +could be provided in its place, as it would be a subtype. However this function +has a *stronger* requirement: it says that it can *only* handle `&'static str`s, +and nothing else. Therefore functions are not variant over their arguments. + +To see why `Fn(T) -> U` should be *variant* over U, consider the following +function signature: + +```rust +// 'a is derived from some parent scope +fn foo(usize) -> &'a str; +``` + +This signature claims that it will return something that outlives `'a`. It is +therefore completely reasonable to provide + +```rust +fn foo(usize) -> &'static str; +``` + +in its place. Therefore functions *are* variant over their return type. + +`*const` has the exact same semantics as `&`, so variance follows. `*mut` on the +other hand can dereference to an &mut whether shared or not, so it is marked +as invariant in analogy to cells. + +This is all well and good for the types the standard library provides, but +how is variance determined for type that *you* define? A struct, informally +speaking, inherits the variance of its fields. If a struct `Foo` +has a generic argument `A` that is used in a field `a`, then Foo's variance +over `A` is exactly `a`'s variance. However this is complicated if `A` is used +in multiple fields. + +* If all uses of A are variant, then Foo is variant over A +* Otherwise, Foo is invariant over A + +```rust +struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { + a: &'a A, // variant over 'a and A + b: &'b mut B, // invariant over 'b and B + c: *const C, // variant over C + d: *mut D, // invariant over D + e: Vec, // variant over E + f: Cell, // invariant over F + g: G // variant over G + h1: H // would also be variant over H except... + h2: Cell // invariant over H, because invariance wins +} +``` \ No newline at end of file diff --git a/transmutes.md b/transmutes.md new file mode 100644 index 000000000000..577d35ddb56d --- /dev/null +++ b/transmutes.md @@ -0,0 +1,29 @@ +% Transmutes + +Get out of our way type system! We're going to reinterpret these bits or die +trying! Even though this book is all about doing things that are unsafe, I really +can't emphasize that you should deeply think about finding Another Way than the +operations covered in this section. This is really, truly, the most horribly +unsafe thing you can do in Rust. The railguards here are dental floss. + +`mem::transmute` takes a value of type `T` and reinterprets it to have +type `U`. The only restriction is that the `T` and `U` are verified to have the +same size. The ways to cause Undefined Behaviour with this are mind boggling. + +* First and foremost, creating an instance of *any* type with an invalid state + is going to cause arbitrary chaos that can't really be predicted. +* Transmute has an overloaded return type. If you do not specify the return type + it may produce a surprising type to satisfy inference. +* Making a primitive with an invalid value is UB +* Transmuting between non-repr(C) types is UB +* Transmuting an & to &mut is UB +* Transmuting to a reference without an explicitly provided lifetime + produces an [unbound lifetime](lifetimes.html#unbounded-lifetimes) + +`mem::transmute_copy` somehow manages to be *even more* wildly unsafe than +this. It copies `size_of` bytes out of an `&T` and interprets them as a `U`. +The size check that `mem::transmute` has is gone (as it may be valid to copy +out a prefix), though it is Undefined Behaviour for `U` to be larger than `T`. + +Also of course you can get most of the functionality of these functions using +pointer casts. \ No newline at end of file diff --git a/unbounded-lifetimes.md b/unbounded-lifetimes.md new file mode 100644 index 000000000000..24caeeb36aaa --- /dev/null +++ b/unbounded-lifetimes.md @@ -0,0 +1,37 @@ +% Unbounded Lifetimes + +Unsafe code can often end up producing references or lifetimes out of thin air. +Such lifetimes come into the world as *unbounded*. The most common source of this +is derefencing a raw pointer, which produces a reference with an unbounded lifetime. +Such a lifetime becomes as big as context demands. This is in fact more powerful +than simply becoming `'static`, because for instance `&'static &'a T` +will fail to typecheck, but the unbound lifetime will perfectly mold into +`&'a &'a T` as needed. However for most intents and purposes, such an unbounded +lifetime can be regarded as `'static`. + +Almost no reference is `'static`, so this is probably wrong. `transmute` and +`transmute_copy` are the two other primary offenders. One should endeavour to +bound an unbounded lifetime as quick as possible, especially across function +boundaries. + +Given a function, any output lifetimes that don't derive from inputs are +unbounded. For instance: + +```rust +fn get_str<'a>() -> &'a str; +``` + +will produce an `&str` with an unbounded lifetime. The easiest way to avoid +unbounded lifetimes is to use lifetime elision at the function boundary. +If an output lifetime is elided, then it *must* be bounded by an input lifetime. +Of course it might be bounded by the *wrong* lifetime, but this will usually +just cause a compiler error, rather than allow memory safety to be trivially +violated. + +Within a function, bounding lifetimes is more error-prone. The safest and easiest +way to bound a lifetime is to return it from a function with a bound lifetime. +However if this is unacceptable, the reference can be placed in a location with +a specific lifetime. Unfortunately it's impossible to name all lifetimes involved +in a function. To get around this, you can in principle use `copy_lifetime`, though +these are unstable due to their awkward nature and questionable utility. + diff --git a/unchecked-uninit.md b/unchecked-uninit.md new file mode 100644 index 000000000000..f5c0fb405993 --- /dev/null +++ b/unchecked-uninit.md @@ -0,0 +1,86 @@ +% Unchecked Uninitialized Memory + +One interesting exception to this rule is working with arrays. Safe Rust doesn't +permit you to partially initialize an array. When you initialize an array, you +can either set every value to the same thing with `let x = [val; N]`, or you can +specify each member individually with `let x = [val1, val2, val3]`. +Unfortunately this is pretty rigid, especially if you need to initialize your +array in a more incremental or dynamic way. + +Unsafe Rust gives us a powerful tool to handle this problem: +`mem::uninitialized`. This function pretends to return a value when really +it does nothing at all. Using it, we can convince Rust that we have initialized +a variable, allowing us to do trickier things with conditional and incremental +initialization. + +Unfortunately, this opens us up to all kinds of problems. Assignment has a +different meaning to Rust based on whether it believes that a variable is +initialized or not. If it's uninitialized, then Rust will semantically just +memcopy the bits over the uninitialized ones, and do nothing else. However if Rust +believes a value to be initialized, it will try to `Drop` the old value! +Since we've tricked Rust into believing that the value is initialized, we +can no longer safely use normal assignment. + +This is also a problem if you're working with a raw system allocator, which +returns a pointer to uninitialized memory. + +To handle this, we must use the `ptr` module. In particular, it provides +three functions that allow us to assign bytes to a location in memory without +evaluating the old value: `write`, `copy`, and `copy_nonoverlapping`. + +* `ptr::write(ptr, val)` takes a `val` and moves it into the address pointed + to by `ptr`. +* `ptr::copy(src, dest, count)` copies the bits that `count` T's would occupy + from src to dest. (this is equivalent to memmove -- note that the argument + order is reversed!) +* `ptr::copy_nonoverlapping(src, dest, count)` does what `copy` does, but a + little faster on the assumption that the two ranges of memory don't overlap. + (this is equivalent to memcopy -- note that the argument order is reversed!) + +It should go without saying that these functions, if misused, will cause serious +havoc or just straight up Undefined Behaviour. The only things that these +functions *themselves* require is that the locations you want to read and write +are allocated. However the ways writing arbitrary bits to arbitrary +locations of memory can break things are basically uncountable! + +Putting this all together, we get the following: + +```rust +fn main() { + use std::mem; + + // size of the array is hard-coded but easy to change. This means we can't + // use [a, b, c] syntax to initialize the array, though! + const SIZE = 10; + + let x: [Box; SIZE]; + + unsafe { + // convince Rust that x is Totally Initialized + x = mem::uninitialized(); + for i in 0..SIZE { + // very carefully overwrite each index without reading it + // NOTE: exception safety is not a concern; Box can't panic + ptr::write(&mut x[i], Box::new(i)); + } + } + + println!("{}", x); +} +``` + +It's worth noting that you don't need to worry about ptr::write-style +shenanigans with types which don't implement Drop or +contain Drop types, because Rust knows not to try to Drop them. Similarly you +should be able to assign to fields of partially initialized structs +directly if those fields don't contain any Drop types. + +However when working with uninitialized memory you need to be ever-vigilant for +Rust trying to Drop values you make like this before they're fully initialized. +Every control path through that variable's scope must initialize the value +before it ends, if has a destructor. +*[This includes code panicking](unwinding.html)*. + +And that's about it for working with uninitialized memory! Basically nothing +anywhere expects to be handed uninitialized memory, so if you're going to pass +it around at all, be sure to be *really* careful. \ No newline at end of file diff --git a/uninitialized.md b/uninitialized.md index 983c320c7382..915ea8602918 100644 --- a/uninitialized.md +++ b/uninitialized.md @@ -6,195 +6,5 @@ of bits that may or may not even reflect a valid state for the type that is supposed to inhabit that location of memory. Attempting to interpret this memory as a value of *any* type will cause Undefined Behaviour. Do Not Do This. -Like C, all stack variables in Rust are uninitialized until a -value is explicitly assigned to them. Unlike C, Rust statically prevents you -from ever reading them until you do: - -```rust -fn main() { - let x: i32; - println!("{}", x); -} -``` - -```text -src/main.rs:3:20: 3:21 error: use of possibly uninitialized variable: `x` -src/main.rs:3 println!("{}", x); - ^ -``` - -This is based off of a basic branch analysis: every branch must assign a value -to `x` before it is first used. Interestingly, Rust doesn't require the variable -to be mutable to perform a delayed initialization if every branch assigns -exactly once. However the analysis does not take advantage of constant analysis -or anything like that. So this compiles: - -```rust -fn main() { - let x: i32; - - if true { - x = 1; - } else { - x = 2; - } - - println!("{}", x); -} -``` - -but this doesn't: - -```rust -fn main() { - let x: i32; - if true { - x = 1; - } - println!("{}", x); -} -``` - -```text -src/main.rs:6:17: 6:18 error: use of possibly uninitialized variable: `x` -src/main.rs:6 println!("{}", x); -``` - -while this does: - -```rust -fn main() { - let x: i32; - if true { - x = 1; - println!("{}", x); - } - // Don't care that there are branches where it's not initialized - // since we don't use the value in those branches -} -``` - -If a value is moved out of a variable, that variable becomes logically -uninitialized if the type of the value isn't Copy. That is: - -```rust -fn main() { - let x = 0; - let y = Box::new(0); - let z1 = x; // x is still valid because i32 is Copy - let z2 = y; // y is now logically uninitialized because Box isn't Copy -} -``` - -However reassigning `y` in this example *would* require `y` to be marked as -mutable, as a Safe Rust program could observe that the value of `y` changed. -Otherwise the variable is exactly like new. - -This raises an interesting question with respect to `Drop`: where does Rust try -to call the destructor of a variable that is conditionally initialized? It turns -out that Rust actually tracks whether a type should be dropped or not *at -runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for -that variable is set and unset. When a variable goes out of scope or is assigned -a value, it evaluates whether the current value of the variable should be dropped. -Of course, static analysis can remove these checks. If the compiler can prove that -a value is guaranteed to be either initialized or not, then it can theoretically -generate more efficient code! As such it may be desirable to structure code to -have *static drop semantics* when possible. - -As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden -field of any type that implements Drop. The language sets the drop flag by -overwriting the entire struct with a particular value. This is pretty obviously -Not The Fastest and causes a bunch of trouble with optimizing code. As such work -is currently under way to move the flags out onto the stack frame where they -more reasonably belong. Unfortunately this work will take some time as it -requires fairly substantial changes to the compiler. - -So in general, Rust programs don't need to worry about uninitialized values on -the stack for correctness. Although they might care for performance. Thankfully, -Rust makes it easy to take control here! Uninitialized values are there, and -Safe Rust lets you work with them, but you're never in danger. - -One interesting exception to this rule is working with arrays. Safe Rust doesn't -permit you to partially initialize an array. When you initialize an array, you -can either set every value to the same thing with `let x = [val; N]`, or you can -specify each member individually with `let x = [val1, val2, val3]`. -Unfortunately this is pretty rigid, especially if you need to initialize your -array in a more incremental or dynamic way. - -Unsafe Rust gives us a powerful tool to handle this problem: -`mem::uninitialized`. This function pretends to return a value when really -it does nothing at all. Using it, we can convince Rust that we have initialized -a variable, allowing us to do trickier things with conditional and incremental -initialization. - -Unfortunately, this opens us up to all kinds of problems. Assignment has a -different meaning to Rust based on whether it believes that a variable is -initialized or not. If it's uninitialized, then Rust will semantically just -memcopy the bits over the uninitialized ones, and do nothing else. However if Rust -believes a value to be initialized, it will try to `Drop` the old value! -Since we've tricked Rust into believing that the value is initialized, we -can no longer safely use normal assignment. - -This is also a problem if you're working with a raw system allocator, which -returns a pointer to uninitialized memory. - -To handle this, we must use the `ptr` module. In particular, it provides -three functions that allow us to assign bytes to a location in memory without -evaluating the old value: `write`, `copy`, and `copy_nonoverlapping`. - -* `ptr::write(ptr, val)` takes a `val` and moves it into the address pointed - to by `ptr`. -* `ptr::copy(src, dest, count)` copies the bits that `count` T's would occupy - from src to dest. (this is equivalent to memmove -- note that the argument - order is reversed!) -* `ptr::copy_nonoverlapping(src, dest, count)` does what `copy` does, but a - little faster on the assumption that the two ranges of memory don't overlap. - (this is equivalent to memcopy -- note that the argument order is reversed!) - -It should go without saying that these functions, if misused, will cause serious -havoc or just straight up Undefined Behaviour. The only things that these -functions *themselves* require is that the locations you want to read and write -are allocated. However the ways writing arbitrary bits to arbitrary -locations of memory can break things are basically uncountable! - -Putting this all together, we get the following: - -```rust -fn main() { - use std::mem; - - // size of the array is hard-coded but easy to change. This means we can't - // use [a, b, c] syntax to initialize the array, though! - const SIZE = 10; - - let x: [Box; SIZE]; - - unsafe { - // convince Rust that x is Totally Initialized - x = mem::uninitialized(); - for i in 0..SIZE { - // very carefully overwrite each index without reading it - // NOTE: exception safety is not a concern; Box can't panic - ptr::write(&mut x[i], Box::new(i)); - } - } - - println!("{}", x); -} -``` - -It's worth noting that you don't need to worry about ptr::write-style -shenanigans with types which don't implement Drop or -contain Drop types, because Rust knows not to try to Drop them. Similarly you -should be able to assign to fields of partially initialized structs -directly if those fields don't contain any Drop types. - -However when working with uninitialized memory you need to be ever-vigilant for -Rust trying to Drop values you make like this before they're fully initialized. -Every control path through that variable's scope must initialize the value -before it ends, if has a destructor. -*[This includes code panicking](unwinding.html)*. - -And that's about it for working with uninitialized memory! Basically nothing -anywhere expects to be handed uninitialized memory, so if you're going to pass -it around at all, be sure to be *really* careful. +Rust provides mechanisms to work with uninitialized memory in checked (safe) and +unchecked (unsafe) ways. \ No newline at end of file diff --git a/vec-alloc.md b/vec-alloc.md new file mode 100644 index 000000000000..a51f23ca4b8b --- /dev/null +++ b/vec-alloc.md @@ -0,0 +1,117 @@ +% Allocating Memory + +So: + +```rust +#![feature(heap_api)] + +use std::rt::heap::EMPTY; +use std::mem; + +impl Vec { + fn new() -> Self { + assert!(mem::size_of::() != 0, "We're not ready to handle ZSTs"); + unsafe { + // need to cast EMPTY to the actual ptr type we want, let + // inference handle it. + Vec { ptr: Unique::new(heap::EMPTY as *mut _), len: 0, cap: 0 } + } + } +} +``` + +I slipped in that assert there because zero-sized types will require some +special handling throughout our code, and I want to defer the issue for now. +Without this assert, some of our early drafts will do some Very Bad Things. + +Next we need to figure out what to actually do when we *do* want space. For that, +we'll need to use the rest of the heap APIs. These basically allow us to +talk directly to Rust's instance of jemalloc. + +We'll also need a way to handle out-of-memory conditions. The standard library +calls the `abort` intrinsic, but calling intrinsics from normal Rust code is a +pretty bad idea. Unfortunately, the `abort` exposed by the standard library +allocates. Not something we want to do during `oom`! Instead, we'll call +`std::process::exit`. + +```rust +fn oom() { + ::std::process::exit(-9999); +} +``` + +Okay, now we can write growing. Roughly, we want to have this logic: + +```text +if cap == 0: + allocate() + cap = 1 +else + reallocate + cap *= 2 +``` + +But Rust's only supported allocator API is so low level that we'll need to +do a fair bit of extra work, though. We also need to guard against some special +conditions that can occur with really large allocations. In particular, we index +into arrays using unsigned integers, but `ptr::offset` takes signed integers. This +means Bad Things will happen if we ever manage to grow to contain more than +`isize::MAX` elements. Thankfully, this isn't something we need to worry about +in most cases. + +On 64-bit targets we're artifically limited to only 48-bits, so we'll run out +of memory far before we reach that point. However on 32-bit targets, particularly +those with extensions to use more of the address space, it's theoretically possible +to successfully allocate more than `isize::MAX` bytes of memory. Still, we only +really need to worry about that if we're allocating elements that are a byte large. +Anything else will use up too much space. + +However since this is a tutorial, we're not going to be particularly optimal here, +and just unconditionally check, rather than use clever platform-specific `cfg`s. + +```rust +fn grow(&mut self) { + // this is all pretty delicate, so let's say it's all unsafe + unsafe { + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + // as an invariant, we can assume that `self.cap < isize::MAX`, + // so this doesn't need to be checked. + let new_cap = self.cap * 2; + // Similarly this can't overflow due to previously allocating this + let old_num_bytes = self.cap * elem_size; + + // check that the new allocation doesn't exceed `isize::MAX` at all + // regardless of the actual size of the capacity. This combines the + // `new_cap <= isize::MAX` and `new_num_bytes <= usize::MAX` checks + // we need to make. We lose the ability to allocate e.g. 2/3rds of + // the address space with a single Vec of i16's on 32-bit though. + // Alas, poor Yorick -- I knew him, Horatio. + assert!(old_num_bytes <= (::std::isize::MAX as usize) / 2, + "capacity overflow"); + + let new_num_bytes = old_num_bytes * 2; + let ptr = heap::reallocate(*self.ptr as *mut _, + old_num_bytes, + new_num_bytes, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom(); } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } +} +``` + +Nothing particularly tricky here. Just computing sizes and alignments and doing +some careful multiplication checks. + diff --git a/vec-dealloc.md b/vec-dealloc.md new file mode 100644 index 000000000000..a83d24d7b49c --- /dev/null +++ b/vec-dealloc.md @@ -0,0 +1,29 @@ +% Deallocating + +Next we should implement Drop so that we don't massively leak tons of resources. +The easiest way is to just call `pop` until it yields None, and then deallocate +our buffer. Note that calling `pop` is uneeded if `T: !Drop`. In theory we can +ask Rust if T needs_drop and omit the calls to `pop`. However in practice LLVM +is *really* good at removing simple side-effect free code like this, so I wouldn't +bother unless you notice it's not being stripped (in this case it is). + +We must not call `heap::deallocate` when `self.cap == 0`, as in this case we haven't +actually allocated any memory. + + +```rust +impl Drop for Vec { + fn drop(&mut self) { + if self.cap != 0 { + while let Some(_) = self.pop() { } + + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr, num_bytes, align); + } + } + } +} +``` diff --git a/vec-deref.md b/vec-deref.md new file mode 100644 index 000000000000..b07d784939ae --- /dev/null +++ b/vec-deref.md @@ -0,0 +1,40 @@ +% Deref + +Alright! We've got a decent minimal ArrayStack implemented. We can push, we can +pop, and we can clean up after ourselves. However there's a whole mess of functionality +we'd reasonably want. In particular, we have a proper array, but none of the slice +functionality. That's actually pretty easy to solve: we can implement `Deref`. +This will magically make our Vec coerce to and behave like a slice in all sorts of +conditions. + +All we need is `slice::from_raw_parts`. + +```rust +use std::ops::Deref; + +impl Deref for Vec { + type Target = [T]; + fn deref(&self) -> &[T] { + unsafe { + ::std::slice::from_raw_parts(*self.ptr, self.len) + } + } +} +``` + +And let's do DerefMut too: + +```rust +use std::ops::DerefMut; + +impl DerefMut for Vec { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { + ::std::slice::from_raw_parts_mut(*self.ptr, self.len) + } + } +} +``` + +Now we have `len`, `first`, `last`, indexing, slicing, sorting, `iter`, `iter_mut`, +and all other sorts of bells and whistles provided by slice. Sweet! diff --git a/vec-drain.md b/vec-drain.md new file mode 100644 index 000000000000..0a53e8bdfad9 --- /dev/null +++ b/vec-drain.md @@ -0,0 +1,318 @@ +% Drain + +Let's move on to Drain. Drain is largely the same as IntoIter, except that +instead of consuming the Vec, it borrows the Vec and leaves its allocation +free. For now we'll only implement the "basic" full-range version. + +```rust,ignore +use std::marker::PhantomData; + +struct Drain<'a, T: 'a> { + vec: PhantomData<&'a mut Vec> + start: *const T, + end: *const T, +} + +impl<'a, T> Iterator for Drain<'a, T> { + type Item = T; + fn next(&mut self) -> Option { + if self.start == self.end { + None +``` + +-- wait, this is seeming familiar. Let's do some more compression. Both +IntoIter and Drain have the exact same structure, let's just factor it out. + +```rust +struct RawValIter { + start: *const T, + end: *const T, +} + +impl RawValIter { + // unsafe to construct because it has no associated lifetimes. + // This is necessary to store a RawValIter in the same struct as + // its actual allocation. OK since it's a private implementation + // detail. + unsafe fn new(slice: &[T]) -> Self { + RawValIter { + start: slice.as_ptr(), + end: if slice.len() == 0 { + slice.as_ptr() + } else { + slice.as_ptr().offset(slice.len() as isize) + } + } + } +} + +// Iterator and DoubleEndedIterator impls identical to IntoIter. +``` + +And IntoIter becomes the following: + +``` +pub struct IntoIter { + _buf: RawVec, // we don't actually care about this. Just need it to live. + iter: RawValIter, +} + +impl Iterator for IntoIter { + type Item = T; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +impl Drop for IntoIter { + fn drop(&mut self) { + for _ in &mut self.iter {} + } +} + +impl Vec { + pub fn into_iter(self) -> IntoIter { + unsafe { + let iter = RawValIter::new(&self); + let buf = ptr::read(&self.buf); + mem::forget(self); + + IntoIter { + iter: iter, + _buf: buf, + } + } + } +} +``` + +Note that I've left a few quirks in this design to make upgrading Drain to work +with arbitrary subranges a bit easier. In particular we *could* have RawValIter +drain itself on drop, but that won't work right for a more complex Drain. +We also take a slice to simplify Drain initialization. + +Alright, now Drain is really easy: + +```rust +use std::marker::PhantomData; + +pub struct Drain<'a, T: 'a> { + vec: PhantomData<&'a mut Vec>, + iter: RawValIter, +} + +impl<'a, T> Iterator for Drain<'a, T> { + type Item = T; + fn next(&mut self) -> Option { self.iter.next_back() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +impl<'a, T> DoubleEndedIterator for Drain<'a, T> { + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +impl<'a, T> Drop for Drain<'a, T> { + fn drop(&mut self) { + for _ in &mut self.iter {} + } +} + +impl Vec { + pub fn drain(&mut self) -> Drain { + // this is a mem::forget safety thing. If Drain is forgotten, we just + // leak the whole Vec's contents. Also we need to do this *eventually* + // anyway, so why not do it now? + self.len = 0; + + unsafe { + Drain { + iter: RawValIter::new(&self), + vec: PhantomData, + } + } + } +} +``` + + + + +# Handling Zero-Sized Types + +It's time. We're going to fight the spectre that is zero-sized types. Safe Rust +*never* needs to care about this, but Vec is very intensive on raw pointers and +raw allocations, which are exactly the *only* two things that care about +zero-sized types. We need to be careful of two things: + +* The raw allocator API has undefined behaviour if you pass in 0 for an + allocation size. +* raw pointer offsets are no-ops for zero-sized types, which will break our + C-style pointer iterator. + +Thankfully we abstracted out pointer-iterators and allocating handling into +RawValIter and RawVec respectively. How mysteriously convenient. + + + + +## Allocating Zero-Sized Types + +So if the allocator API doesn't support zero-sized allocations, what on earth +do we store as our allocation? Why, `heap::EMPTY` of course! Almost every operation +with a ZST is a no-op since ZSTs have exactly one value, and therefore no state needs +to be considered to store or load them. This actually extends to `ptr::read` and +`ptr::write`: they won't actually look at the pointer at all. As such we *never* need +to change the pointer. + +Note however that our previous reliance on running out of memory before overflow is +no longer valid with zero-sized types. We must explicitly guard against capacity +overflow for zero-sized types. + +Due to our current architecture, all this means is writing 3 guards, one in each +method of RawVec. + +```rust +impl RawVec { + fn new() -> Self { + unsafe { + // !0 is usize::MAX. This branch should be stripped at compile time. + let cap = if mem::size_of::() == 0 { !0 } else { 0 }; + + // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" + RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } + } + } + + fn grow(&mut self) { + unsafe { + let elem_size = mem::size_of::(); + + // since we set the capacity to usize::MAX when elem_size is + // 0, getting to here necessarily means the Vec is overfull. + assert!(elem_size != 0, "capacity overflow"); + + let align = mem::min_align_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + let new_cap = 2 * self.cap; + let ptr = heap::reallocate(*self.ptr as *mut _, + self.cap * elem_size, + new_cap * elem_size, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom() } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } + } +} + +impl Drop for RawVec { + fn drop(&mut self) { + let elem_size = mem::size_of::(); + + // don't free zero-sized allocations, as they were never allocated. + if self.cap != 0 && elem_size != 0 { + let align = mem::min_align_of::(); + + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr as *mut _, num_bytes, align); + } + } + } +} +``` + +That's it. We support pushing and popping zero-sized types now. Our iterators +(that aren't provided by slice Deref) are still busted, though. + + + + +## Iterating Zero-Sized Types + +Zero-sized offsets are no-ops. This means that our current design will always +initialize `start` and `end` as the same value, and our iterators will yield +nothing. The current solution to this is to cast the pointers to integers, +increment, and then cast them back: + +``` +impl RawValIter { + unsafe fn new(slice: &[T]) -> Self { + RawValIter { + start: slice.as_ptr(), + end: if mem::size_of::() == 0 { + ((slice.as_ptr() as usize) + slice.len()) as *const _ + } else if slice.len() == 0 { + slice.as_ptr() + } else { + slice.as_ptr().offset(slice.len() as isize) + } + } + } +} +``` + +Now we have a different bug. Instead of our iterators not running at all, our +iterators now run *forever*. We need to do the same trick in our iterator impls. +Also, our size_hint computation code will divide by 0 for ZSTs. Since we'll +basically be treating the two pointers as if they point to bytes, we'll just +map size 0 to divide by 1. + +``` +impl Iterator for RawValIter { + type Item = T; + fn next(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + let result = ptr::read(self.start); + self.start = if mem::size_of::() == 0 { + (self.start as usize + 1) as *const _ + } else { + self.start.offset(1); + } + Some(result) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let elem_size = mem::size_of::(); + let len = (self.end as usize - self.start as usize) + / if elem_size == 0 { 1 } else { elem_size }; + (len, Some(len)) + } +} + +impl DoubleEndedIterator for RawValIter { + fn next_back(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + self.end = if mem::size_of::() == 0 { + (self.end as usize - 1) as *const _ + } else { + self.end.offset(-1); + } + Some(ptr::read(self.end)) + } + } + } +} +``` + +And that's it. Iteration works! \ No newline at end of file diff --git a/vec-final.md b/vec-final.md new file mode 100644 index 000000000000..96fcf6d47103 --- /dev/null +++ b/vec-final.md @@ -0,0 +1,309 @@ +% The Final Code + +```rust +#![feature(unique)] +#![feature(heap_api)] + +use std::ptr::{Unique, self}; +use std::rt::heap; +use std::mem; +use std::ops::{Deref, DerefMut}; +use std::marker::PhantomData; + + + + + +struct RawVec { + ptr: Unique, + cap: usize, +} + +impl RawVec { + fn new() -> Self { + unsafe { + // !0 is usize::MAX. This branch should be stripped at compile time. + let cap = if mem::size_of::() == 0 { !0 } else { 0 }; + + // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" + RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } + } + } + + fn grow(&mut self) { + unsafe { + let elem_size = mem::size_of::(); + + // since we set the capacity to usize::MAX when elem_size is + // 0, getting to here necessarily means the Vec is overfull. + assert!(elem_size != 0, "capacity overflow"); + + let align = mem::min_align_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + let new_cap = 2 * self.cap; + let ptr = heap::reallocate(*self.ptr as *mut _, + self.cap * elem_size, + new_cap * elem_size, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom() } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } + } +} + +impl Drop for RawVec { + fn drop(&mut self) { + let elem_size = mem::size_of::(); + if self.cap != 0 && elem_size != 0 { + let align = mem::min_align_of::(); + + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr as *mut _, num_bytes, align); + } + } + } +} + + + + + +pub struct Vec { + buf: RawVec, + len: usize, +} + +impl Vec { + fn ptr(&self) -> *mut T { *self.buf.ptr } + + fn cap(&self) -> usize { self.buf.cap } + + pub fn new() -> Self { + Vec { buf: RawVec::new(), len: 0 } + } + pub fn push(&mut self, elem: T) { + if self.len == self.cap() { self.buf.grow(); } + + unsafe { + ptr::write(self.ptr().offset(self.len as isize), elem); + } + + // Can't fail, we'll OOM first. + self.len += 1; + } + + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + self.len -= 1; + unsafe { + Some(ptr::read(self.ptr().offset(self.len as isize))) + } + } + } + + pub fn insert(&mut self, index: usize, elem: T) { + assert!(index <= self.len, "index out of bounds"); + if self.cap() == self.len { self.buf.grow(); } + + unsafe { + if index < self.len { + ptr::copy(self.ptr().offset(index as isize), + self.ptr().offset(index as isize + 1), + self.len - index); + } + ptr::write(self.ptr().offset(index as isize), elem); + self.len += 1; + } + } + + pub fn remove(&mut self, index: usize) -> T { + assert!(index < self.len, "index out of bounds"); + unsafe { + self.len -= 1; + let result = ptr::read(self.ptr().offset(index as isize)); + ptr::copy(self.ptr().offset(index as isize + 1), + self.ptr().offset(index as isize), + self.len - index); + result + } + } + + pub fn into_iter(self) -> IntoIter { + unsafe { + let iter = RawValIter::new(&self); + let buf = ptr::read(&self.buf); + mem::forget(self); + + IntoIter { + iter: iter, + _buf: buf, + } + } + } + + pub fn drain(&mut self) -> Drain { + // this is a mem::forget safety thing. If this is forgotten, we just + // leak the whole Vec's contents. Also we need to do this *eventually* + // anyway, so why not do it now? + self.len = 0; + unsafe { + Drain { + iter: RawValIter::new(&self), + vec: PhantomData, + } + } + } +} + +impl Drop for Vec { + fn drop(&mut self) { + while let Some(_) = self.pop() {} + // allocation is handled by RawVec + } +} + +impl Deref for Vec { + type Target = [T]; + fn deref(&self) -> &[T] { + unsafe { + ::std::slice::from_raw_parts(self.ptr(), self.len) + } + } +} + +impl DerefMut for Vec { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { + ::std::slice::from_raw_parts_mut(self.ptr(), self.len) + } + } +} + + + + + +struct RawValIter { + start: *const T, + end: *const T, +} + +impl RawValIter { + unsafe fn new(slice: &[T]) -> Self { + RawValIter { + start: slice.as_ptr(), + end: if mem::size_of::() == 0 { + ((slice.as_ptr() as usize) + slice.len()) as *const _ + } else if slice.len() == 0 { + slice.as_ptr() + } else { + slice.as_ptr().offset(slice.len() as isize) + } + } + } +} + +impl Iterator for RawValIter { + type Item = T; + fn next(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + let result = ptr::read(self.start); + self.start = self.start.offset(1); + Some(result) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let elem_size = mem::size_of::(); + let len = (self.end as usize - self.start as usize) + / if elem_size == 0 { 1 } else { elem_size }; + (len, Some(len)) + } +} + +impl DoubleEndedIterator for RawValIter { + fn next_back(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + self.end = self.end.offset(-1); + Some(ptr::read(self.end)) + } + } + } +} + + + + +pub struct IntoIter { + _buf: RawVec, // we don't actually care about this. Just need it to live. + iter: RawValIter, +} + +impl Iterator for IntoIter { + type Item = T; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +impl Drop for IntoIter { + fn drop(&mut self) { + for _ in &mut *self {} + } +} + + + + +pub struct Drain<'a, T: 'a> { + vec: PhantomData<&'a mut Vec>, + iter: RawValIter, +} + +impl<'a, T> Iterator for Drain<'a, T> { + type Item = T; + fn next(&mut self) -> Option { self.iter.next_back() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +impl<'a, T> DoubleEndedIterator for Drain<'a, T> { + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +impl<'a, T> Drop for Drain<'a, T> { + fn drop(&mut self) { + // pre-drain the iter + for _ in &mut self.iter {} + } +} + +/// Abort the process, we're out of memory! +/// +/// In practice this is probably dead code on most OSes +fn oom() { + ::std::process::exit(-9999); +} +``` \ No newline at end of file diff --git a/vec-insert-remove.md b/vec-insert-remove.md new file mode 100644 index 000000000000..42d114c4a449 --- /dev/null +++ b/vec-insert-remove.md @@ -0,0 +1,50 @@ +% Insert and Remove + +Something *not* provided but slice is `insert` and `remove`, so let's do those next. + +Insert needs to shift all the elements at the target index to the right by one. +To do this we need to use `ptr::copy`, which is our version of C's `memmove`. +This copies some chunk of memory from one location to another, correctly handling +the case where the source and destination overlap (which will definitely happen +here). + +If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]` +using the *old* len. + +```rust +pub fn insert(&mut self, index: usize, elem: T) { + // Note: `<=` because it's valid to insert after everything + // which would be equivalent to push. + assert!(index <= self.len, "index out of bounds"); + if self.cap == self.len { self.grow(); } + + unsafe { + if index < self.len { + // ptr::copy(src, dest, len): "copy from source to dest len elems" + ptr::copy(self.ptr.offset(index as isize), + self.ptr.offset(index as isize + 1), + len - index); + } + ptr::write(self.ptr.offset(index as isize), elem); + self.len += 1; + } +} +``` + +Remove behaves in the opposite manner. We need to shift all the elements from +`[i+1 .. len + 1]` to `[i .. len]` using the *new* len. + +```rust +pub fn remove(&mut self, index: usize) -> T { + // Note: `<` because it's *not* valid to remove after everything + assert!(index < self.len, "index out of bounds"); + unsafe { + self.len -= 1; + let result = ptr::read(self.ptr.offset(index as isize)); + ptr::copy(self.ptr.offset(index as isize + 1), + self.ptr.offset(index as isize), + len - index); + result + } +} +``` \ No newline at end of file diff --git a/vec-into-iter.md b/vec-into-iter.md new file mode 100644 index 000000000000..b7e7d2bdc42d --- /dev/null +++ b/vec-into-iter.md @@ -0,0 +1,293 @@ +% IntoIter + +Let's move on to writing iterators. `iter` and `iter_mut` have already been +written for us thanks to The Magic of Deref. However there's two interesting +iterators that Vec provides that slices can't: `into_iter` and `drain`. + +IntoIter consumes the Vec by-value, and can consequently yield its elements +by-value. In order to enable this, IntoIter needs to take control of Vec's +allocation. + +IntoIter needs to be DoubleEnded as well, to enable reading from both ends. +Reading from the back could just be implemented as calling `pop`, but reading +from the front is harder. We could call `remove(0)` but that would be insanely +expensive. Instead we're going to just use ptr::read to copy values out of either +end of the Vec without mutating the buffer at all. + +To do this we're going to use a very common C idiom for array iteration. We'll +make two pointers; one that points to the start of the array, and one that points +to one-element past the end. When we want an element from one end, we'll read out +the value pointed to at that end and move the pointer over by one. When the two +pointers are equal, we know we're done. + +Note that the order of read and offset are reversed for `next` and `next_back` +For `next_back` the pointer is always *after* the element it wants to read next, +while for `next` the pointer is always *at* the element it wants to read next. +To see why this is, consider the case where every element but one has been yielded. + +The array looks like this: + +```text + S E +[X, X, X, O, X, X, X] +``` + +If E pointed directly at the element it wanted to yield next, it would be +indistinguishable from the case where there are no more elements to yield. + +So we're going to use the following struct: + +```rust +struct IntoIter { + buf: Unique, + cap: usize, + start: *const T, + end: *const T, +} +``` + +One last subtle detail: if our Vec is empty, we want to produce an empty iterator. +This will actually technically fall out doing the naive thing of: + +```text +start = ptr +end = ptr.offset(len) +``` + +However because `offset` is marked as a GEP inbounds instruction, this will tell +LLVM that ptr is allocated and won't alias other allocated memory. This is fine +for zero-sized types, as they can't alias anything. However if we're using +`heap::EMPTY` as a sentinel for a non-allocation for a *non-zero-sized* type, +this can cause undefined behaviour. Alas, we must therefore special case either +cap or len being 0 to not do the offset. + +So this is what we end up with for initialization: + +```rust +impl Vec { + fn into_iter(self) -> IntoIter { + // Can't destructure Vec since it's Drop + let ptr = self.ptr; + let cap = self.cap; + let len = self.len; + + // Make sure not to drop Vec since that will free the buffer + mem::forget(self); + + unsafe { + IntoIter { + buf: ptr, + cap: cap, + start: *ptr, + end: if cap == 0 { + // can't offset off this pointer, it's not allocated! + *ptr + } else { + ptr.offset(len as isize) + } + } + } + } +} +``` + +Here's iterating forward: + +```rust +impl Iterator for IntoIter { + type Item = T; + fn next(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + let result = ptr::read(self.start); + self.start = self.start.offset(1); + Some(result) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = (self.end as usize - self.start as usize) + / mem::size_of::(); + (len, Some(len)) + } +} +``` + +And here's iterating backwards. + +```rust +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + self.end = self.end.offset(-1); + Some(ptr::read(self.end)) + } + } + } +} +``` + +Because IntoIter takes ownership of its allocation, it needs to implement Drop +to free it. However it *also* wants to implement Drop to drop any elements it +contains that weren't yielded. + + +```rust +impl Drop for IntoIter { + fn drop(&mut self) { + if self.cap != 0 { + // drop any remaining elements + for _ in &mut *self {} + + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.buf as *mut _, num_bytes, align); + } + } + } +} +``` + +We've actually reached an interesting situation here: we've duplicated the logic +for specifying a buffer and freeing its memory. Now that we've implemented it and +identified *actual* logic duplication, this is a good time to perform some logic +compression. + +We're going to abstract out the `(ptr, cap)` pair and give them the logic for +allocating, growing, and freeing: + +```rust + +struct RawVec { + ptr: Unique, + cap: usize, +} + +impl RawVec { + fn new() -> Self { + assert!(mem::size_of::() != 0, "TODO: implement ZST support"); + unsafe { + RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: 0 } + } + } + + // unchanged from Vec + fn grow(&mut self) { + unsafe { + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + let new_cap = 2 * self.cap; + let ptr = heap::reallocate(*self.ptr as *mut _, + self.cap * elem_size, + new_cap * elem_size, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom() } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } + } +} + + +impl Drop for RawVec { + fn drop(&mut self) { + if self.cap != 0 { + let align = mem::min_align_of::(); + let elem_size = mem::size_of::(); + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr as *mut _, num_bytes, align); + } + } + } +} +``` + +And change vec as follows: + +```rust +pub struct Vec { + buf: RawVec, + len: usize, +} + +impl Vec { + fn ptr(&self) -> *mut T { *self.buf.ptr } + + fn cap(&self) -> usize { self.buf.cap } + + pub fn new() -> Self { + Vec { buf: RawVec::new(), len: 0 } + } + + // push/pop/insert/remove largely unchanged: + // * `self.ptr -> self.ptr()` + // * `self.cap -> self.cap()` + // * `self.grow -> self.buf.grow()` +} + +impl Drop for Vec { + fn drop(&mut self) { + while let Some(_) = self.pop() {} + // deallocation is handled by RawVec + } +} +``` + +And finally we can really simplify IntoIter: + +```rust +struct IntoIter { + _buf: RawVec, // we don't actually care about this. Just need it to live. + start: *const T, + end: *const T, +} + +// next and next_back litterally unchanged since they never referred to the buf + +impl Drop for IntoIter { + fn drop(&mut self) { + // only need to ensure all our elements are read; + // buffer will clean itself up afterwards. + for _ in &mut *self {} + } +} + +impl Vec { + pub fn into_iter(self) -> IntoIter { + unsafe { + // need to use ptr::read to unsafely move the buf out since it's + // not Copy. + let buf = ptr::read(&self.buf); + let len = self.len; + mem::forget(self); + + IntoIter { + start: *buf.ptr, + end: buf.ptr.offset(len as isize), + _buf: buf, + } + } + } +} +``` + +Much better. \ No newline at end of file diff --git a/vec-layout.md b/vec-layout.md new file mode 100644 index 000000000000..0f85e4d27cef --- /dev/null +++ b/vec-layout.md @@ -0,0 +1,61 @@ +% Layout + +First off, we need to come up with the struct layout. Naively we want this +design: + +```rust +struct Vec { + ptr: *mut T, + cap: usize, + len: usize, +} +``` + +And indeed this would compile. Unfortunately, it would be incorrect. The compiler +will give us too strict variance, so e.g. an `&Vec<&'static str>` couldn't be used +where an `&Vec<&'a str>` was expected. More importantly, it will give incorrect +ownership information to dropck, as it will conservatively assume we don't own +any values of type `T`. See [the chapter on ownership and lifetimes] +(lifetimes.html) for details. + +As we saw in the lifetimes chapter, we should use `Unique` in place of `*mut T` +when we have a raw pointer to an allocation we own: + + +```rust +#![feature(unique)] + +use std::ptr::{Unique, self}; + +pub struct Vec { + ptr: Unique, + cap: usize, + len: usize, +} +``` + +As a recap, Unique is a wrapper around a raw pointer that declares that: + +* We own at least one value of type `T` +* We are Send/Sync iff `T` is Send/Sync +* Our pointer is never null (and therefore `Option` is null-pointer-optimized) + +That last point is subtle. First, it makes `Unique::new` unsafe to call, because +putting `null` inside of it is Undefined Behaviour. It also throws a +wrench in an important feature of Vec (and indeed all of the std collections): +an empty Vec doesn't actually allocate at all. So if we can't allocate, +but also can't put a null pointer in `ptr`, what do we do in +`Vec::new`? Well, we just put some other garbage in there! + +This is perfectly fine because we already have `cap == 0` as our sentinel for no +allocation. We don't even need to handle it specially in almost any code because +we usually need to check if `cap > len` or `len > 0` anyway. The traditional +Rust value to put here is `0x01`. The standard library actually exposes this +as `std::rt::heap::EMPTY`. There are quite a few places where we'll want to use +`heap::EMPTY` because there's no real allocation to talk about but `null` would +make the compiler angry. + +All of the `heap` API is totally unstable under the `heap_api` feature, though. +We could trivially define `heap::EMPTY` ourselves, but we'll want the rest of +the `heap` API anyway, so let's just get that dependency over with. + diff --git a/vec-push-pop.md b/vec-push-pop.md new file mode 100644 index 000000000000..d1584a234210 --- /dev/null +++ b/vec-push-pop.md @@ -0,0 +1,55 @@ +% Push and Pop + +Alright. We can initialize. We can allocate. Let's actually implement some +functionality! Let's start with `push`. All it needs to do is check if we're +full to grow, unconditionally write to the next index, and then increment our +length. + +To do the write we have to be careful not to evaluate the memory we want to write +to. At worst, it's truly uninitialized memory from the allocator. At best it's the +bits of some old value we popped off. Either way, we can't just index to the memory +and dereference it, because that will evaluate the memory as a valid instance of +T. Worse, `foo[idx] = x` will try to call `drop` on the old value of `foo[idx]`! + +The correct way to do this is with `ptr::write`, which just blindly overwrites the +target address with the bits of the value we provide. No evaluation involved. + +For `push`, if the old len (before push was called) is 0, then we want to write +to the 0th index. So we should offset by the old len. + +```rust +pub fn push(&mut self, elem: T) { + if self.len == self.cap { self.grow(); } + + unsafe { + ptr::write(self.ptr.offset(self.len as isize), elem); + } + + // Can't fail, we'll OOM first. + self.len += 1; +} +``` + +Easy! How about `pop`? Although this time the index we want to access is +initialized, Rust won't just let us dereference the location of memory to move +the value out, because that *would* leave the memory uninitialized! For this we +need `ptr::read`, which just copies out the bits from the target address and +intrprets it as a value of type T. This will leave the memory at this address +*logically* uninitialized, even though there is in fact a perfectly good instance +of T there. + +For `pop`, if the old len is 1, we want to read out of the 0th index. So we +should offset by the *new* len. + +```rust +pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + self.len -= 1; + unsafe { + Some(ptr::read(self.ptr.offset(self.len as isize))) + } + } +} +``` \ No newline at end of file diff --git a/vec.md b/vec.md index 2b4e35e7653f..a613f259b70f 100644 --- a/vec.md +++ b/vec.md @@ -4,1320 +4,3 @@ To bring everything together, we're going to write `std::Vec` from scratch. Because all the best tools for writing unsafe code are unstable, this project will only work on nightly (as of Rust 1.2.0). - - -# Layout - -First off, we need to come up with the struct layout. Naively we want this -design: - -```rust -struct Vec { - ptr: *mut T, - cap: usize, - len: usize, -} -``` - -And indeed this would compile. Unfortunately, it would be incorrect. The compiler -will give us too strict variance, so e.g. an `&Vec<&'static str>` couldn't be used -where an `&Vec<&'a str>` was expected. More importantly, it will give incorrect -ownership information to dropck, as it will conservatively assume we don't own -any values of type `T`. See [the chapter on ownership and lifetimes] -(lifetimes.html) for details. - -As we saw in the lifetimes chapter, we should use `Unique` in place of `*mut T` -when we have a raw pointer to an allocation we own: - - -```rust -#![feature(unique)] - -use std::ptr::{Unique, self}; - -pub struct Vec { - ptr: Unique, - cap: usize, - len: usize, -} -``` - -As a recap, Unique is a wrapper around a raw pointer that declares that: - -* We own at least one value of type `T` -* We are Send/Sync iff `T` is Send/Sync -* Our pointer is never null (and therefore `Option` is null-pointer-optimized) - -That last point is subtle. First, it makes `Unique::new` unsafe to call, because -putting `null` inside of it is Undefined Behaviour. It also throws a -wrench in an important feature of Vec (and indeed all of the std collections): -an empty Vec doesn't actually allocate at all. So if we can't allocate, -but also can't put a null pointer in `ptr`, what do we do in -`Vec::new`? Well, we just put some other garbage in there! - -This is perfectly fine because we already have `cap == 0` as our sentinel for no -allocation. We don't even need to handle it specially in almost any code because -we usually need to check if `cap > len` or `len > 0` anyway. The traditional -Rust value to put here is `0x01`. The standard library actually exposes this -as `std::rt::heap::EMPTY`. There are quite a few places where we'll want to use -`heap::EMPTY` because there's no real allocation to talk about but `null` would -make the compiler angry. - -All of the `heap` API is totally unstable under the `heap_api` feature, though. -We could trivially define `heap::EMPTY` ourselves, but we'll want the rest of -the `heap` API anyway, so let's just get that dependency over with. - - - - -# Allocating Memory - -So: - -```rust -#![feature(heap_api)] - -use std::rt::heap::EMPTY; -use std::mem; - -impl Vec { - fn new() -> Self { - assert!(mem::size_of::() != 0, "We're not ready to handle ZSTs"); - unsafe { - // need to cast EMPTY to the actual ptr type we want, let - // inference handle it. - Vec { ptr: Unique::new(heap::EMPTY as *mut _), len: 0, cap: 0 } - } - } -} -``` - -I slipped in that assert there because zero-sized types will require some -special handling throughout our code, and I want to defer the issue for now. -Without this assert, some of our early drafts will do some Very Bad Things. - -Next we need to figure out what to actually do when we *do* want space. For that, -we'll need to use the rest of the heap APIs. These basically allow us to -talk directly to Rust's instance of jemalloc. - -We'll also need a way to handle out-of-memory conditions. The standard library -calls the `abort` intrinsic, but calling intrinsics from normal Rust code is a -pretty bad idea. Unfortunately, the `abort` exposed by the standard library -allocates. Not something we want to do during `oom`! Instead, we'll call -`std::process::exit`. - -```rust -fn oom() { - ::std::process::exit(-9999); -} -``` - -Okay, now we can write growing. Roughly, we want to have this logic: - -```text -if cap == 0: - allocate() - cap = 1 -else - reallocate - cap *= 2 -``` - -But Rust's only supported allocator API is so low level that we'll need to -do a fair bit of extra work, though. We also need to guard against some special -conditions that can occur with really large allocations. In particular, we index -into arrays using unsigned integers, but `ptr::offset` takes signed integers. This -means Bad Things will happen if we ever manage to grow to contain more than -`isize::MAX` elements. Thankfully, this isn't something we need to worry about -in most cases. - -On 64-bit targets we're artifically limited to only 48-bits, so we'll run out -of memory far before we reach that point. However on 32-bit targets, particularly -those with extensions to use more of the address space, it's theoretically possible -to successfully allocate more than `isize::MAX` bytes of memory. Still, we only -really need to worry about that if we're allocating elements that are a byte large. -Anything else will use up too much space. - -However since this is a tutorial, we're not going to be particularly optimal here, -and just unconditionally check, rather than use clever platform-specific `cfg`s. - -```rust -fn grow(&mut self) { - // this is all pretty delicate, so let's say it's all unsafe - unsafe { - let align = mem::min_align_of::(); - let elem_size = mem::size_of::(); - - let (new_cap, ptr) = if self.cap == 0 { - let ptr = heap::allocate(elem_size, align); - (1, ptr) - } else { - // as an invariant, we can assume that `self.cap < isize::MAX`, - // so this doesn't need to be checked. - let new_cap = self.cap * 2; - // Similarly this can't overflow due to previously allocating this - let old_num_bytes = self.cap * elem_size; - - // check that the new allocation doesn't exceed `isize::MAX` at all - // regardless of the actual size of the capacity. This combines the - // `new_cap <= isize::MAX` and `new_num_bytes <= usize::MAX` checks - // we need to make. We lose the ability to allocate e.g. 2/3rds of - // the address space with a single Vec of i16's on 32-bit though. - // Alas, poor Yorick -- I knew him, Horatio. - assert!(old_num_bytes <= (::std::isize::MAX as usize) / 2, - "capacity overflow"); - - let new_num_bytes = old_num_bytes * 2; - let ptr = heap::reallocate(*self.ptr as *mut _, - old_num_bytes, - new_num_bytes, - align); - (new_cap, ptr) - }; - - // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { oom(); } - - self.ptr = Unique::new(ptr as *mut _); - self.cap = new_cap; - } -} -``` - -Nothing particularly tricky here. Just computing sizes and alignments and doing -some careful multiplication checks. - - - - - -# Push and Pop - -Alright. We can initialize. We can allocate. Let's actually implement some -functionality! Let's start with `push`. All it needs to do is check if we're -full to grow, unconditionally write to the next index, and then increment our -length. - -To do the write we have to be careful not to evaluate the memory we want to write -to. At worst, it's truly uninitialized memory from the allocator. At best it's the -bits of some old value we popped off. Either way, we can't just index to the memory -and dereference it, because that will evaluate the memory as a valid instance of -T. Worse, `foo[idx] = x` will try to call `drop` on the old value of `foo[idx]`! - -The correct way to do this is with `ptr::write`, which just blindly overwrites the -target address with the bits of the value we provide. No evaluation involved. - -For `push`, if the old len (before push was called) is 0, then we want to write -to the 0th index. So we should offset by the old len. - -```rust -pub fn push(&mut self, elem: T) { - if self.len == self.cap { self.grow(); } - - unsafe { - ptr::write(self.ptr.offset(self.len as isize), elem); - } - - // Can't fail, we'll OOM first. - self.len += 1; -} -``` - -Easy! How about `pop`? Although this time the index we want to access is -initialized, Rust won't just let us dereference the location of memory to move -the value out, because that *would* leave the memory uninitialized! For this we -need `ptr::read`, which just copies out the bits from the target address and -intrprets it as a value of type T. This will leave the memory at this address -*logically* uninitialized, even though there is in fact a perfectly good instance -of T there. - -For `pop`, if the old len is 1, we want to read out of the 0th index. So we -should offset by the *new* len. - -```rust -pub fn pop(&mut self) -> Option { - if self.len == 0 { - None - } else { - self.len -= 1; - unsafe { - Some(ptr::read(self.ptr.offset(self.len as isize))) - } - } -} -``` - - - - - -# Deallocating - -Next we should implement Drop so that we don't massively leak tons of resources. -The easiest way is to just call `pop` until it yields None, and then deallocate -our buffer. Note that calling `pop` is uneeded if `T: !Drop`. In theory we can -ask Rust if T needs_drop and omit the calls to `pop`. However in practice LLVM -is *really* good at removing simple side-effect free code like this, so I wouldn't -bother unless you notice it's not being stripped (in this case it is). - -We must not call `heap::deallocate` when `self.cap == 0`, as in this case we haven't -actually allocated any memory. - - -```rust -impl Drop for Vec { - fn drop(&mut self) { - if self.cap != 0 { - while let Some(_) = self.pop() { } - - let align = mem::min_align_of::(); - let elem_size = mem::size_of::(); - let num_bytes = elem_size * self.cap; - unsafe { - heap::deallocate(*self.ptr, num_bytes, align); - } - } - } -} -``` - - - - - -# Deref - -Alright! We've got a decent minimal ArrayStack implemented. We can push, we can -pop, and we can clean up after ourselves. However there's a whole mess of functionality -we'd reasonably want. In particular, we have a proper array, but none of the slice -functionality. That's actually pretty easy to solve: we can implement `Deref`. -This will magically make our Vec coerce to and behave like a slice in all sorts of -conditions. - -All we need is `slice::from_raw_parts`. - -```rust -use std::ops::Deref; - -impl Deref for Vec { - type Target = [T]; - fn deref(&self) -> &[T] { - unsafe { - ::std::slice::from_raw_parts(*self.ptr, self.len) - } - } -} -``` - -And let's do DerefMut too: - -```rust -use std::ops::DerefMut; - -impl DerefMut for Vec { - fn deref_mut(&mut self) -> &mut [T] { - unsafe { - ::std::slice::from_raw_parts_mut(*self.ptr, self.len) - } - } -} -``` - -Now we have `len`, `first`, `last`, indexing, slicing, sorting, `iter`, `iter_mut`, -and all other sorts of bells and whistles provided by slice. Sweet! - - - - - -# Insert and Remove - -Something *not* provided but slice is `insert` and `remove`, so let's do those next. - -Insert needs to shift all the elements at the target index to the right by one. -To do this we need to use `ptr::copy`, which is our version of C's `memmove`. -This copies some chunk of memory from one location to another, correctly handling -the case where the source and destination overlap (which will definitely happen -here). - -If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]` -using the *old* len. - -```rust -pub fn insert(&mut self, index: usize, elem: T) { - // Note: `<=` because it's valid to insert after everything - // which would be equivalent to push. - assert!(index <= self.len, "index out of bounds"); - if self.cap == self.len { self.grow(); } - - unsafe { - if index < self.len { - // ptr::copy(src, dest, len): "copy from source to dest len elems" - ptr::copy(self.ptr.offset(index as isize), - self.ptr.offset(index as isize + 1), - len - index); - } - ptr::write(self.ptr.offset(index as isize), elem); - self.len += 1; - } -} -``` - -Remove behaves in the opposite manner. We need to shift all the elements from -`[i+1 .. len + 1]` to `[i .. len]` using the *new* len. - -```rust -pub fn remove(&mut self, index: usize) -> T { - // Note: `<` because it's *not* valid to remove after everything - assert!(index < self.len, "index out of bounds"); - unsafe { - self.len -= 1; - let result = ptr::read(self.ptr.offset(index as isize)); - ptr::copy(self.ptr.offset(index as isize + 1), - self.ptr.offset(index as isize), - len - index); - result - } -} -``` - - - - - -# IntoIter - -Let's move on to writing iterators. `iter` and `iter_mut` have already been -written for us thanks to The Magic of Deref. However there's two interesting -iterators that Vec provides that slices can't: `into_iter` and `drain`. - -IntoIter consumes the Vec by-value, and can consequently yield its elements -by-value. In order to enable this, IntoIter needs to take control of Vec's -allocation. - -IntoIter needs to be DoubleEnded as well, to enable reading from both ends. -Reading from the back could just be implemented as calling `pop`, but reading -from the front is harder. We could call `remove(0)` but that would be insanely -expensive. Instead we're going to just use ptr::read to copy values out of either -end of the Vec without mutating the buffer at all. - -To do this we're going to use a very common C idiom for array iteration. We'll -make two pointers; one that points to the start of the array, and one that points -to one-element past the end. When we want an element from one end, we'll read out -the value pointed to at that end and move the pointer over by one. When the two -pointers are equal, we know we're done. - -Note that the order of read and offset are reversed for `next` and `next_back` -For `next_back` the pointer is always *after* the element it wants to read next, -while for `next` the pointer is always *at* the element it wants to read next. -To see why this is, consider the case where every element but one has been yielded. - -The array looks like this: - -```text - S E -[X, X, X, O, X, X, X] -``` - -If E pointed directly at the element it wanted to yield next, it would be -indistinguishable from the case where there are no more elements to yield. - -So we're going to use the following struct: - -```rust -struct IntoIter { - buf: Unique, - cap: usize, - start: *const T, - end: *const T, -} -``` - -One last subtle detail: if our Vec is empty, we want to produce an empty iterator. -This will actually technically fall out doing the naive thing of: - -```text -start = ptr -end = ptr.offset(len) -``` - -However because `offset` is marked as a GEP inbounds instruction, this will tell -LLVM that ptr is allocated and won't alias other allocated memory. This is fine -for zero-sized types, as they can't alias anything. However if we're using -`heap::EMPTY` as a sentinel for a non-allocation for a *non-zero-sized* type, -this can cause undefined behaviour. Alas, we must therefore special case either -cap or len being 0 to not do the offset. - -So this is what we end up with for initialization: - -```rust -impl Vec { - fn into_iter(self) -> IntoIter { - // Can't destructure Vec since it's Drop - let ptr = self.ptr; - let cap = self.cap; - let len = self.len; - - // Make sure not to drop Vec since that will free the buffer - mem::forget(self); - - unsafe { - IntoIter { - buf: ptr, - cap: cap, - start: *ptr, - end: if cap == 0 { - // can't offset off this pointer, it's not allocated! - *ptr - } else { - ptr.offset(len as isize) - } - } - } - } -} -``` - -Here's iterating forward: - -```rust -impl Iterator for IntoIter { - type Item = T; - fn next(&mut self) -> Option { - if self.start == self.end { - None - } else { - unsafe { - let result = ptr::read(self.start); - self.start = self.start.offset(1); - Some(result) - } - } - } - - fn size_hint(&self) -> (usize, Option) { - let len = (self.end as usize - self.start as usize) - / mem::size_of::(); - (len, Some(len)) - } -} -``` - -And here's iterating backwards. - -```rust -impl DoubleEndedIterator for IntoIter { - fn next_back(&mut self) -> Option { - if self.start == self.end { - None - } else { - unsafe { - self.end = self.end.offset(-1); - Some(ptr::read(self.end)) - } - } - } -} -``` - -Because IntoIter takes ownership of its allocation, it needs to implement Drop -to free it. However it *also* wants to implement Drop to drop any elements it -contains that weren't yielded. - - -```rust -impl Drop for IntoIter { - fn drop(&mut self) { - if self.cap != 0 { - // drop any remaining elements - for _ in &mut *self {} - - let align = mem::min_align_of::(); - let elem_size = mem::size_of::(); - let num_bytes = elem_size * self.cap; - unsafe { - heap::deallocate(*self.buf as *mut _, num_bytes, align); - } - } - } -} -``` - -We've actually reached an interesting situation here: we've duplicated the logic -for specifying a buffer and freeing its memory. Now that we've implemented it and -identified *actual* logic duplication, this is a good time to perform some logic -compression. - -We're going to abstract out the `(ptr, cap)` pair and give them the logic for -allocating, growing, and freeing: - -```rust - -struct RawVec { - ptr: Unique, - cap: usize, -} - -impl RawVec { - fn new() -> Self { - assert!(mem::size_of::() != 0, "TODO: implement ZST support"); - unsafe { - RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: 0 } - } - } - - // unchanged from Vec - fn grow(&mut self) { - unsafe { - let align = mem::min_align_of::(); - let elem_size = mem::size_of::(); - - let (new_cap, ptr) = if self.cap == 0 { - let ptr = heap::allocate(elem_size, align); - (1, ptr) - } else { - let new_cap = 2 * self.cap; - let ptr = heap::reallocate(*self.ptr as *mut _, - self.cap * elem_size, - new_cap * elem_size, - align); - (new_cap, ptr) - }; - - // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { oom() } - - self.ptr = Unique::new(ptr as *mut _); - self.cap = new_cap; - } - } -} - - -impl Drop for RawVec { - fn drop(&mut self) { - if self.cap != 0 { - let align = mem::min_align_of::(); - let elem_size = mem::size_of::(); - let num_bytes = elem_size * self.cap; - unsafe { - heap::deallocate(*self.ptr as *mut _, num_bytes, align); - } - } - } -} -``` - -And change vec as follows: - -```rust -pub struct Vec { - buf: RawVec, - len: usize, -} - -impl Vec { - fn ptr(&self) -> *mut T { *self.buf.ptr } - - fn cap(&self) -> usize { self.buf.cap } - - pub fn new() -> Self { - Vec { buf: RawVec::new(), len: 0 } - } - - // push/pop/insert/remove largely unchanged: - // * `self.ptr -> self.ptr()` - // * `self.cap -> self.cap()` - // * `self.grow -> self.buf.grow()` -} - -impl Drop for Vec { - fn drop(&mut self) { - while let Some(_) = self.pop() {} - // deallocation is handled by RawVec - } -} -``` - -And finally we can really simplify IntoIter: - -```rust -struct IntoIter { - _buf: RawVec, // we don't actually care about this. Just need it to live. - start: *const T, - end: *const T, -} - -// next and next_back litterally unchanged since they never referred to the buf - -impl Drop for IntoIter { - fn drop(&mut self) { - // only need to ensure all our elements are read; - // buffer will clean itself up afterwards. - for _ in &mut *self {} - } -} - -impl Vec { - pub fn into_iter(self) -> IntoIter { - unsafe { - // need to use ptr::read to unsafely move the buf out since it's - // not Copy. - let buf = ptr::read(&self.buf); - let len = self.len; - mem::forget(self); - - IntoIter { - start: *buf.ptr, - end: buf.ptr.offset(len as isize), - _buf: buf, - } - } - } -} -``` - -Much better. - - - - - -# Drain - -Let's move on to Drain. Drain is largely the same as IntoIter, except that -instead of consuming the Vec, it borrows the Vec and leaves its allocation -free. For now we'll only implement the "basic" full-range version. - -```rust,ignore -use std::marker::PhantomData; - -struct Drain<'a, T: 'a> { - vec: PhantomData<&'a mut Vec> - start: *const T, - end: *const T, -} - -impl<'a, T> Iterator for Drain<'a, T> { - type Item = T; - fn next(&mut self) -> Option { - if self.start == self.end { - None -``` - --- wait, this is seeming familiar. Let's do some more compression. Both -IntoIter and Drain have the exact same structure, let's just factor it out. - -```rust -struct RawValIter { - start: *const T, - end: *const T, -} - -impl RawValIter { - // unsafe to construct because it has no associated lifetimes. - // This is necessary to store a RawValIter in the same struct as - // its actual allocation. OK since it's a private implementation - // detail. - unsafe fn new(slice: &[T]) -> Self { - RawValIter { - start: slice.as_ptr(), - end: if slice.len() == 0 { - slice.as_ptr() - } else { - slice.as_ptr().offset(slice.len() as isize) - } - } - } -} - -// Iterator and DoubleEndedIterator impls identical to IntoIter. -``` - -And IntoIter becomes the following: - -``` -pub struct IntoIter { - _buf: RawVec, // we don't actually care about this. Just need it to live. - iter: RawValIter, -} - -impl Iterator for IntoIter { - type Item = T; - fn next(&mut self) -> Option { self.iter.next() } - fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } -} - -impl DoubleEndedIterator for IntoIter { - fn next_back(&mut self) -> Option { self.iter.next_back() } -} - -impl Drop for IntoIter { - fn drop(&mut self) { - for _ in &mut self.iter {} - } -} - -impl Vec { - pub fn into_iter(self) -> IntoIter { - unsafe { - let iter = RawValIter::new(&self); - let buf = ptr::read(&self.buf); - mem::forget(self); - - IntoIter { - iter: iter, - _buf: buf, - } - } - } -} -``` - -Note that I've left a few quirks in this design to make upgrading Drain to work -with arbitrary subranges a bit easier. In particular we *could* have RawValIter -drain itself on drop, but that won't work right for a more complex Drain. -We also take a slice to simplify Drain initialization. - -Alright, now Drain is really easy: - -```rust -use std::marker::PhantomData; - -pub struct Drain<'a, T: 'a> { - vec: PhantomData<&'a mut Vec>, - iter: RawValIter, -} - -impl<'a, T> Iterator for Drain<'a, T> { - type Item = T; - fn next(&mut self) -> Option { self.iter.next_back() } - fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } -} - -impl<'a, T> DoubleEndedIterator for Drain<'a, T> { - fn next_back(&mut self) -> Option { self.iter.next_back() } -} - -impl<'a, T> Drop for Drain<'a, T> { - fn drop(&mut self) { - for _ in &mut self.iter {} - } -} - -impl Vec { - pub fn drain(&mut self) -> Drain { - // this is a mem::forget safety thing. If Drain is forgotten, we just - // leak the whole Vec's contents. Also we need to do this *eventually* - // anyway, so why not do it now? - self.len = 0; - - unsafe { - Drain { - iter: RawValIter::new(&self), - vec: PhantomData, - } - } - } -} -``` - - - - -# Handling Zero-Sized Types - -It's time. We're going to fight the spectre that is zero-sized types. Safe Rust -*never* needs to care about this, but Vec is very intensive on raw pointers and -raw allocations, which are exactly the *only* two things that care about -zero-sized types. We need to be careful of two things: - -* The raw allocator API has undefined behaviour if you pass in 0 for an - allocation size. -* raw pointer offsets are no-ops for zero-sized types, which will break our - C-style pointer iterator. - -Thankfully we abstracted out pointer-iterators and allocating handling into -RawValIter and RawVec respectively. How mysteriously convenient. - - - - -## Allocating Zero-Sized Types - -So if the allocator API doesn't support zero-sized allocations, what on earth -do we store as our allocation? Why, `heap::EMPTY` of course! Almost every operation -with a ZST is a no-op since ZSTs have exactly one value, and therefore no state needs -to be considered to store or load them. This actually extends to `ptr::read` and -`ptr::write`: they won't actually look at the pointer at all. As such we *never* need -to change the pointer. - -Note however that our previous reliance on running out of memory before overflow is -no longer valid with zero-sized types. We must explicitly guard against capacity -overflow for zero-sized types. - -Due to our current architecture, all this means is writing 3 guards, one in each -method of RawVec. - -```rust -impl RawVec { - fn new() -> Self { - unsafe { - // !0 is usize::MAX. This branch should be stripped at compile time. - let cap = if mem::size_of::() == 0 { !0 } else { 0 }; - - // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" - RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } - } - } - - fn grow(&mut self) { - unsafe { - let elem_size = mem::size_of::(); - - // since we set the capacity to usize::MAX when elem_size is - // 0, getting to here necessarily means the Vec is overfull. - assert!(elem_size != 0, "capacity overflow"); - - let align = mem::min_align_of::(); - - let (new_cap, ptr) = if self.cap == 0 { - let ptr = heap::allocate(elem_size, align); - (1, ptr) - } else { - let new_cap = 2 * self.cap; - let ptr = heap::reallocate(*self.ptr as *mut _, - self.cap * elem_size, - new_cap * elem_size, - align); - (new_cap, ptr) - }; - - // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { oom() } - - self.ptr = Unique::new(ptr as *mut _); - self.cap = new_cap; - } - } -} - -impl Drop for RawVec { - fn drop(&mut self) { - let elem_size = mem::size_of::(); - - // don't free zero-sized allocations, as they were never allocated. - if self.cap != 0 && elem_size != 0 { - let align = mem::min_align_of::(); - - let num_bytes = elem_size * self.cap; - unsafe { - heap::deallocate(*self.ptr as *mut _, num_bytes, align); - } - } - } -} -``` - -That's it. We support pushing and popping zero-sized types now. Our iterators -(that aren't provided by slice Deref) are still busted, though. - - - - -## Iterating Zero-Sized Types - -Zero-sized offsets are no-ops. This means that our current design will always -initialize `start` and `end` as the same value, and our iterators will yield -nothing. The current solution to this is to cast the pointers to integers, -increment, and then cast them back: - -``` -impl RawValIter { - unsafe fn new(slice: &[T]) -> Self { - RawValIter { - start: slice.as_ptr(), - end: if mem::size_of::() == 0 { - ((slice.as_ptr() as usize) + slice.len()) as *const _ - } else if slice.len() == 0 { - slice.as_ptr() - } else { - slice.as_ptr().offset(slice.len() as isize) - } - } - } -} -``` - -Now we have a different bug. Instead of our iterators not running at all, our -iterators now run *forever*. We need to do the same trick in our iterator impls. -Also, our size_hint computation code will divide by 0 for ZSTs. Since we'll -basically be treating the two pointers as if they point to bytes, we'll just -map size 0 to divide by 1. - -``` -impl Iterator for RawValIter { - type Item = T; - fn next(&mut self) -> Option { - if self.start == self.end { - None - } else { - unsafe { - let result = ptr::read(self.start); - self.start = if mem::size_of::() == 0 { - (self.start as usize + 1) as *const _ - } else { - self.start.offset(1); - } - Some(result) - } - } - } - - fn size_hint(&self) -> (usize, Option) { - let elem_size = mem::size_of::(); - let len = (self.end as usize - self.start as usize) - / if elem_size == 0 { 1 } else { elem_size }; - (len, Some(len)) - } -} - -impl DoubleEndedIterator for RawValIter { - fn next_back(&mut self) -> Option { - if self.start == self.end { - None - } else { - unsafe { - self.end = if mem::size_of::() == 0 { - (self.end as usize - 1) as *const _ - } else { - self.end.offset(-1); - } - Some(ptr::read(self.end)) - } - } - } -} -``` - -And that's it. Iteration works! - - - -# Advanced Drain - -TODO? Not clear if informative - - - - - -# The Final Code - -```rust -#![feature(unique)] -#![feature(heap_api)] - -use std::ptr::{Unique, self}; -use std::rt::heap; -use std::mem; -use std::ops::{Deref, DerefMut}; -use std::marker::PhantomData; - - - - - -struct RawVec { - ptr: Unique, - cap: usize, -} - -impl RawVec { - fn new() -> Self { - unsafe { - // !0 is usize::MAX. This branch should be stripped at compile time. - let cap = if mem::size_of::() == 0 { !0 } else { 0 }; - - // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" - RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } - } - } - - fn grow(&mut self) { - unsafe { - let elem_size = mem::size_of::(); - - // since we set the capacity to usize::MAX when elem_size is - // 0, getting to here necessarily means the Vec is overfull. - assert!(elem_size != 0, "capacity overflow"); - - let align = mem::min_align_of::(); - - let (new_cap, ptr) = if self.cap == 0 { - let ptr = heap::allocate(elem_size, align); - (1, ptr) - } else { - let new_cap = 2 * self.cap; - let ptr = heap::reallocate(*self.ptr as *mut _, - self.cap * elem_size, - new_cap * elem_size, - align); - (new_cap, ptr) - }; - - // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { oom() } - - self.ptr = Unique::new(ptr as *mut _); - self.cap = new_cap; - } - } -} - -impl Drop for RawVec { - fn drop(&mut self) { - let elem_size = mem::size_of::(); - if self.cap != 0 && elem_size != 0 { - let align = mem::min_align_of::(); - - let num_bytes = elem_size * self.cap; - unsafe { - heap::deallocate(*self.ptr as *mut _, num_bytes, align); - } - } - } -} - - - - - -pub struct Vec { - buf: RawVec, - len: usize, -} - -impl Vec { - fn ptr(&self) -> *mut T { *self.buf.ptr } - - fn cap(&self) -> usize { self.buf.cap } - - pub fn new() -> Self { - Vec { buf: RawVec::new(), len: 0 } - } - pub fn push(&mut self, elem: T) { - if self.len == self.cap() { self.buf.grow(); } - - unsafe { - ptr::write(self.ptr().offset(self.len as isize), elem); - } - - // Can't fail, we'll OOM first. - self.len += 1; - } - - pub fn pop(&mut self) -> Option { - if self.len == 0 { - None - } else { - self.len -= 1; - unsafe { - Some(ptr::read(self.ptr().offset(self.len as isize))) - } - } - } - - pub fn insert(&mut self, index: usize, elem: T) { - assert!(index <= self.len, "index out of bounds"); - if self.cap() == self.len { self.buf.grow(); } - - unsafe { - if index < self.len { - ptr::copy(self.ptr().offset(index as isize), - self.ptr().offset(index as isize + 1), - self.len - index); - } - ptr::write(self.ptr().offset(index as isize), elem); - self.len += 1; - } - } - - pub fn remove(&mut self, index: usize) -> T { - assert!(index < self.len, "index out of bounds"); - unsafe { - self.len -= 1; - let result = ptr::read(self.ptr().offset(index as isize)); - ptr::copy(self.ptr().offset(index as isize + 1), - self.ptr().offset(index as isize), - self.len - index); - result - } - } - - pub fn into_iter(self) -> IntoIter { - unsafe { - let iter = RawValIter::new(&self); - let buf = ptr::read(&self.buf); - mem::forget(self); - - IntoIter { - iter: iter, - _buf: buf, - } - } - } - - pub fn drain(&mut self) -> Drain { - // this is a mem::forget safety thing. If this is forgotten, we just - // leak the whole Vec's contents. Also we need to do this *eventually* - // anyway, so why not do it now? - self.len = 0; - unsafe { - Drain { - iter: RawValIter::new(&self), - vec: PhantomData, - } - } - } -} - -impl Drop for Vec { - fn drop(&mut self) { - while let Some(_) = self.pop() {} - // allocation is handled by RawVec - } -} - -impl Deref for Vec { - type Target = [T]; - fn deref(&self) -> &[T] { - unsafe { - ::std::slice::from_raw_parts(self.ptr(), self.len) - } - } -} - -impl DerefMut for Vec { - fn deref_mut(&mut self) -> &mut [T] { - unsafe { - ::std::slice::from_raw_parts_mut(self.ptr(), self.len) - } - } -} - - - - - -struct RawValIter { - start: *const T, - end: *const T, -} - -impl RawValIter { - unsafe fn new(slice: &[T]) -> Self { - RawValIter { - start: slice.as_ptr(), - end: if mem::size_of::() == 0 { - ((slice.as_ptr() as usize) + slice.len()) as *const _ - } else if slice.len() == 0 { - slice.as_ptr() - } else { - slice.as_ptr().offset(slice.len() as isize) - } - } - } -} - -impl Iterator for RawValIter { - type Item = T; - fn next(&mut self) -> Option { - if self.start == self.end { - None - } else { - unsafe { - let result = ptr::read(self.start); - self.start = self.start.offset(1); - Some(result) - } - } - } - - fn size_hint(&self) -> (usize, Option) { - let elem_size = mem::size_of::(); - let len = (self.end as usize - self.start as usize) - / if elem_size == 0 { 1 } else { elem_size }; - (len, Some(len)) - } -} - -impl DoubleEndedIterator for RawValIter { - fn next_back(&mut self) -> Option { - if self.start == self.end { - None - } else { - unsafe { - self.end = self.end.offset(-1); - Some(ptr::read(self.end)) - } - } - } -} - - - - -pub struct IntoIter { - _buf: RawVec, // we don't actually care about this. Just need it to live. - iter: RawValIter, -} - -impl Iterator for IntoIter { - type Item = T; - fn next(&mut self) -> Option { self.iter.next() } - fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } -} - -impl DoubleEndedIterator for IntoIter { - fn next_back(&mut self) -> Option { self.iter.next_back() } -} - -impl Drop for IntoIter { - fn drop(&mut self) { - for _ in &mut *self {} - } -} - - - - -pub struct Drain<'a, T: 'a> { - vec: PhantomData<&'a mut Vec>, - iter: RawValIter, -} - -impl<'a, T> Iterator for Drain<'a, T> { - type Item = T; - fn next(&mut self) -> Option { self.iter.next_back() } - fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } -} - -impl<'a, T> DoubleEndedIterator for Drain<'a, T> { - fn next_back(&mut self) -> Option { self.iter.next_back() } -} - -impl<'a, T> Drop for Drain<'a, T> { - fn drop(&mut self) { - // pre-drain the iter - for _ in &mut self.iter {} - } -} - -/// Abort the process, we're out of memory! -/// -/// In practice this is probably dead code on most OSes -fn oom() { - ::std::process::exit(-1); -} -``` diff --git a/working-with-unsafe.md b/working-with-unsafe.md new file mode 100644 index 000000000000..672513246619 --- /dev/null +++ b/working-with-unsafe.md @@ -0,0 +1,88 @@ +% Working with Unsafe + +Rust generally only gives us the tools to talk about safety in a scoped and +binary manner. Unfortunately reality is significantly more complicated than that. +For instance, consider the following toy function: + +```rust +fn do_idx(idx: usize, arr: &[u8]) -> Option { + if idx < arr.len() { + unsafe { + Some(*arr.get_unchecked(idx)) + } + } else { + None + } +} +``` + +Clearly, this function is safe. We check that the index is in bounds, and if it +is, index into the array in an unchecked manner. But even in such a trivial +function, the scope of the unsafe block is questionable. Consider changing the +`<` to a `<=`: + +```rust +fn do_idx(idx: usize, arr: &[u8]) -> Option { + if idx <= arr.len() { + unsafe { + Some(*arr.get_unchecked(idx)) + } + } else { + None + } +} +``` + +This program is now unsound, an yet *we only modified safe code*. This is the +fundamental problem of safety: it's non-local. The soundness of our unsafe +operations necessarily depends on the state established by "safe" operations. +Although safety *is* modular (we *still* don't need to worry about about +unrelated safety issues like uninitialized memory), it quickly contaminates the +surrounding code. + +Trickier than that is when we get into actual statefulness. Consider a simple +implementation of `Vec`: + +```rust +// Note this defintion is insufficient. See the section on lifetimes. +struct Vec { + ptr: *mut T, + len: usize, + cap: usize, +} + +// Note this implementation does not correctly handle zero-sized types. +// We currently live in a nice imaginary world of only positive fixed-size +// types. +impl Vec { + fn push(&mut self, elem: T) { + if self.len == self.cap { + // not important for this example + self.reallocate(); + } + unsafe { + ptr::write(self.ptr.offset(len as isize), elem); + self.len += 1; + } + } +} +``` + +This code is simple enough to reasonably audit and verify. Now consider +adding the following method: + +```rust + fn make_room(&mut self) { + // grow the capacity + self.cap += 1; + } +``` + +This code is safe, but it is also completely unsound. Changing the capacity +violates the invariants of Vec (that `cap` reflects the allocated space in the +Vec). This is not something the rest of `Vec` can guard against. It *has* to +trust the capacity field because there's no way to verify it. + +`unsafe` does more than pollute a whole function: it pollutes a whole *module*. +Generally, the only bullet-proof way to limit the scope of unsafe code is at the +module boundary with privacy. From 59ff3a39ae866b862678a769f469f0bae55606e5 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 6 Jul 2015 20:25:14 -0700 Subject: [PATCH 046/104] expand on ctors --- constructors.md | 71 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/constructors.md b/constructors.md index 8069776c0aaf..99bcf5e283ee 100644 --- a/constructors.md +++ b/constructors.md @@ -1,26 +1,55 @@ % Constructors -Unlike C++, Rust does not come with a slew of builtin -kinds of constructor. There are no Copy, Default, Assignment, Move, or whatever constructors. -This largely has to do with Rust's philosophy of being explicit. +There is exactly one way to create an instance of a user-defined type: name it, +and initialize all its fields at once: -Move constructors are meaningless in Rust because we don't enable types to "care" about their -location in memory. Every type must be ready for it to be blindly memcopied to somewhere else -in memory. This means pure on-the-stack-but-still-movable intrusive linked lists are simply -not happening in Rust (safely). +```rust +struct Foo { + a: u8, + b: u32, + c: bool, +} -Assignment and copy constructors similarly don't exist because move semantics are the *default* -in rust. At most `x = y` just moves the bits of y into the x variable. Rust does provide two -facilities for going back to C++'s copy-oriented semantics: `Copy` and `Clone`. Clone is our -moral equivalent of a copy constructor, but it's never implicitly invoked. You have to explicitly -call `clone` on an element you want to be cloned. Copy is a special case of Clone where the -implementation is just "copy the bits". Copy types *are* implicitly -cloned whenever they're moved, but because of the definition of Copy this just means *not* -treating the old copy as uninitialized -- a no-op. +enum Bar { + X(u32), + Y(bool), +} -While Rust provides a `Default` trait for specifying the moral equivalent of a default -constructor, it's incredibly rare for this trait to be used. This is because variables -[aren't implicitly initialized][uninit]. Default is basically only useful for generic -programming. In concrete contexts, a type will provide a static `new` method for any -kind of "default" constructor. This has no relation to `new` in other -languages and has no special meaning. It's just a naming convention. \ No newline at end of file +struct Empty; + +let foo = Foo { a: 0, b: 1, c: false }; +let bar = Bar::X(0); +let empty = Empty; +``` + +That's it. Every other way you make an instance of a type is just calling a +totally vanilla function that does some stuff and eventually bottoms out to The +One True Constructor. + +Unlike C++, Rust does not come with a slew of built in kinds of constructor. +There are no Copy, Default, Assignment, Move, or whatever constructors. The +reasons for this are varied, but it largely boils down to Rust's philosophy +of *being explicit*. + +Move constructors are meaningless in Rust because we don't enable types to +"care" about their location in memory. Every type must be ready for it to be +blindly memcopied to somewhere else in memory. This means pure on-the-stack-but- +still-movable intrusive linked lists are simply not happening in Rust (safely). + +Assignment and copy constructors similarly don't exist because move semantics +are the *only* semantics in Rust. At most `x = y` just moves the bits of y into the x +variable. Rust *does* provide two facilities for providing C++'s copy-oriented +semantics: `Copy` and `Clone`. Clone is our moral equivalent of a copy +constructor, but it's never implicitly invoked. You have to explicitly call +`clone` on an element you want to be cloned. Copy is a special case of Clone +where the implementation is just "copy the bits". Copy types *are* implicitly +cloned whenever they're moved, but because of the definition of Copy this just +means *not* treating the old copy as uninitialized -- a no-op. + +While Rust provides a `Default` trait for specifying the moral equivalent of a +default constructor, it's incredibly rare for this trait to be used. This is +because variables [aren't implicitly initialized][uninit]. Default is basically +only useful for generic programming. In concrete contexts, a type will provide a +static `new` method for any kind of "default" constructor. This has no relation +to `new` in other languages and has no special meaning. It's just a naming +convention. From adcd30c5a2aa732174b0c5deba3f4b9c9a9a44d0 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 6 Jul 2015 20:28:11 -0700 Subject: [PATCH 047/104] mdinger fix --- safe-unsafe-meaning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/safe-unsafe-meaning.md b/safe-unsafe-meaning.md index 8a6300a061d2..6c3d4087b819 100644 --- a/safe-unsafe-meaning.md +++ b/safe-unsafe-meaning.md @@ -98,7 +98,7 @@ destructors will be successfully called! Hooray! However BTreeMap is implemented using a modest spoonful of Unsafe (most collections are). That means that it is not necessarily *trivially true* that a bad Ord -implementation will make BTreeMap behave safely. Unsafe most be sure not to rely +implementation will make BTreeMap behave safely. Unsafe must be sure not to rely on Ord *where safety is at stake*, because Ord is provided by Safe, and memory safety is not Safe's responsibility to uphold. *It must be impossible for Safe code to violate memory safety*. From 5ec12b154bcc839f9a903f238791b6010a61418b Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 6 Jul 2015 23:36:10 -0700 Subject: [PATCH 048/104] cleanup --- subtyping.md | 84 ++++++++++++++++++++++++++++------------------------ unwinding.md | 19 ++++++------ 2 files changed, 56 insertions(+), 47 deletions(-) diff --git a/subtyping.md b/subtyping.md index 733e015dbd7d..31aba0adbf98 100644 --- a/subtyping.md +++ b/subtyping.md @@ -2,22 +2,23 @@ Although Rust doesn't have any notion of inheritance, it *does* include subtyping. In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes are scopes, -we can partially order them based on a *contains* (outlives) relationship. We -can even express this as a generic bound: `T: 'a` specifies that whatever scope `T` -is valid for must contain the scope `'a` ("T outlives `'a`"). +we can partially order them based on the *contains* (outlives) relationship. We +can even express this as a generic bound. -We can then define subtyping on lifetimes in terms of that relationship: if `'a: 'b` +Subtyping on lifetimes in terms of that relationship: if `'a: 'b` ("a contains b" or "a outlives b"), then `'a` is a subtype of `'b`. This is a large source of confusion, because it seems intuitively backwards to many: the bigger scope is a *sub type* of the smaller scope. -This does in fact make sense. The intuitive reason for this is that if you expect an -`&'a u8`, then it's totally fine for me to hand you an `&'static u8`, in the same way -that if you expect an Animal in Java, it's totally fine for me to hand you a Cat. -Cats are just Animals *and more*, just as `'static` is just `'a` *and more*. +This does in fact make sense, though. The intuitive reason for this is that if +you expect an `&'a u8`, then it's totally fine for me to hand you an `&'static u8`, +in the same way that if you expect an Animal in Java, it's totally fine for me to +hand you a Cat. Cats are just Animals *and more*, just as `'static` is just `'a` +*and more*. (Note, the subtyping relationship and typed-ness of lifetimes is a fairly arbitrary -construct that some disagree with. I just find that it simplifies this analysis.) +construct that some disagree with. However it simplifies our analysis to treat +lifetimes and types uniformly.) Higher-ranked lifetimes are also subtypes of every concrete lifetime. This is because taking an arbitrary lifetime is strictly more general than taking a specific one. @@ -26,15 +27,15 @@ taking an arbitrary lifetime is strictly more general than taking a specific one # Variance -Variance is where things get really harsh. +Variance is where things get a bit complicated. Variance is a property that *type constructors* have. A type constructor in Rust is a generic type with unbound arguments. For instance `Vec` is a type constructor that takes a `T` and returns a `Vec`. `&` and `&mut` are type constructors that -take a lifetime and a type. +take a two types: a lifetime, and a type to point to. -A type constructor's *variance* is how the subtypes of its inputs affects the -subtypes of its outputs. There are three kinds of variance: +A type constructor's *variance* is how the subtyping of its inputs affects the +subtyping of its outputs. There are two kinds of variance in Rust: * F is *variant* if `T` being a subtype of `U` implies `F` is a subtype of `F` * F is *invariant* otherwise (no subtyping relation can be derived) @@ -60,42 +61,47 @@ needed. To see why `&mut` should be invariant, consider the following code: -```rust +```rust,ignore +fn overwrite(input: &mut T, new: &mut T) { + *input = *new; +} + fn main() { let mut forever_str: &'static str = "hello"; { let string = String::from("world"); overwrite(&mut forever_str, &mut &*string); } + // Oops, printing free'd memory println!("{}", forever_str); } - -fn overwrite(input: &mut T, new: &mut T) { - *input = *new; -} ``` -The signature of `overwrite` is clearly valid: it takes mutable references to two values -of the same type, and overwrites one with the other. We have seen already that `&` is -variant, and `'static` is a subtype of *any* `'a`, so `&'static str` is a -subtype of `&'a str`. Therefore, if `&mut` was -*also* variant, then the lifetime of the `&'static str` would successfully be -"shrunk" down to the shorter lifetime of the string, and `overwrite` would be -called successfully. The string would subsequently be dropped, and `forever_str` -would point to freed memory when we print it! +The signature of `overwrite` is clearly valid: it takes mutable references to +two values of the same type, and overwrites one with the other. If `&mut` was +variant, then `&mut &'a str` would be a subtype of `&mut &'static str`, since +`&'a str` is a subtype of `&'static str`. Therefore the lifetime of +`forever_str` would successfully be "shrunk" down to the shorter lifetime of +`string`, and `overwrite` would be called successfully. `string` would +subsequently be dropped, and `forever_str` would point to freed memory when we +print it! Therefore `&mut` should be invariant. -Therefore `&mut` should be invariant. This is the general theme of variance vs +This is the general theme of variance vs invariance: if variance would allow you to *store* a short-lived value in a longer-lived slot, then you must be invariant. `Box` and `Vec` are interesting cases because they're variant, but you can -definitely store values in them! This is fine because *you can only store values -in them through a mutable reference*! The mutable reference makes the whole type -invariant, and therefore prevents you from getting in trouble. +definitely store values in them! This is where Rust gets really clever: it's +fine for them to be variant because you can only store values +in them *via a mutable reference*! The mutable reference makes the whole type +invariant, and therefore prevents you from smuggling a short-lived type into +them. -Being variant allows them to be variant when shared immutably (so you can pass -a `&Box<&'static str>` where a `&Box<&'a str>` is expected). It also allows you to -forever weaken the type by moving it into a weaker slot. That is, you can do: +Being variant *does* allows them to be weakened when shared immutably. +So you can pass a `&Box<&'static str>` where a `&Box<&'a str>` is expected. + +However what should happen when passing *by-value* is less obvious. It turns out +that, yes, you can use subtyping when passing by-value. That is, this works: ```rust fn get_box<'a>(&'a u8) -> Box<&'a str> { @@ -104,14 +110,16 @@ fn get_box<'a>(&'a u8) -> Box<&'a str> { } ``` -which is fine because unlike the mutable borrow case, there's no one else who -"remembers" the old lifetime in the box. +Weakening when you pass by-value is fine because there's no one else who +"remembers" the old lifetime in the Box. The reason a variant `&mut` was +trouble was because there's always someone else who remembers the original +subtype: the actual owner. -The variance of the cell types similarly follows. `&` is like an `&mut` for a +The invariance of the cell types can be seen as follows: `&` is like an `&mut` for a cell, because you can still store values in them through an `&`. Therefore cells must be invariant to avoid lifetime smuggling. -`Fn` is the most subtle case, because it has mixed variance. To see why +`Fn` is the most subtle case because it has mixed variance. To see why `Fn(T) -> U` should be invariant over T, consider the following function signature: @@ -120,7 +128,7 @@ signature: fn foo(&'a str) -> usize; ``` -This signature claims that it can handle any &str that lives *at least* as long +This signature claims that it can handle any `&str` that lives *at least* as long as `'a`. Now if this signature was variant with respect to `&str`, that would mean ```rust diff --git a/unwinding.md b/unwinding.md index 925f30423662..052689655028 100644 --- a/unwinding.md +++ b/unwinding.md @@ -263,17 +263,18 @@ impl BinaryHeap { Although all unsafe code *must* ensure some minimal level of exception safety, some types may choose to explicitly *poison* themselves if they witness a panic. -The most notable example of this is the standard library's Mutex type. A Mutex -will poison itself if one of its MutexGuards (the thing it returns when a lock -is obtained) is dropped during a panic. Any future attempts to lock the Mutex -will return an `Err`. +Poisoning doesn't entail anything in particular. Generally it just means +preventing normal usage from proceeding. The most notable example of this is the +standard library's Mutex type. A Mutex will poison itself if one of its +MutexGuards (the thing it returns when a lock is obtained) is dropped during a +panic. Any future attempts to lock the Mutex will return an `Err`. Mutex poisons not for *true* safety in the sense that Rust normally cares about. It poisons as a safety-guard against blindly using the data that comes out of a Mutex that has witnessed a panic while locked. The data in such a Mutex was likely in the middle of being modified, and as such may be in an inconsistent or incomplete state. It is important to note that one cannot violate memory safety with such a type -if it is correctly written. After all, it must be exception safe! +if it is correctly written. After all, it must be minimally exception safe! However if the Mutex contained, say, a BinaryHeap that does not actually have the heap property, it's unlikely that any code that uses it will do @@ -288,7 +289,7 @@ the Err exposes a method to get the lock anyway. It *is* safe, after all. Rust's unwinding strategy is not specified to be fundamentally compatible with any other language's unwinding. As such, unwinding into Rust from another language, or unwinding into another language from Rust is Undefined Behaviour. -What you do at that point is up to you, but you must *absolutely* catch any -panics at the FFI boundary! At best, your application will crash and burn. At -worst, your application *won't* crash and burn, and will proceed with completely -clobbered state. +You must *absolutely* catch any panics at the FFI boundary! What you do at that +point is up to you, but *something* must be done. If you fail to do this, +at best, your application will crash and burn. At worst, your application *won't* +crash and burn, and will proceed with completely clobbered state. From 35b8001f684399992978c60fcb3d51232b3ca85d Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 6 Jul 2015 23:37:44 -0700 Subject: [PATCH 049/104] cleanup --- subtyping.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subtyping.md b/subtyping.md index 31aba0adbf98..24f974ca73ac 100644 --- a/subtyping.md +++ b/subtyping.md @@ -48,11 +48,11 @@ interactions with other features.) Some important variances: * `&` is variant (as is `*const` by metaphor) -* `&mut` is invariant (as is `*mut` by metaphor) +* `&mut` is invariant * `Fn(T) -> U` is invariant with respect to `T`, but variant with respect to `U` * `Box`, `Vec`, and all other collections are variant * `UnsafeCell`, `Cell`, `RefCell`, `Mutex` and all "interior mutability" - types are invariant + types are invariant (as is `*mut` by metaphor) To understand why these variances are correct and desirable, we will consider several examples. We have already covered why `&` should be variant when introducing subtyping: @@ -158,7 +158,7 @@ in its place. Therefore functions *are* variant over their return type. `*const` has the exact same semantics as `&`, so variance follows. `*mut` on the other hand can dereference to an &mut whether shared or not, so it is marked -as invariant in analogy to cells. +as invariant just like cells. This is all well and good for the types the standard library provides, but how is variance determined for type that *you* define? A struct, informally From 987a8687db1a2a5a9388265a6bb5a1590a05dd69 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 7 Jul 2015 09:33:20 -0700 Subject: [PATCH 050/104] split out and rework drop flags section --- SUMMARY.md | 1 + checked-uninit.md | 24 --------------- drop-flags.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 24 deletions(-) create mode 100644 drop-flags.md diff --git a/SUMMARY.md b/SUMMARY.md index 225708e21869..3b5a04c5a3eb 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -23,6 +23,7 @@ * [Transmutes](transmutes.md) * [Uninitialized Memory](uninitialized.md) * [Checked](checked-uninit.md) + * [Drop Flags](drop-flags.md) * [Unchecked](unchecked-uninit.md) * [Ownership-Oriented Resource Management](raii.md) * [Constructors](constructors.md) diff --git a/checked-uninit.md b/checked-uninit.md index e39a329bfd29..8896fc9de019 100644 --- a/checked-uninit.md +++ b/checked-uninit.md @@ -83,27 +83,3 @@ fn main() { However reassigning `y` in this example *would* require `y` to be marked as mutable, as a Safe Rust program could observe that the value of `y` changed. Otherwise the variable is exactly like new. - -This raises an interesting question with respect to `Drop`: where does Rust try -to call the destructor of a variable that is conditionally initialized? It turns -out that Rust actually tracks whether a type should be dropped or not *at -runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for -that variable is set and unset. When a variable goes out of scope or is assigned -a value, it evaluates whether the current value of the variable should be dropped. -Of course, static analysis can remove these checks. If the compiler can prove that -a value is guaranteed to be either initialized or not, then it can theoretically -generate more efficient code! As such it may be desirable to structure code to -have *static drop semantics* when possible. - -As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden -field of any type that implements Drop. The language sets the drop flag by -overwriting the entire struct with a particular value. This is pretty obviously -Not The Fastest and causes a bunch of trouble with optimizing code. As such work -is currently under way to move the flags out onto the stack frame where they -more reasonably belong. Unfortunately this work will take some time as it -requires fairly substantial changes to the compiler. - -So in general, Rust programs don't need to worry about uninitialized values on -the stack for correctness. Although they might care for performance. Thankfully, -Rust makes it easy to take control here! Uninitialized values are there, and -Safe Rust lets you work with them, but you're never in danger. diff --git a/drop-flags.md b/drop-flags.md new file mode 100644 index 000000000000..2d5bae6dcfe9 --- /dev/null +++ b/drop-flags.md @@ -0,0 +1,78 @@ +% Drop Flags + +The examples in the previous section introduce an interesting problem for Rust. +We have seen that's possible to conditionally initialize, deinitialize, and +*reinitialize* locations of memory totally safely. For Copy types, this isn't +particularly notable since they're just a random pile of bits. However types with +destructors are a different story: Rust needs to know whether to call a destructor +whenever a variable is assigned to, or a variable goes out of scope. How can it +do this with conditional initialization? + +It turns out that Rust actually tracks whether a type should be dropped or not *at +runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for +that variable is toggled. When a variable *might* need to be dropped, this flag +is evaluated to determine if it *should* be dropped. + +Of course, it is *often* the case that a value's initialization state can be +*statically* known at every point in the program. If this is the case, then the +compiler can theoretically generate more effecient code! For instance, +straight-line code has such *static drop semantics*: + +```rust +let mut x = Box::new(0); // x was uninit +let mut y = x; // y was uninit +x = Box::new(0); // x was uninit +y = x; // y was init; Drop y! + // y was init; Drop y! + // x was uninit +``` + +And even branched code where all branches have the same behaviour with respect +to initialization: + +```rust +let mut x = Box::new(0); // x was uninit +if condition { + drop(x) // x gets moved out +} else { + println!("{}", x); + drop(x) // x gets moved out +} +x = Box::new(0); // x was uninit + // x was init; Drop x! +``` + +However code like this *requires* runtime information to correctly Drop: + +```rust +let x; +if condition { + x = Box::new(0); // x was uninit + println!("{}", x); +} + // x might be uninit; check the flag! +``` + +Of course, in this case it's trivial to retrieve static drop semantics: + +```rust +if condition { + let x = Box::new(0); + println!("{}", x); +} +``` + +As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden +field of any type that implements Drop. Rust sets the drop flag by +overwriting the *entire* value with a particular byte. This is pretty obviously +Not The Fastest and causes a bunch of trouble with optimizing code. It's legacy +from a time when you could do much more complex conditional initialization. + +As such work is currently under way to move the flags out onto the stack frame +where they more reasonably belong. Unfortunately, this work will take some time +as it requires fairly substantial changes to the compiler. + +Regardless, Rust programs don't need to worry about uninitialized values on +the stack for correctness. Although they might care for performance. Thankfully, +Rust makes it easy to take control here! Uninitialized values are there, and +you can work with them in Safe Rust, but you're *never* in danger. \ No newline at end of file From 50d8656945513c6b327122e5a40650c66baa87cb Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 7 Jul 2015 09:39:21 -0700 Subject: [PATCH 051/104] void types --- exotic-sizes.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/exotic-sizes.md b/exotic-sizes.md index 8e05485055f7..ea8dc86d1f0a 100644 --- a/exotic-sizes.md +++ b/exotic-sizes.md @@ -3,6 +3,10 @@ Most of the time, we think in terms of types with a fixed, positive size. This is not always the case, however. + + + + # Dynamically Sized Types (DSTs) Rust also supports types without a statically known size. On the surface, @@ -34,19 +38,20 @@ a variable position based on its alignment.** + + # Zero Sized Types (ZSTs) Rust actually allows types to be specified that occupy *no* space: ```rust struct Foo; // No fields = no size -enum Bar; // No variants = no size // All fields have no size = no size struct Baz { foo: Foo, - bar: Bar, - qux: (), // empty tuple has no size + qux: (), // empty tuple has no size + baz: [u8; 0], // empty array has no size } ``` @@ -67,3 +72,16 @@ standard allocators (including jemalloc, the one used by Rust) generally conside passing in `0` as Undefined Behaviour. + + + +# Void Types + +Rust also enables types to be declared that *cannot even be instantiated*. These +types can only be talked about at the type level, and never at the value level. + +```rust +enum Foo { } // No variants = VOID +``` + +TODO: WHY?! \ No newline at end of file From 2e653f3cce3e5a75861c7c6b9b08729f16b967bf Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 7 Jul 2015 09:48:57 -0700 Subject: [PATCH 052/104] shard out concurrency --- SUMMARY.md | 3 + atomics.md | 47 +++++++++++ concurrency.md | 214 ++--------------------------------------------- races.md | 66 +++++++++++++++ send-and-sync.md | 76 +++++++++++++++++ 5 files changed, 197 insertions(+), 209 deletions(-) create mode 100644 atomics.md create mode 100644 races.md create mode 100644 send-and-sync.md diff --git a/SUMMARY.md b/SUMMARY.md index 3b5a04c5a3eb..1456e3602e0b 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -31,6 +31,9 @@ * [Leaking](leaking.md) * [Unwinding](unwinding.md) * [Concurrency](concurrency.md) + * [Races](races.md) + * [Send and Sync](send-and-sync.md) + * [Atomics](atomics.md) * [Example: Implementing Vec](vec.md) * [Layout](vec-layout.md) * [Allocating](vec-alloc.md) diff --git a/atomics.md b/atomics.md new file mode 100644 index 000000000000..e13fb01c06b6 --- /dev/null +++ b/atomics.md @@ -0,0 +1,47 @@ +% Atomics + +Rust pretty blatantly just inherits C11's memory model for atomics. This is not +due this model being particularly excellent or easy to understand. Indeed, this +model is quite complex and known to have [several flaws][C11-busted]. Rather, +it is a pragmatic concession to the fact that *everyone* is pretty bad at modeling +atomics. At very least, we can benefit from existing tooling and research around +C. + +Trying to fully explain the model is fairly hopeless. If you want all the +nitty-gritty details, you should check out [C's specification][C11-model]. +Still, we'll try to cover the basics and some of the problems Rust developers +face. + +The C11 memory model is fundamentally about trying to bridge the gap between C's +single-threaded semantics, common compiler optimizations, and hardware peculiarities +in the face of a multi-threaded environment. It does this by splitting memory +accesses into two worlds: data accesses, and atomic accesses. + +Data accesses are the bread-and-butter of the programming world. They are +fundamentally unsynchronized and compilers are free to aggressively optimize +them. In particular data accesses are free to be reordered by the compiler +on the assumption that the program is single-threaded. The hardware is also free +to propagate the changes made in data accesses as lazily and inconsistently as +it wants to other threads. Mostly critically, data accesses are where we get data +races. These are pretty clearly awful semantics to try to write a multi-threaded +program with. + +Atomic accesses are the answer to this. Each atomic access can be marked with +an *ordering*. The set of orderings Rust exposes are: + +* Sequentially Consistent (SeqCst) +* Release +* Acquire +* Relaxed + +(Note: We explicitly do not expose the C11 *consume* ordering) + +TODO: give simple "basic" explanation of these +TODO: implementing Arc example (why does Drop need the trailing barrier?) + + + + + +[C11-busted]: http://plv.mpi-sws.org/c11comp/popl15.pdf +[C11-model]: http://en.cppreference.com/w/c/atomic/memory_order diff --git a/concurrency.md b/concurrency.md index 71cfec3393e5..e5276323267c 100644 --- a/concurrency.md +++ b/concurrency.md @@ -1,217 +1,13 @@ % Concurrency and Paralellism - - -# Data Races and Race Conditions - -Safe Rust guarantees an absence of data races, which are defined as: - -* two or more threads concurrently accessing a location of memory -* one of them is a write -* one of them is unsynchronized - -A data race has Undefined Behaviour, and is therefore impossible to perform -in Safe Rust. Data races are *mostly* prevented through rust's ownership system: -it's impossible to alias a mutable reference, so it's impossible to perform a -data race. Interior mutability makes this more complicated, which is largely why -we have the Send and Sync traits (see below). - -However Rust *does not* prevent general race conditions. This is -pretty fundamentally impossible, and probably honestly undesirable. Your hardware -is racy, your OS is racy, the other programs on your computer are racy, and the -world this all runs in is racy. Any system that could genuinely claim to prevent -*all* race conditions would be pretty awful to use, if not just incorrect. - -So it's perfectly "fine" for a Safe Rust program to get deadlocked or do -something incredibly stupid with incorrect synchronization. Obviously such a -program isn't very good, but Rust can only hold your hand so far. Still, a -race condition can't violate memory safety in a Rust program on -its own. Only in conjunction with some other unsafe code can a race condition -actually violate memory safety. For instance: - -```rust -use std::thread; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::Arc; - -let data = vec![1, 2, 3, 4]; -// Arc so that the memory the AtomicUsize is stored in still exists for -// the other thread to increment, even if we completely finish executing -// before it. Rust won't compile the program without it, because of the -// lifetime requirements of thread::spawn! -let idx = Arc::new(AtomicUsize::new(0)); -let other_idx = idx.clone(); - -// `move` captures other_idx by-value, moving it into this thread -thread::spawn(move || { - // It's ok to mutate idx because this value - // is an atomic, so it can't cause a Data Race. - other_idx.fetch_add(10, Ordering::SeqCst); -}); - -// Index with the value loaded from the atomic. This is safe because we -// read the atomic memory only once, and then pass a *copy* of that value -// to the Vec's indexing implementation. This indexing will be correctly -// bounds checked, and there's no chance of the value getting changed -// in the middle. However our program may panic if the thread we spawned -// managed to increment before this ran. A race condition because correct -// program execution (panicing is rarely correct) depends on order of -// thread execution. -println!("{}", data[idx.load(Ordering::SeqCst)]); - -if idx.load(Ordering::SeqCst) < data.len() { - unsafe { - // Incorrectly loading the idx *after* we did the bounds check. - // It could have changed. This is a race condition, *and dangerous* - // because we decided to do `get_unchecked`, which is `unsafe`. - println!("{}", data.get_unchecked(idx.load(Ordering::SeqCst))); - } -} -``` - - - - -# Send and Sync - -Not everything obeys inherited mutability, though. Some types allow you to multiply -alias a location in memory while mutating it. Unless these types use synchronization -to manage this access, they are absolutely not thread safe. Rust captures this with -through the `Send` and `Sync` traits. - -* A type is Send if it is safe to send it to another thread. -* A type is Sync if it is safe to share between threads (`&T` is Send). - -Send and Sync are *very* fundamental to Rust's concurrency story. As such, a -substantial amount of special tooling exists to make them work right. First and -foremost, they're *unsafe traits*. This means that they are unsafe *to implement*, -and other unsafe code can *trust* that they are correctly implemented. Since -they're *marker traits* (they have no associated items like methods), correctly -implemented simply means that they have the intrinsic properties an implementor -should have. Incorrectly implementing Send or Sync can cause Undefined Behaviour. - -Send and Sync are also what Rust calls *opt-in builtin traits*. -This means that, unlike every other trait, they are *automatically* derived: -if a type is composed entirely of Send or Sync types, then it is Send or Sync. -Almost all primitives are Send and Sync, and as a consequence pretty much -all types you'll ever interact with are Send and Sync. - -Major exceptions include: - -* raw pointers are neither Send nor Sync (because they have no safety guards) -* `UnsafeCell` isn't Sync (and therefore `Cell` and `RefCell` aren't) -* `Rc` isn't Send or Sync (because the refcount is shared and unsynchronized) - -`Rc` and `UnsafeCell` are very fundamentally not thread-safe: they enable -unsynchronized shared mutable state. However raw pointers are, strictly speaking, -marked as thread-unsafe as more of a *lint*. Doing anything useful -with a raw pointer requires dereferencing it, which is already unsafe. In that -sense, one could argue that it would be "fine" for them to be marked as thread safe. - -However it's important that they aren't thread safe to prevent types that -*contain them* from being automatically marked as thread safe. These types have -non-trivial untracked ownership, and it's unlikely that their author was -necessarily thinking hard about thread safety. In the case of Rc, we have a nice -example of a type that contains a `*mut` that is *definitely* not thread safe. - -Types that aren't automatically derived can *opt-in* to Send and Sync by simply -implementing them: - -```rust -struct MyBox(*mut u8); - -unsafe impl Send for MyBox {} -unsafe impl Sync for MyBox {} -``` - -In the *incredibly rare* case that a type is *inappropriately* automatically -derived to be Send or Sync, then one can also *unimplement* Send and Sync: - -```rust -struct SpecialThreadToken(u8); - -impl !Send for SpecialThreadToken {} -impl !Sync for SpecialThreadToken {} -``` - -Note that *in and of itself* it is impossible to incorrectly derive Send and Sync. -Only types that are ascribed special meaning by other unsafe code can possible cause -trouble by being incorrectly Send or Sync. - -Most uses of raw pointers should be encapsulated behind a sufficient abstraction -that Send and Sync can be derived. For instance all of Rust's standard -collections are Send and Sync (when they contain Send and Sync types) -in spite of their pervasive use raw pointers to -manage allocations and complex ownership. Similarly, most iterators into these -collections are Send and Sync because they largely behave like an `&` or `&mut` -into the collection. - -TODO: better explain what can or can't be Send or Sync. Sufficient to appeal -only to data races? - - - - -# Atomics - -Rust pretty blatantly just inherits C11's memory model for atomics. This is not -due this model being particularly excellent or easy to understand. Indeed, this -model is quite complex and known to have [several flaws][C11-busted]. Rather, -it is a pragmatic concession to the fact that *everyone* is pretty bad at modeling -atomics. At very least, we can benefit from existing tooling and research around -C. - -Trying to fully explain the model is fairly hopeless. If you want all the -nitty-gritty details, you should check out [C's specification][C11-model]. -Still, we'll try to cover the basics and some of the problems Rust developers -face. - -The C11 memory model is fundamentally about trying to bridge the gap between C's -single-threaded semantics, common compiler optimizations, and hardware peculiarities -in the face of a multi-threaded environment. It does this by splitting memory -accesses into two worlds: data accesses, and atomic accesses. - -Data accesses are the bread-and-butter of the programming world. They are -fundamentally unsynchronized and compilers are free to aggressively optimize -them. In particular data accesses are free to be reordered by the compiler -on the assumption that the program is single-threaded. The hardware is also free -to propagate the changes made in data accesses as lazily and inconsistently as -it wants to other threads. Mostly critically, data accesses are where we get data -races. These are pretty clearly awful semantics to try to write a multi-threaded -program with. - -Atomic accesses are the answer to this. Each atomic access can be marked with -an *ordering*. The set of orderings Rust exposes are: - -* Sequentially Consistent (SeqCst) -* Release -* Acquire -* Relaxed - -(Note: We explicitly do not expose the C11 *consume* ordering) - -TODO: give simple "basic" explanation of these -TODO: implementing Arc example (why does Drop need the trailing barrier?) - - - - -# Actually Doing Things Concurrently - Rust as a language doesn't *really* have an opinion on how to do concurrency or parallelism. The standard library exposes OS threads and blocking sys-calls -because *everyone* has those and they're uniform enough that you can provide +because *everyone* has those, and they're uniform enough that you can provide an abstraction over them in a relatively uncontroversial way. Message passing, green threads, and async APIs are all diverse enough that any abstraction over them tends to involve trade-offs that we weren't willing to commit to for 1.0. -However Rust's current design is setup so that you can set up your own -concurrent paradigm or library as you see fit. Just require the right -lifetimes and Send and Sync where appropriate and everything should Just Work -with everyone else's stuff. - - - - -[C11-busted]: http://plv.mpi-sws.org/c11comp/popl15.pdf -[C11-model]: http://en.cppreference.com/w/c/atomic/memory_order +However the way Rust models concurrency makes it relatively easy design your own +concurrency paradigm as a library and have *everyone else's* code Just Work +with yours. Just require the right lifetimes and Send and Sync where appropriate +and you're off to the races. Or rather, not having races. Races are bad. diff --git a/races.md b/races.md new file mode 100644 index 000000000000..240e4aca7f6b --- /dev/null +++ b/races.md @@ -0,0 +1,66 @@ +% Data Races and Race Conditions + +Safe Rust guarantees an absence of data races, which are defined as: + +* two or more threads concurrently accessing a location of memory +* one of them is a write +* one of them is unsynchronized + +A data race has Undefined Behaviour, and is therefore impossible to perform +in Safe Rust. Data races are *mostly* prevented through rust's ownership system: +it's impossible to alias a mutable reference, so it's impossible to perform a +data race. Interior mutability makes this more complicated, which is largely why +we have the Send and Sync traits (see below). + +However Rust *does not* prevent general race conditions. This is +pretty fundamentally impossible, and probably honestly undesirable. Your hardware +is racy, your OS is racy, the other programs on your computer are racy, and the +world this all runs in is racy. Any system that could genuinely claim to prevent +*all* race conditions would be pretty awful to use, if not just incorrect. + +So it's perfectly "fine" for a Safe Rust program to get deadlocked or do +something incredibly stupid with incorrect synchronization. Obviously such a +program isn't very good, but Rust can only hold your hand so far. Still, a +race condition can't violate memory safety in a Rust program on +its own. Only in conjunction with some other unsafe code can a race condition +actually violate memory safety. For instance: + +```rust +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; + +let data = vec![1, 2, 3, 4]; +// Arc so that the memory the AtomicUsize is stored in still exists for +// the other thread to increment, even if we completely finish executing +// before it. Rust won't compile the program without it, because of the +// lifetime requirements of thread::spawn! +let idx = Arc::new(AtomicUsize::new(0)); +let other_idx = idx.clone(); + +// `move` captures other_idx by-value, moving it into this thread +thread::spawn(move || { + // It's ok to mutate idx because this value + // is an atomic, so it can't cause a Data Race. + other_idx.fetch_add(10, Ordering::SeqCst); +}); + +// Index with the value loaded from the atomic. This is safe because we +// read the atomic memory only once, and then pass a *copy* of that value +// to the Vec's indexing implementation. This indexing will be correctly +// bounds checked, and there's no chance of the value getting changed +// in the middle. However our program may panic if the thread we spawned +// managed to increment before this ran. A race condition because correct +// program execution (panicing is rarely correct) depends on order of +// thread execution. +println!("{}", data[idx.load(Ordering::SeqCst)]); + +if idx.load(Ordering::SeqCst) < data.len() { + unsafe { + // Incorrectly loading the idx *after* we did the bounds check. + // It could have changed. This is a race condition, *and dangerous* + // because we decided to do `get_unchecked`, which is `unsafe`. + println!("{}", data.get_unchecked(idx.load(Ordering::SeqCst))); + } +} +``` diff --git a/send-and-sync.md b/send-and-sync.md new file mode 100644 index 000000000000..0ac14a85f847 --- /dev/null +++ b/send-and-sync.md @@ -0,0 +1,76 @@ +% Send and Sync + +Not everything obeys inherited mutability, though. Some types allow you to multiply +alias a location in memory while mutating it. Unless these types use synchronization +to manage this access, they are absolutely not thread safe. Rust captures this with +through the `Send` and `Sync` traits. + +* A type is Send if it is safe to send it to another thread. +* A type is Sync if it is safe to share between threads (`&T` is Send). + +Send and Sync are *very* fundamental to Rust's concurrency story. As such, a +substantial amount of special tooling exists to make them work right. First and +foremost, they're *unsafe traits*. This means that they are unsafe *to implement*, +and other unsafe code can *trust* that they are correctly implemented. Since +they're *marker traits* (they have no associated items like methods), correctly +implemented simply means that they have the intrinsic properties an implementor +should have. Incorrectly implementing Send or Sync can cause Undefined Behaviour. + +Send and Sync are also what Rust calls *opt-in builtin traits*. +This means that, unlike every other trait, they are *automatically* derived: +if a type is composed entirely of Send or Sync types, then it is Send or Sync. +Almost all primitives are Send and Sync, and as a consequence pretty much +all types you'll ever interact with are Send and Sync. + +Major exceptions include: + +* raw pointers are neither Send nor Sync (because they have no safety guards) +* `UnsafeCell` isn't Sync (and therefore `Cell` and `RefCell` aren't) +* `Rc` isn't Send or Sync (because the refcount is shared and unsynchronized) + +`Rc` and `UnsafeCell` are very fundamentally not thread-safe: they enable +unsynchronized shared mutable state. However raw pointers are, strictly speaking, +marked as thread-unsafe as more of a *lint*. Doing anything useful +with a raw pointer requires dereferencing it, which is already unsafe. In that +sense, one could argue that it would be "fine" for them to be marked as thread safe. + +However it's important that they aren't thread safe to prevent types that +*contain them* from being automatically marked as thread safe. These types have +non-trivial untracked ownership, and it's unlikely that their author was +necessarily thinking hard about thread safety. In the case of Rc, we have a nice +example of a type that contains a `*mut` that is *definitely* not thread safe. + +Types that aren't automatically derived can *opt-in* to Send and Sync by simply +implementing them: + +```rust +struct MyBox(*mut u8); + +unsafe impl Send for MyBox {} +unsafe impl Sync for MyBox {} +``` + +In the *incredibly rare* case that a type is *inappropriately* automatically +derived to be Send or Sync, then one can also *unimplement* Send and Sync: + +```rust +struct SpecialThreadToken(u8); + +impl !Send for SpecialThreadToken {} +impl !Sync for SpecialThreadToken {} +``` + +Note that *in and of itself* it is impossible to incorrectly derive Send and Sync. +Only types that are ascribed special meaning by other unsafe code can possible cause +trouble by being incorrectly Send or Sync. + +Most uses of raw pointers should be encapsulated behind a sufficient abstraction +that Send and Sync can be derived. For instance all of Rust's standard +collections are Send and Sync (when they contain Send and Sync types) +in spite of their pervasive use raw pointers to +manage allocations and complex ownership. Similarly, most iterators into these +collections are Send and Sync because they largely behave like an `&` or `&mut` +into the collection. + +TODO: better explain what can or can't be Send or Sync. Sufficient to appeal +only to data races? \ No newline at end of file From d8f460c29d6b7e07775562e2090f3f36c6d651e0 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 7 Jul 2015 10:03:51 -0700 Subject: [PATCH 053/104] improve joke --- concurrency.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concurrency.md b/concurrency.md index e5276323267c..95973b35d4ff 100644 --- a/concurrency.md +++ b/concurrency.md @@ -10,4 +10,4 @@ them tends to involve trade-offs that we weren't willing to commit to for 1.0. However the way Rust models concurrency makes it relatively easy design your own concurrency paradigm as a library and have *everyone else's* code Just Work with yours. Just require the right lifetimes and Send and Sync where appropriate -and you're off to the races. Or rather, not having races. Races are bad. +and you're off to the races. Or rather, off to the... not... having... races. \ No newline at end of file From 668bdd3650f8fcce956d8e47ae74247a50da3e46 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 7 Jul 2015 21:19:04 -0700 Subject: [PATCH 054/104] flesh out atomics --- atomics.md | 218 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 199 insertions(+), 19 deletions(-) diff --git a/atomics.md b/atomics.md index e13fb01c06b6..9bafb761321d 100644 --- a/atomics.md +++ b/atomics.md @@ -7,27 +7,138 @@ it is a pragmatic concession to the fact that *everyone* is pretty bad at modeli atomics. At very least, we can benefit from existing tooling and research around C. -Trying to fully explain the model is fairly hopeless. If you want all the -nitty-gritty details, you should check out [C's specification][C11-model]. -Still, we'll try to cover the basics and some of the problems Rust developers -face. +Trying to fully explain the model in this book is fairly hopeless. It's defined +in terms of madness-inducing causality graphs that require a full book to properly +understand in a practical way. If you want all the nitty-gritty details, you +should check out [C's specification][C11-model]. Still, we'll try to cover the +basics and some of the problems Rust developers face. -The C11 memory model is fundamentally about trying to bridge the gap between C's -single-threaded semantics, common compiler optimizations, and hardware peculiarities -in the face of a multi-threaded environment. It does this by splitting memory -accesses into two worlds: data accesses, and atomic accesses. +The C11 memory model is fundamentally about trying to bridge the gap between +the semantics we want, the optimizations compilers want, and the inconsistent +chaos our hardware wants. *We* would like to just write programs and have them +do exactly what we said but, you know, *fast*. Wouldn't that be great? + + + + +# Compiler Reordering + +Compilers fundamentally want to be able to do all sorts of crazy transformations +to reduce data dependencies and eleminate dead code. In particular, they may +radically change the actual order of events, or make events never occur! If we +write something like + +```rust,ignore +x = 1; +y = 3; +x = 2; +``` + +The compiler may conclude that it would *really* be best if your program did + +```rust,ignore +x = 2; +y = 3; +``` + +This has inverted the order of events *and* completely eliminated one event. From +a single-threaded perspective this is completely unobservable: after all the +statements have executed we are in exactly the same state. But if our program is +multi-threaded, we may have been relying on `x` to *actually* be assigned to 1 before +`y` was assigned. We would *really* like the compiler to be able to make these kinds +of optimizations, because they can seriously improve performance. On the other hand, +we'd really like to be able to depend on our program *doing the thing we said*. + + + + +# Hardware Reordering + +On the other hand, even if the compiler totally understood what we wanted and +respected our wishes, our *hardware* might instead get us in trouble. Trouble comes +from CPUs in the form of memory hierarchies. There is indeed a global shared memory +space somewhere in your hardware, but from the perspective of each CPU core it is +*so very far away* and *so very slow*. Each CPU would rather work with its local +cache of the data and only go through all the *anguish* of talking to shared +memory *only* when it doesn't actually have that memory in cache. + +After all, that's the whole *point* of the cache, right? If every read from the +cache had to run back to shared memory to double check that it hadn't changed, +what would the point be? The end result is that the hardware doesn't guarantee +that events that occur in the same order on *one* thread, occur in the same order +on *another* thread. To guarantee this, we must issue special instructions to +the CPU telling it to be a bit less smart. + +For instance, say we convince the compiler to emit this logic: + +```text +initial state: x = 0, y = 1 + +THREAD 1 THREAD2 +y = 3; if x == 1 { +x = 1; y *= 2; + } +``` + +Ideally this program has 2 possible final states: + +* `y = 3`: (thread 2 did the check before thread 1 completed) +* `y = 6`: (thread 2 did the check after thread 1 completed) + +However there's a third potential state that the hardware enables: + +* `y = 2`: (thread 2 saw `x = 2`, but not `y = 3`, and then overwrote `y = 3`) + +``` + +It's worth noting that different kinds of CPU provide different guarantees. It +is common to seperate hardware into two categories: strongly-ordered and weakly- +ordered. Most notably x86/64 provides strong ordering guarantees, while ARM and +provides weak ordering guarantees. This has two consequences for +concurrent programming: + +* Asking for stronger guarantees on strongly-ordered hardware may be cheap or + even *free* because they already provide strong guarantees unconditionally. + Weaker guarantees may only yield performance wins on weakly-ordered hardware. + +* Asking for guarantees that are *too* weak on strongly-ordered hardware + is more likely to *happen* to work, even though your program is strictly + incorrect. If possible, concurrent algorithms should be tested on + weakly-ordered hardware. + + + + + +# Data Accesses + +The C11 memory model attempts to bridge the gap by allowing us to talk about +the *causality* of our program. Generally, this is by establishing a +*happens before* relationships between parts of the program and the threads +that are running them. This gives the hardware and compiler room to optimize the +program more aggressively where a strict happens-before relationship isn't +established, but forces them to be more careful where one *is* established. +The way we communicate these relationships are through *data accesses* and +*atomic accesses*. Data accesses are the bread-and-butter of the programming world. They are fundamentally unsynchronized and compilers are free to aggressively optimize -them. In particular data accesses are free to be reordered by the compiler +them. In particular, data accesses are free to be reordered by the compiler on the assumption that the program is single-threaded. The hardware is also free -to propagate the changes made in data accesses as lazily and inconsistently as -it wants to other threads. Mostly critically, data accesses are where we get data -races. These are pretty clearly awful semantics to try to write a multi-threaded -program with. +to propagate the changes made in data accesses to other threads +as lazily and inconsistently as it wants. Mostly critically, data accesses are +how data races happen. Data accesses are very friendly to the hardware and +compiler, but as we've seen they offer *awful* semantics to try to +write synchronized code with. -Atomic accesses are the answer to this. Each atomic access can be marked with -an *ordering*. The set of orderings Rust exposes are: +Atomic accesses are how we tell the hardware and compiler that our program is +multi-threaded. Each atomic access can be marked with +an *ordering* that specifies what kind of relationship it establishes with +other accesses. In practice, this boils down to telling the compiler and hardware +certain things they *can't* do. For the compiler, this largely revolves +around re-ordering of instructions. For the hardware, this largely revolves +around how writes are propagated to other threads. The set of orderings Rust +exposes are: * Sequentially Consistent (SeqCst) * Release @@ -36,12 +147,81 @@ an *ordering*. The set of orderings Rust exposes are: (Note: We explicitly do not expose the C11 *consume* ordering) -TODO: give simple "basic" explanation of these +TODO: negative reasoning vs positive reasoning? + + + + +# Sequentially Consistent + +Sequentially Consistent is the most powerful of all, implying the restrictions +of all other orderings. A Sequentially Consistent operation *cannot* +be reordered: all accesses on one thread that happen before and after it *stay* +before and after it. A program that has sequential consistency has the very nice +property that there is a single global execution of the program's instructions +that all threads agree on. This execution is also particularly nice to reason +about: it's just an interleaving of each thread's individual executions. + +The relative developer-friendliness of sequential consistency doesn't come for +free. Even on strongly-ordered platforms, sequential consistency involves +emitting memory fences. + +In practice, sequential consistency is rarely necessary for program correctness. +However sequential consistency is definitely the right choice if you're not +confident about the other memory orders. Having your program run a bit slower +than it needs to is certainly better than it running incorrectly! It's also +completely trivial to downgrade to a weaker consistency later. + + + + +# Acquire-Release + +Acquire and Release are largely intended to be paired. Their names hint at +their use case: they're perfectly suited for acquiring and releasing locks, +and ensuring that critical sections don't overlap. + +An acquire access ensures that every access after it *stays* after it. However +operations that occur before an acquire are free to be reordered to occur after +it. + +A release access ensures that every access before it *stays* before it. However +operations that occur after a release are free to be reordered to occur before +it. + +Basic use of release-acquire is simple: you acquire a location of memory to +begin the critical section, and the release that location to end it. If +thread A releases a location of memory and thread B acquires that location of +memory, this establishes that A's critical section *happened before* B's +critical section. All accesses that happened before the release will be observed +by anything that happens after the acquire. + +On strongly-ordered platforms most accesses have release or acquire semantics, +making release and acquire often totally free. This is not the case on +weakly-ordered platforms. + + + + +# Relaxed + +Relaxed accesses are the absolute weakest. They can be freely re-ordered and +provide no happens-before relationship. Still, relaxed operations *are* still +atomic, which is valuable. Relaxed operations are appropriate for things that +you definitely want to happen, but don't particularly care about much else. For +instance, incrementing a counter can be relaxed if you're not using the +counter to synchronize any other accesses. + +There's rarely a benefit in making an operation relaxed on strongly-ordered +platforms, since they usually provide release-acquire semantics anyway. However +relaxed operations can be cheaper on weakly-ordered platforms. + + + + + TODO: implementing Arc example (why does Drop need the trailing barrier?) - - - [C11-busted]: http://plv.mpi-sws.org/c11comp/popl15.pdf [C11-model]: http://en.cppreference.com/w/c/atomic/memory_order From 778a4fa390590752df3624fe295b484a8a40288a Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 7 Jul 2015 21:30:03 -0700 Subject: [PATCH 055/104] new chapter --- SUMMARY.md | 5 +++-- atomics.md | 3 --- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/SUMMARY.md b/SUMMARY.md index 1456e3602e0b..1d66f1bfdea8 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -34,7 +34,7 @@ * [Races](races.md) * [Send and Sync](send-and-sync.md) * [Atomics](atomics.md) -* [Example: Implementing Vec](vec.md) +* [Implementing Vec](vec.md) * [Layout](vec-layout.md) * [Allocating](vec-alloc.md) * [Push and Pop](vec-push-pop.md) @@ -43,4 +43,5 @@ * [Insert and Remove](vec-insert-remove.md) * [IntoIter](vec-into-iter.md) * [Drain](vec-drain.md) - * [Final Code](vec-final.md) \ No newline at end of file + * [Final Code](vec-final.md) +* [Implementing Arc and Mutex](arc-and-mutex.md) diff --git a/atomics.md b/atomics.md index 9bafb761321d..2a080adc2bc6 100644 --- a/atomics.md +++ b/atomics.md @@ -220,8 +220,5 @@ relaxed operations can be cheaper on weakly-ordered platforms. -TODO: implementing Arc example (why does Drop need the trailing barrier?) - - [C11-busted]: http://plv.mpi-sws.org/c11comp/popl15.pdf [C11-model]: http://en.cppreference.com/w/c/atomic/memory_order From 498e44d87a93183ac04690e09a39fee47dfe85b0 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 7 Jul 2015 21:30:14 -0700 Subject: [PATCH 056/104] new chapter for reals --- arc-and-mutex.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 arc-and-mutex.md diff --git a/arc-and-mutex.md b/arc-and-mutex.md new file mode 100644 index 000000000000..d28180fa9cf5 --- /dev/null +++ b/arc-and-mutex.md @@ -0,0 +1,7 @@ +% Implementing Arc and Mutex + +Knowing the theory is all fine and good, but the *best* was to understand +something is to use it. To better understand atomics and interior mutability, +we'll be implementing versions of the standard library's Arc and Mutex types. + +TODO: ALL OF THIS OMG From fcf4a7e5c87cf80ff8d7c142fbdfd8fd398ad3a7 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 7 Jul 2015 21:31:09 -0700 Subject: [PATCH 057/104] oops --- atomics.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/atomics.md b/atomics.md index 2a080adc2bc6..69c0874dc186 100644 --- a/atomics.md +++ b/atomics.md @@ -89,8 +89,6 @@ However there's a third potential state that the hardware enables: * `y = 2`: (thread 2 saw `x = 2`, but not `y = 3`, and then overwrote `y = 3`) -``` - It's worth noting that different kinds of CPU provide different guarantees. It is common to seperate hardware into two categories: strongly-ordered and weakly- ordered. Most notably x86/64 provides strong ordering guarantees, while ARM and From 29e71b92bc5992dd2bf85dc4b27b60aaf0dcead8 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 8 Jul 2015 10:42:35 -0700 Subject: [PATCH 058/104] niko discussion affects --- atomics.md | 2 +- references.md | 33 ++++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/atomics.md b/atomics.md index 69c0874dc186..39ea2150973a 100644 --- a/atomics.md +++ b/atomics.md @@ -24,7 +24,7 @@ do exactly what we said but, you know, *fast*. Wouldn't that be great? # Compiler Reordering Compilers fundamentally want to be able to do all sorts of crazy transformations -to reduce data dependencies and eleminate dead code. In particular, they may +to reduce data dependencies and eliminate dead code. In particular, they may radically change the actual order of events, or make events never occur! If we write something like diff --git a/references.md b/references.md index fa47a69a7eaa..1039cb1197b6 100644 --- a/references.md +++ b/references.md @@ -25,14 +25,16 @@ as its direct children. Each variable's direct children would be their fields From this view, every value in Rust has a unique *path* in the tree of ownership. References to a value can subsequently be interpreted as a path in this tree. -Of particular interest are *prefixes*: `x` is a prefix of `y` if `x` owns `y` +Of particular interest are *ancestors* and *descendants*: if `x` owns `y`, then +`x` is an *ancestor* of `y`, and `y` is a *descendant* of `x`. Note that this is +an inclusive relationship: `x` is a descendant and ancestor of itself. -However much data doesn't reside on the stack, and we must also accommodate this. +Tragically, plenty of data doesn't reside on the stack, and we must also accommodate this. Globals and thread-locals are simple enough to model as residing at the bottom of the stack (though we must be careful with mutable globals). Data on the heap poses a different problem. -If all Rust had on the heap was data uniquely by a pointer on the stack, +If all Rust had on the heap was data uniquely owned by a pointer on the stack, then we can just treat that pointer as a struct that owns the value on the heap. Box, Vec, String, and HashMap, are examples of types which uniquely own data on the heap. @@ -51,6 +53,10 @@ types provide exclusive access through runtime restrictions. However it is also possible to establish unique ownership without interior mutability. For instance, if an Rc has refcount 1, then it is safe to mutate or move its internals. +In order to correctly communicate to the type system that a variable or field of +a struct can have interior mutability, it must be wrapped in an UnsafeCell. This +does not in itself make it safe to perform interior mutability operations on that +value. You still must yourself ensure that mutual exclusion is upheld. @@ -61,9 +67,9 @@ dereferenced. Shared references are always live unless they are literally unreac (for instance, they reside in freed or leaked memory). Mutable references can be reachable but *not* live through the process of *reborrowing*. -A mutable reference can be reborrowed to either a shared or mutable reference. -Further, the reborrow can produce exactly the same reference, or point to a -path it is a prefix of. For instance, a mutable reference can be reborrowed +A mutable reference can be reborrowed to either a shared or mutable reference to +one of its descendants. A reborrowed reference will only be live again once all +reborrows derived from it expire. For instance, a mutable reference can be reborrowed to point to a field of its referent: ```rust @@ -79,7 +85,7 @@ let x = &mut (1, 2); ``` It is also possible to reborrow into *multiple* mutable references, as long as -they are *disjoint*: no reference is a prefix of another. Rust +they are *disjoint*: no reference is an ancestor of another. Rust explicitly enables this to be done with disjoint struct fields, because disjointness can be statically proven: @@ -89,6 +95,7 @@ let x = &mut (1, 2); // reborrow x to two disjoint subfields let y = &mut x.0; let z = &mut x.1; + // y and z are now live, but x isn't *y = 3; *z = 4; @@ -105,14 +112,14 @@ To simplify things, we can model variables as a fake type of reference: *owned* references. Owned references have much the same semantics as mutable references: they can be re-borrowed in a mutable or shared manner, which makes them no longer live. Live owned references have the unique property that they can be moved -out of (though mutable references *can* be swapped out of). This is +out of (though mutable references *can* be swapped out of). This power is only given to *live* owned references because moving its referent would of course invalidate all outstanding references prematurely. As a local lint against inappropriate mutation, only variables that are marked as `mut` can be borrowed mutably. -It is also interesting to note that Box behaves exactly like an owned +It is interesting to note that Box behaves exactly like an owned reference. It can be moved out of, and Rust understands it sufficiently to reason about its paths like a normal variable. @@ -123,8 +130,12 @@ reason about its paths like a normal variable. With liveness and paths defined, we can now properly define *aliasing*: -**A mutable reference is aliased if there exists another live reference to it or -one of its prefixes.** +**A mutable reference is aliased if there exists another live reference to one of +its ancestors or descendants.** + +(If you prefer, you may also say the two live references alias *each other*. +This has no semantic consequences, but is probably a more useful notion when +verifying the soundness of a construct.) That's it. Super simple right? Except for the fact that it took us two pages to define all of the terms in that defintion. You know: Super. Simple. From e167ee825984b649c1e5e1754b8479f70f1043c5 Mon Sep 17 00:00:00 2001 From: mdinger Date: Wed, 8 Jul 2015 15:41:39 -0400 Subject: [PATCH 059/104] typos --- meet-safe-and-unsafe.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meet-safe-and-unsafe.md b/meet-safe-and-unsafe.md index e12997f6f246..dfcbd4a216c6 100644 --- a/meet-safe-and-unsafe.md +++ b/meet-safe-and-unsafe.md @@ -14,12 +14,12 @@ on a leap year? Are we ready for that? Unsafe better be, because if they get built to Unsafe's standards! That's where Safe comes in. Safe has to handle *everything else*. Since Safe needs -to *get work done*, they've grown to be fairly carless and clumsy! Safe doesn't worry +to *get work done*, they've grown to be fairly careless and clumsy! Safe doesn't worry about all the crazy eventualities that Unsafe does, because life is too short to deal with leap-year-earthquakes. Of course, this means there's some jobs that Safe just can't handle. Safe is all about quantity over quality. -Unsafe loves Safe to bits, but knows that tey *can never trust them to do the +Unsafe loves Safe to bits, but knows that they *can never trust them to do the right thing*. Still, Unsafe acknowledges that not every problem needs quite the attention to detail that they apply. Indeed, Unsafe would *love* if Safe could do *everything* for them. To accomplish this, Unsafe spends most of their time From acd3c5947a4b85113a0c21d435dec5bd1bd22956 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 8 Jul 2015 15:04:55 -0700 Subject: [PATCH 060/104] fix typo --- working-with-unsafe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/working-with-unsafe.md b/working-with-unsafe.md index 672513246619..57b71d160339 100644 --- a/working-with-unsafe.md +++ b/working-with-unsafe.md @@ -33,7 +33,7 @@ fn do_idx(idx: usize, arr: &[u8]) -> Option { } ``` -This program is now unsound, an yet *we only modified safe code*. This is the +This program is now unsound, and yet *we only modified safe code*. This is the fundamental problem of safety: it's non-local. The soundness of our unsafe operations necessarily depends on the state established by "safe" operations. Although safety *is* modular (we *still* don't need to worry about about From 62e827cfc7b76c0a8a2485fb421f6f41af289048 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 11:12:16 -0700 Subject: [PATCH 061/104] rewrite intro --- README.md | 45 ++++++++---- SUMMARY.md | 2 +- meet-safe-and-unsafe.md | 150 ++++++++++++++++++++++------------------ safe-unsafe-meaning.md | 97 +++++++++++++------------- working-with-unsafe.md | 30 ++++++-- 5 files changed, 186 insertions(+), 138 deletions(-) diff --git a/README.md b/README.md index a801a21db3d5..874f6f2ac612 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,39 @@ -% The Unsafe Rust Programming Language +% The Advanced Rust Programming Language # NOTE: This is a draft document, and may contain serious errors -**This document is about advanced functionality and low-level development practices -in the Rust Programming Language. Most of the things discussed won't matter -to the average Rust programmer. However if you wish to correctly write unsafe -code in Rust, this text contains invaluable information.** +So you've played around with Rust a bit. You've written a few simple programs and +you think you grok the basics. Maybe you've even read through +*[The Rust Programming Language][trpl]*. Now you want to get neck-deep in all the +nitty-gritty details of the language. You want to know those weird corner-cases. +You want to know what the heck `unsafe` really means, and how to properly use it. +This is the book for you. -The Unsafe Rust Programming Language (TURPL) seeks to complement -[The Rust Programming Language Book][trpl] (TRPL). -Where TRPL introduces the language and teaches the basics, TURPL dives deep into -the specification of the language, and all the nasty bits necessary to write -Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know -the basics of the language and systems programming. We will not explain the -stack or heap. We will not explain the basic syntax. +To be clear, this book goes into *serious* detail. We're going to dig into +exception-safety and pointer aliasing. We're going to talk about memory +models. We're even going to do some type-theory. This is stuff that you +absolutely *don't* need to know to write fast and safe Rust programs. +You could probably close this book *right now* and still have a productive +and happy career in Rust. +However if you intend to write unsafe code -- or just *really* want to dig into +the guts of the language -- this book contains *invaluable* information. +Unlike *The Rust Programming Language* we *will* be assuming considerable prior +knowledge. In particular, you should be comfortable with: -[trpl]: https://doc.rust-lang.org/book/ \ No newline at end of file +* Basic Systems Programming: + * Pointers + * [The stack and heap][] + * The memory hierarchy (caches) + * Threads + +* [Basic Rust][] + +Due to the nature of advanced Rust programming, we will be spending a lot of time +talking about *safety* and *guarantees*. In particular, a significant portion of +the book will be dedicated to correctly writing and understanding Unsafe Rust. + +[trpl]: https://doc.rust-lang.org/book/ +[The stack and heap]: https://doc.rust-lang.org/book/the-stack-and-the-heap.html +[Basic Rust]: https://doc.rust-lang.org/book/syntax-and-semantics.html diff --git a/SUMMARY.md b/SUMMARY.md index 1d66f1bfdea8..dc494d2b0c94 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,7 +1,7 @@ # Summary * [Meet Safe and Unsafe](meet-safe-and-unsafe.md) - * [What Do Safe and Unsafe Mean](safe-unsafe-meaning.md) + * [How Safe and Unsafe Interact](safe-unsafe-meaning.md) * [Working with Unsafe](working-with-unsafe.md) * [Data Layout](data.md) * [repr(Rust)](repr-rust.md) diff --git a/meet-safe-and-unsafe.md b/meet-safe-and-unsafe.md index dfcbd4a216c6..5ff000f2bbce 100644 --- a/meet-safe-and-unsafe.md +++ b/meet-safe-and-unsafe.md @@ -1,82 +1,98 @@ % Meet Safe and Unsafe -Safe and Unsafe are Rust's chief engineers. +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 some *really* 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. -TODO: ADORABLE PICTURES OMG +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. -Unsafe handles all the dangerous internal stuff. They build the foundations -and handle all the dangerous materials. By all accounts, Unsafe is really a bit -unproductive, because the nature of their work means that they have to spend a -lot of time checking and double-checking everything. What if there's an earthquake -on a leap year? Are we ready for that? Unsafe better be, because if they get -*anything* wrong, everything will blow up! What Unsafe brings to the table is -*quality*, not quantity. Still, nothing would ever get done if everything was -built to Unsafe's standards! +With that said, Rust is *totally* a safe programming language. -That's where Safe comes in. Safe has to handle *everything else*. Since Safe needs -to *get work done*, they've grown to be fairly careless and clumsy! Safe doesn't worry -about all the crazy eventualities that Unsafe does, because life is too short to deal -with leap-year-earthquakes. Of course, this means there's some jobs that Safe just -can't handle. Safe is all about quantity over quality. +Well, Rust *has* a safe programming language. Let's step back a bit. -Unsafe loves Safe to bits, but knows that they *can never trust them to do the -right thing*. Still, Unsafe acknowledges that not every problem needs quite the -attention to detail that they apply. Indeed, Unsafe would *love* if Safe could do -*everything* for them. To accomplish this, Unsafe spends most of their time -building *safe abstractions*. These abstractions handle all the nitty-gritty -details for Safe, and choose good defaults so that the simplest solution (which -Safe will inevitably use) is usually the *right* one. Once a safe abstraction is -built, Unsafe ideally needs to never work on it again, and Safe can blindly use -it in all their work. +Rust can be thought of as being composed of two +programming languages: *Safe* and *Unsafe*. Safe is For Reals Totally Safe. +Unsafe, unsurprisingly, is *not* For Reals Totally Safe. In fact, Unsafe lets +you do some really crazy unsafe things. -Unsafe's attention to detail means that all the things that they mark as ok for -Safe to use can be combined in arbitrarily ridiculous ways, and all the rules -that Unsafe is forced to uphold will never be violated. If they *can* be violated -by Safe, that means *Unsafe*'s the one in the wrong. Safe can work carelessly, -knowing that if anything blows up, it's not *their* fault. Safe can also call in -Unsafe at any time if there's a hard problem they can't quite work out, or if they -can't meet the client's quality demands. Of course, Unsafe will beg and plead Safe -to try their latest safe abstraction first! +Safe is *the* 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 Behaviour nonsense. -In addition to being adorable, Safe and Unsafe are what makes Rust possible. -Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust. -Any time someone opines the guarantees of Rust, they are almost surely talking about -Safe. However Safe is not sufficient to write every program. For that, -we need the Unsafe superset. +*That's totally awesome*. -Most fundamentally, writing bindings to other languages -(such as the C exposed by your operating system) is never going to be safe. Rust -can't control what other languages do to program execution! However Unsafe is -also necessary to construct fundamental abstractions where the type system is not -sufficient to automatically prove what you're doing is sound. +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. -Indeed, the Rust standard library is implemented in Rust, and it makes substantial -use of Unsafe for implementing IO, memory allocation, collections, -synchronization, and other low-level computational primitives. +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 +*writing* the standard library (which is written entirely in Rust). Maybe you +need to do something the type-system doesn't understand and just *frob some dang +bits*. Maybe you need Unsafe Rust. -Upon hearing this, many wonder why they would not simply just use C or C++ in place of -Rust (or just use a "real" safe language). If we're going to do unsafe things, why not -lean on these much more established languages? +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 most important difference between C++ and Rust is a matter of defaults: -Rust is 100% safe by default. Even when you *opt out* of safety in Rust, it is a modular -action. In deciding to work with unchecked uninitialized memory, this does not -suddenly make dangling or null pointers a problem. When using unchecked indexing on `x`, -one does not have to suddenly worry about indexing out of bounds on `y`. -C and C++, by contrast, have pervasive unsafety baked into the language. Even the -modern best practices like `unique_ptr` have various safety pitfalls. +The only things that are different in Unsafe Rust are that you can: -It cannot be emphasized enough that Unsafe should be regarded as an exceptional -thing, not a normal one. Unsafe is often the domain of *fundamental libraries*: anything that needs -to make FFI bindings or define core abstractions. These fundamental libraries then expose -a safe interface for intermediate libraries and applications to build upon. And these -safe interfaces make an important promise: if your application segfaults, it's not your -fault. *They* have a bug. +* Dereference raw pointers +* Call `unsafe` functions (including C functions, intrinsics, and the raw allocator) +* Implement `unsafe` traits +* Mutate statics -And really, how is that different from *any* safe language? Python, Ruby, and Java libraries -can internally do all sorts of nasty things. The languages themselves are no -different. Safe languages *regularly* have bugs that cause critical vulnerabilities. -The fact that Rust is written with a healthy spoonful of Unsafe is no different. -However it *does* mean that Rust doesn't need to fall back to the pervasive unsafety of -C to do the nasty things that need to get done. +That's it. The reason these operations are relegated to Unsafe is that misusing +any of these things will cause the ever dreaded Undefined Behaviour. Invoking +Undefined Behaviour gives the compiler full rights to do arbitrarily bad things +to your program. You definitely *should not* invoke Undefined Behaviour. +Unlike C, Undefined Behaviour 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] +* Double-dropping a value + +That's it. That's all the Undefined Behaviour baked into Rust. Of course, unsafe +functions and traits are free to declare arbitrary other constraints that a +program must maintain to avoid Undefined Behaviour. However these are generally +just things that will 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 diff --git a/safe-unsafe-meaning.md b/safe-unsafe-meaning.md index 6c3d4087b819..082970d20387 100644 --- a/safe-unsafe-meaning.md +++ b/safe-unsafe-meaning.md @@ -1,38 +1,17 @@ -% What do Safe and Unsafe really mean? +% How Safe and Unsafe Interact -Rust cares about preventing the following things: +So what's the relationship between Safe and Unsafe? How do they interact? -* 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` larger than char::MAX (TODO: check if stronger restrictions apply) - * A non-utf8 `str` -* Unwinding into another language -* Causing a [data race][] -* Invoking Misc. Undefined Behaviour (in e.g. compiler intrinsics) +Rust models the seperation between Safe and Unsafe with the `unsafe` keyword, which +can be thought as a sort of *foreign function interface* (FFI) between Safe and Unsafe. +This is the magic behind why we can say Safe is a safe language: all the scary unsafe +bits are relagated *exclusively* to FFI *just like every other safe language*. -That's it. That's all the Undefined Behaviour in Rust. Libraries are free to -declare arbitrary requirements if they could transitively cause memory safety -issues, but it all boils down to the above actions. Rust is otherwise -quite permisive with respect to other dubious operations. Rust considers it -"safe" to: +However because one language is a subset of the other, the two can be cleanly +intermixed as long as the boundary between Safe and Unsafe is denoted with the +`unsafe` keyword. No need to write headers, initialize runtimes, or any of that +other FFI boiler-plate. -* Deadlock -* Have a Race Condition -* Leak memory -* Fail to call destructors -* Overflow integers -* Delete the production database - -However any program that does such a thing is *probably* incorrect. Rust -provides lots of tools to make doing these things rare, but these problems are -considered impractical to categorically prevent. - -Rust models the seperation between Safe and Unsafe with the `unsafe` keyword. There are several places `unsafe` can appear in Rust today, which can largely be grouped into two categories: @@ -44,7 +23,7 @@ you to write `unsafe` elsewhere: the danger. * On trait declarations, `unsafe` is declaring that *implementing* the trait is an unsafe operation, as it has contracts that other unsafe code is free to - trust blindly. + trust blindly. (More on this below.) * I am declaring that I have, to the best of my knowledge, adhered to the unchecked contracts: @@ -55,14 +34,14 @@ unchecked contracts: There is also `#[unsafe_no_drop_flag]`, which is a special case that exists for historical reasons and is in the process of being phased out. See the section on -[destructors][] for details. +[drop flags][] for details. Some examples of unsafe functions: * `slice::get_unchecked` will perform unchecked indexing, allowing memory safety to be freely violated. * `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is - not "in bounds" as defined by LLVM (see the lifetimes section for details). + not "in bounds" as defined by LLVM. * `mem::transmute` reinterprets some value as having the given type, bypassing type safety in arbitrary ways. (see [conversions][] for details) * All FFI functions are `unsafe` because they can do arbitrary things. @@ -72,14 +51,34 @@ Some examples of unsafe functions: As of Rust 1.0 there are exactly two unsafe traits: * `Send` is a marker trait (it has no actual API) that promises implementors - are safe to send to another thread. + are safe to send (move) to another thread. * `Sync` is a marker trait that promises that threads can safely share implementors through a shared reference. -The need for unsafe traits boils down to the fundamental lack of trust that Unsafe -has for Safe. All safe traits are free to declare arbitrary contracts, but because -implementing them is a job for Safe, Unsafe can't trust those contracts to actually -be upheld. +The need for unsafe traits boils down to the fundamental property of safe code: + +**No matter how completely awful Safe code is, it can't cause Undefined +Behaviour.** + +This means that Unsafe, **the royal vanguard of Undefined Behaviour**, has to be +*super paranoid* about generic safe code. Unsafe is free to trust *specific* safe +code (or else you would degenerate into infinite spirals of paranoid despair). +It is generally regarded as ok to trust the standard library to be correct, as +std is effectively an extension of the language (and you *really* just have to trust +the language). If `std` fails to uphold the guarantees it declares, then it's +basically a language bug. + +That said, it would be best to minimize *needlessly* relying on properties of +concrete safe code. Bugs happen! Of course, I must reinforce that this is only +a concern for Unsafe code. Safe code can't blindly trust anyone and everyone +as far as basic memory-safety is concerned. + +On the other hand, safe traits are free to declare arbitrary contracts, but because +implementing them is Safe, Unsafe can't trust those contracts to actually +be upheld. This is different from the concrete case because *anyone* can +randomly implement the interface. There is something fundamentally different +about trusting a *particular* piece of code to be correct, and trusting *all the +code that will ever be written* to be correct. For instance Rust has `PartialOrd` and `Ord` traits to try to differentiate between types which can "just" be compared, and those that actually implement a @@ -99,14 +98,13 @@ destructors will be successfully called! Hooray! However BTreeMap is implemented using a modest spoonful of Unsafe (most collections are). That means that it is not necessarily *trivially true* that a bad Ord implementation will make BTreeMap behave safely. Unsafe must be sure not to rely -on Ord *where safety is at stake*, because Ord is provided by Safe, and memory -safety is not Safe's responsibility to uphold. *It must be impossible for Safe -code to violate memory safety*. +on Ord *where safety is at stake*. Ord is provided by Safe, and safety is not +Safe's responsibility to uphold. But wouldn't it be grand if there was some way for Unsafe to trust *some* trait contracts *somewhere*? This is the problem that unsafe traits tackle: by marking *the trait itself* as unsafe *to implement*, Unsafe can trust the implementation -to be correct (because Unsafe can trust themself). +to be correct. Rust has traditionally avoided making traits unsafe because it makes Unsafe pervasive, which is not desirable. Send and Sync are unsafe is because @@ -114,11 +112,12 @@ thread safety is a *fundamental property* that Unsafe cannot possibly hope to defend against in the same way it would defend against a bad Ord implementation. The only way to possibly defend against thread-unsafety would be to *not use threading at all*. Making every operation atomic isn't even sufficient, because -it's possible for complex invariants between disjoint locations in memory. +it's possible for complex invariants to exist between disjoint locations in +memory. For instance, the pointer and capacity of a Vec must be in sync. Even concurrent paradigms that are traditionally regarded as Totally Safe like message passing implicitly rely on some notion of thread safety -- are you -really message-passing if you send a *pointer*? Send and Sync therefore require +really message-passing if you pass a *pointer*? Send and Sync therefore require some *fundamental* level of trust that Safe code can't provide, so they must be unsafe to implement. To help obviate the pervasive unsafety that this would introduce, Send (resp. Sync) is *automatically* derived for all types composed only @@ -128,8 +127,6 @@ primitives). -[pointer aliasing rules]: lifetimes.html#references -[uninitialized memory]: uninitialized.html -[data race]: concurrency.html -[destructors]: raii.html -[conversions]: conversions.html \ No newline at end of file + +[drop flags]: drop-flags.html +[conversions]: conversions.html diff --git a/working-with-unsafe.md b/working-with-unsafe.md index 57b71d160339..b1174a74c0bc 100644 --- a/working-with-unsafe.md +++ b/working-with-unsafe.md @@ -1,11 +1,11 @@ % Working with Unsafe -Rust generally only gives us the tools to talk about safety in a scoped and -binary manner. Unfortunately reality is significantly more complicated than that. +Rust generally only gives us the tools to talk about Unsafe in a scoped and +binary manner. Unfortunately, reality is significantly more complicated than that. For instance, consider the following toy function: ```rust -fn do_idx(idx: usize, arr: &[u8]) -> Option { +pub fn index(idx: usize, arr: &[u8]) -> Option { if idx < arr.len() { unsafe { Some(*arr.get_unchecked(idx)) @@ -22,7 +22,7 @@ function, the scope of the unsafe block is questionable. Consider changing the `<` to a `<=`: ```rust -fn do_idx(idx: usize, arr: &[u8]) -> Option { +pub fn index(idx: usize, arr: &[u8]) -> Option { if idx <= arr.len() { unsafe { Some(*arr.get_unchecked(idx)) @@ -45,7 +45,7 @@ implementation of `Vec`: ```rust // Note this defintion is insufficient. See the section on lifetimes. -struct Vec { +pub struct Vec { ptr: *mut T, len: usize, cap: usize, @@ -55,7 +55,7 @@ struct Vec { // We currently live in a nice imaginary world of only positive fixed-size // types. impl Vec { - fn push(&mut self, elem: T) { + pub fn push(&mut self, elem: T) { if self.len == self.cap { // not important for this example self.reallocate(); @@ -80,9 +80,25 @@ adding the following method: This code is safe, but it is also completely unsound. Changing the capacity violates the invariants of Vec (that `cap` reflects the allocated space in the -Vec). This is not something the rest of `Vec` can guard against. It *has* to +Vec). This is not something the rest of Vec can guard against. It *has* to trust the capacity field because there's no way to verify it. `unsafe` does more than pollute a whole function: it pollutes a whole *module*. Generally, the only bullet-proof way to limit the scope of unsafe code is at the module boundary with privacy. + +However this works *perfectly*. The existence of `make_room` is *not* a +problem for the soundness of Vec because we didn't mark it as public. Only the +module that defines this function can call it. Also, `make_room` directly +accesses the private fields of Vec, so it can only be written in the same module +as Vec. + +It is therefore possible for us to write a completely safe abstraction that +relies on complex invariants. This is *critical* to the relationship between +Safe Rust and Unsafe Rust. We have already seen that Unsafe code must trust +*some* Safe code, but can't trust *arbitrary* Safe code. However if Unsafe +couldn't prevent client Safe code from messing with its state in arbitrary ways, +safety would be a lost cause. + +Safety lives! + From cbc6408281ce7d67a3454761e832d402971a85cf Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 11:46:57 -0700 Subject: [PATCH 062/104] fix --- safe-unsafe-meaning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/safe-unsafe-meaning.md b/safe-unsafe-meaning.md index 082970d20387..2a593ffc5a7a 100644 --- a/safe-unsafe-meaning.md +++ b/safe-unsafe-meaning.md @@ -70,7 +70,7 @@ basically a language bug. That said, it would be best to minimize *needlessly* relying on properties of concrete safe code. Bugs happen! Of course, I must reinforce that this is only -a concern for Unsafe code. Safe code can't blindly trust anyone and everyone +a concern for Unsafe code. Safe code can blindly trust anyone and everyone as far as basic memory-safety is concerned. On the other hand, safe traits are free to declare arbitrary contracts, but because From d66c67be784a4d0678f60158adb9e76c6b58d9c3 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 17:49:58 -0700 Subject: [PATCH 063/104] clarify atomics --- atomics.md | 85 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/atomics.md b/atomics.md index 39ea2150973a..82e69dd2e13f 100644 --- a/atomics.md +++ b/atomics.md @@ -10,8 +10,8 @@ C. Trying to fully explain the model in this book is fairly hopeless. It's defined in terms of madness-inducing causality graphs that require a full book to properly understand in a practical way. If you want all the nitty-gritty details, you -should check out [C's specification][C11-model]. Still, we'll try to cover the -basics and some of the problems Rust developers face. +should check out [C's specification (Section 7.17)][C11-model]. Still, we'll try +to cover the basics and some of the problems Rust developers face. The C11 memory model is fundamentally about trying to bridge the gap between the semantics we want, the optimizations compilers want, and the inconsistent @@ -127,7 +127,8 @@ to propagate the changes made in data accesses to other threads as lazily and inconsistently as it wants. Mostly critically, data accesses are how data races happen. Data accesses are very friendly to the hardware and compiler, but as we've seen they offer *awful* semantics to try to -write synchronized code with. +write synchronized code with. Actually, that's too weak. *It is literally +impossible to write correct synchronized code using only data accesses*. Atomic accesses are how we tell the hardware and compiler that our program is multi-threaded. Each atomic access can be marked with @@ -146,29 +147,33 @@ exposes are: (Note: We explicitly do not expose the C11 *consume* ordering) TODO: negative reasoning vs positive reasoning? - +TODO: "can't forget to synchronize" # Sequentially Consistent Sequentially Consistent is the most powerful of all, implying the restrictions -of all other orderings. A Sequentially Consistent operation *cannot* +of all other orderings. Intuitively, a sequentially consistent operation *cannot* be reordered: all accesses on one thread that happen before and after it *stay* -before and after it. A program that has sequential consistency has the very nice -property that there is a single global execution of the program's instructions -that all threads agree on. This execution is also particularly nice to reason -about: it's just an interleaving of each thread's individual executions. +before and after it. A data-race-free program that uses only sequentially consistent +atomics and data accesses has the very nice property that there is a single global +execution of the program's instructions that all threads agree on. This execution +is also particularly nice to reason about: it's just an interleaving of each thread's +individual executions. This *does not* hold if you start using the weaker atomic +orderings. The relative developer-friendliness of sequential consistency doesn't come for -free. Even on strongly-ordered platforms, sequential consistency involves +free. Even on strongly-ordered platforms sequential consistency involves emitting memory fences. In practice, sequential consistency is rarely necessary for program correctness. However sequential consistency is definitely the right choice if you're not confident about the other memory orders. Having your program run a bit slower than it needs to is certainly better than it running incorrectly! It's also -completely trivial to downgrade to a weaker consistency later. +*mechanically* trivial to downgrade atomic operations to have a weaker +consistency later on. Just change `SeqCst` to e.g. `Relaxed` and you're done! Of +course, proving that this transformation is *correct* is whole other matter. @@ -179,20 +184,42 @@ Acquire and Release are largely intended to be paired. Their names hint at their use case: they're perfectly suited for acquiring and releasing locks, and ensuring that critical sections don't overlap. -An acquire access ensures that every access after it *stays* after it. However -operations that occur before an acquire are free to be reordered to occur after -it. +Intuitively, an acquire access ensures that every access after it *stays* after +it. However operations that occur before an acquire are free to be reordered to +occur after it. Similarly, a release access ensures that every access before it +*stays* before it. However operations that occur after a release are free to +be reordered to occur before it. -A release access ensures that every access before it *stays* before it. However -operations that occur after a release are free to be reordered to occur before -it. +When thread A releases a location in memory and then thread B subsequently +acquires *the same* location in memory, causality is established. Every write +that happened *before* A's release will be observed by B *after* it's release. +However no causality is established with any other threads. Similarly, no +causality is established if A and B access *different* locations in memory. -Basic use of release-acquire is simple: you acquire a location of memory to -begin the critical section, and the release that location to end it. If -thread A releases a location of memory and thread B acquires that location of -memory, this establishes that A's critical section *happened before* B's -critical section. All accesses that happened before the release will be observed -by anything that happens after the acquire. +Basic use of release-acquire is therefore simple: you acquire a location of +memory to begin the critical section, and then release that location to end it. +For instance, a simple spinlock might look like: + +```rust +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::thread; + +fn main() { + let lock = Arc::new(AtomicBool::new(true)); // value answers "am I locked?" + + // ... distribute lock to threads somehow ... + + // Try to acquire the lock by setting it to false + while !lock.compare_and_swap(true, false, Ordering::Acquire) { } + // broke out of the loop, so we successfully acquired the lock! + + // ... scary data accesses ... + + // ok we're done, release the lock + lock.store(true, Ordering::Release); +} +``` On strongly-ordered platforms most accesses have release or acquire semantics, making release and acquire often totally free. This is not the case on @@ -205,10 +232,12 @@ weakly-ordered platforms. Relaxed accesses are the absolute weakest. They can be freely re-ordered and provide no happens-before relationship. Still, relaxed operations *are* still -atomic, which is valuable. Relaxed operations are appropriate for things that -you definitely want to happen, but don't particularly care about much else. For -instance, incrementing a counter can be relaxed if you're not using the -counter to synchronize any other accesses. +atomic. That is, they don't count as data accesses and any read-modify-write +operations done to them occur atomically. Relaxed operations are appropriate for +things that you definitely want to happen, but don't particularly otherwise care +about. For instance, incrementing a counter can be safely done by multiple +threads using a relaxed `fetch_add` if you're not using the counter to +synchronize any other accesses. There's rarely a benefit in making an operation relaxed on strongly-ordered platforms, since they usually provide release-acquire semantics anyway. However @@ -219,4 +248,4 @@ relaxed operations can be cheaper on weakly-ordered platforms. [C11-busted]: http://plv.mpi-sws.org/c11comp/popl15.pdf -[C11-model]: http://en.cppreference.com/w/c/atomic/memory_order +[C11-model]: http://www.open-std.org/jtc1/sc22/wg14/www/standards.html#9899 From bdc62e009cc5b62fcf356e7977c6397296b2077d Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 21:37:19 -0700 Subject: [PATCH 064/104] fix definition --- references.md | 2 +- working-with-unsafe.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/references.md b/references.md index 1039cb1197b6..24c6b607840d 100644 --- a/references.md +++ b/references.md @@ -138,7 +138,7 @@ This has no semantic consequences, but is probably a more useful notion when verifying the soundness of a construct.) That's it. Super simple right? Except for the fact that it took us two pages -to define all of the terms in that defintion. You know: Super. Simple. +to define all of the terms in that definition. You know: Super. Simple. Actually it's a bit more complicated than that. In addition to references, Rust has *raw pointers*: `*const T` and `*mut T`. Raw pointers have no inherent diff --git a/working-with-unsafe.md b/working-with-unsafe.md index b1174a74c0bc..69d0b31cf88d 100644 --- a/working-with-unsafe.md +++ b/working-with-unsafe.md @@ -44,7 +44,7 @@ Trickier than that is when we get into actual statefulness. Consider a simple implementation of `Vec`: ```rust -// Note this defintion is insufficient. See the section on lifetimes. +// Note this definition is insufficient. See the section on lifetimes. pub struct Vec { ptr: *mut T, len: usize, From d4268f944714dc01fe98c6353d7a23bd9631e4c2 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 22:09:44 -0700 Subject: [PATCH 065/104] shard out and clean up unwinding --- SUMMARY.md | 2 + exception-safety.md | 217 ++++++++++++++++++++++++++++++++++++ poisoning.md | 35 ++++++ unwinding.md | 266 ++------------------------------------------ 4 files changed, 264 insertions(+), 256 deletions(-) create mode 100644 exception-safety.md create mode 100644 poisoning.md diff --git a/SUMMARY.md b/SUMMARY.md index dc494d2b0c94..8a8ea6dfab79 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -30,6 +30,8 @@ * [Destructors](destructors.md) * [Leaking](leaking.md) * [Unwinding](unwinding.md) + * [Exception Safety](exception-safety.md) + * [Poisoning](poisoning.md) * [Concurrency](concurrency.md) * [Races](races.md) * [Send and Sync](send-and-sync.md) diff --git a/exception-safety.md b/exception-safety.md new file mode 100644 index 000000000000..12e000b5ef6e --- /dev/null +++ b/exception-safety.md @@ -0,0 +1,217 @@ +% Exception Safety + +Although programs should use unwinding sparingly, there's *a lot* of code that +*can* panic. If you unwrap a None, index out of bounds, or divide by 0, your +program *will* panic. On debug builds, *every* arithmetic operation can panic +if it overflows. Unless you are very careful and tightly control what code runs, +pretty much everything can unwind, and you need to be ready for it. + +Being ready for unwinding is often referred to as *exception safety* +in the broader programming world. In Rust, their are two levels of exception +safety that one may concern themselves with: + +* In unsafe code, we *must* be exception safe to the point of not violating + memory safety. We'll call this *minimal* exception safety. + +* In safe code, it is *good* to be exception safe to the point of your program + doing the right thing. We'll call this *maximal* exception safety. + +As is the case in many places in Rust, Unsafe code must be ready to deal with +bad Safe code when it comes to unwinding. Code that transiently creates +unsound states must be careful that a panic does not cause that state to be +used. Generally this means ensuring that only non-panicking code is run while +these states exist, or making a guard that cleans up the state in the case of +a panic. This does not necessarily mean that the state a panic witnesses is a +fully *coherent* state. We need only guarantee that it's a *safe* state. + +Most Unsafe code is leaf-like, and therefore fairly easy to make exception-safe. +It controls all the code that runs, and most of that code can't panic. However +it is not uncommon for Unsafe code to work with arrays of temporarily +uninitialized data while repeatedly invoking caller-provided code. Such code +needs to be careful and consider exception safety. + + + + + +## Vec::push_all + +`Vec::push_all` is a temporary hack to get extending a Vec by a slice reliably +effecient without specialization. Here's a simple implementation: + +```rust,ignore +impl Vec { + fn push_all(&mut self, to_push: &[T]) { + self.reserve(to_push.len()); + unsafe { + // can't overflow because we just reserved this + self.set_len(self.len() + to_push.len()); + + for (i, x) in to_push.iter().enumerate() { + self.ptr().offset(i as isize).write(x.clone()); + } + } + } +} +``` + +We bypass `push` in order to avoid redundant capacity and `len` checks on the +Vec that we definitely know has capacity. The logic is totally correct, except +there's a subtle problem with our code: it's not exception-safe! `set_len`, +`offset`, and `write` are all fine, but *clone* is the panic bomb we over-looked. + +Clone is completely out of our control, and is totally free to panic. If it does, +our function will exit early with the length of the Vec set too large. If +the Vec is looked at or dropped, uninitialized memory will be read! + +The fix in this case is fairly simple. If we want to guarantee that the values +we *did* clone are dropped we can set the len *in* the loop. If we just want to +guarantee that uninitialized memory can't be observed, we can set the len *after* +the loop. + + + + + +## BinaryHeap::sift_up + +Bubbling an element up a heap is a bit more complicated than extending a Vec. +The pseudocode is as follows: + +```text +bubble_up(heap, index): + while index != 0 && heap[index] < heap[parent(index)]: + heap.swap(index, parent(index)) + index = parent(index) + +``` + +A literal transcription of this code to Rust is totally fine, but has an annoying +performance characteristic: the `self` element is swapped over and over again +uselessly. We would *rather* have the following: + +```text +bubble_up(heap, index): + let elem = heap[index] + while index != 0 && element < heap[parent(index)]: + heap[index] = heap[parent(index)] + index = parent(index) + heap[index] = elem +``` + +This code ensures that each element is copied as little as possible (it is in +fact necessary that elem be copied twice in general). However it now exposes +some exception safety trouble! At all times, there exists two copies of one +value. If we panic in this function something will be double-dropped. +Unfortunately, we also don't have full control of the code: that comparison is +user-defined! + +Unlike Vec, the fix isn't as easy here. One option is to break the user-defined +code and the unsafe code into two separate phases: + +```text +bubble_up(heap, index): + let end_index = index; + while end_index != 0 && heap[end_index] < heap[parent(end_index)]: + end_index = parent(end_index) + + let elem = heap[index] + while index != end_index: + heap[index] = heap[parent(index)] + index = parent(index) + heap[index] = elem +``` + +If the user-defined code blows up, that's no problem anymore, because we haven't +actually touched the state of the heap yet. Once we do start messing with the +heap, we're working with only data and functions that we trust, so there's no +concern of panics. + +Perhaps you're not happy with this design. Surely, it's cheating! And we have +to do the complex heap traversal *twice*! Alright, let's bite the bullet. Let's +intermix untrusted and unsafe code *for reals*. + +If Rust had `try` and `finally` like in Java, we could do the following: + +```text +bubble_up(heap, index): + let elem = heap[index] + try: + while index != 0 && element < heap[parent(index)]: + heap[index] = heap[parent(index)] + index = parent(index) + finally: + heap[index] = elem +``` + +The basic idea is simple: if the comparison panics, we just toss the loose +element in the logically uninitialized index and bail out. Anyone who observes +the heap will see a potentially *inconsistent* heap, but at least it won't +cause any double-drops! If the algorithm terminates normally, then this +operation happens to coincide precisely with the how we finish up regardless. + +Sadly, Rust has no such construct, so we're going to need to roll our own! The +way to do this is to store the algorithm's state in a separate struct with a +destructor for the "finally" logic. Whether we panic or not, that destructor +will run and clean up after us. + +```rust +struct Hole<'a, T: 'a> { + data: &'a mut [T], + /// `elt` is always `Some` from new until drop. + elt: Option, + pos: usize, +} + +impl<'a, T> Hole<'a, T> { + fn new(data: &'a mut [T], pos: usize) -> Self { + unsafe { + let elt = ptr::read(&data[pos]); + Hole { + data: data, + elt: Some(elt), + pos: pos, + } + } + } + + fn pos(&self) -> usize { self.pos } + + fn removed(&self) -> &T { self.elt.as_ref().unwrap() } + + unsafe fn get(&self, index: usize) -> &T { &self.data[index] } + + unsafe fn move_to(&mut self, index: usize) { + let index_ptr: *const _ = &self.data[index]; + let hole_ptr = &mut self.data[self.pos]; + ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1); + self.pos = index; + } +} + +impl<'a, T> Drop for Hole<'a, T> { + fn drop(&mut self) { + // fill the hole again + unsafe { + let pos = self.pos; + ptr::write(&mut self.data[pos], self.elt.take().unwrap()); + } + } +} + +impl BinaryHeap { + fn sift_up(&mut self, pos: usize) { + unsafe { + // Take out the value at `pos` and create a hole. + let mut hole = Hole::new(&mut self.data, pos); + + while hole.pos() != 0 { + let parent = parent(hole.pos()); + if hole.removed() <= hole.get(parent) { break } + hole.move_to(parent); + } + // Hole will be unconditionally filled here; panic or not! + } + } +} +``` diff --git a/poisoning.md b/poisoning.md new file mode 100644 index 000000000000..6fb16f28e343 --- /dev/null +++ b/poisoning.md @@ -0,0 +1,35 @@ +% Poisoning + +Although all unsafe code *must* ensure it has minimal exception safety, not all +types ensure *maximal* exception safety. Even if the type does, your code may +ascribe additional meaning to it. For instance, an integer is certainly +exception-safe, but has no semantics on its own. It's possible that code that +panics could fail to correctly update the integer, producing an inconsistent +program state. + +This is *usually* fine, because anything that witnesses an exception is about +to get destroyed. For instance, if you send a Vec to another thread and that +thread panics, it doesn't matter if the Vec is in a weird state. It will be +dropped and go away forever. However some types are especially good at smuggling +values across the panic boundary. + +These types may choose to explicitly *poison* themselves if they witness a panic. +Poisoning doesn't entail anything in particular. Generally it just means +preventing normal usage from proceeding. The most notable example of this is the +standard library's Mutex type. A Mutex will poison itself if one of its +MutexGuards (the thing it returns when a lock is obtained) is dropped during a +panic. Any future attempts to lock the Mutex will return an `Err` or panic. + +Mutex poisons not for *true* safety in the sense that Rust normally cares about. It +poisons as a safety-guard against blindly using the data that comes out of a Mutex +that has witnessed a panic while locked. The data in such a Mutex was likely in the +middle of being modified, and as such may be in an inconsistent or incomplete state. +It is important to note that one cannot violate memory safety with such a type +if it is correctly written. After all, it must be minimally exception-safe! + +However if the Mutex contained, say, a BinaryHeap that does not actually have the +heap property, it's unlikely that any code that uses it will do +what the author intended. As such, the program should not proceed normally. +Still, if you're double-plus-sure that you can do *something* with the value, +the Mutex exposes a method to get the lock anyway. It *is* safe, after all. +Just maybe nonsense. diff --git a/unwinding.md b/unwinding.md index 052689655028..59494d864746 100644 --- a/unwinding.md +++ b/unwinding.md @@ -2,14 +2,13 @@ Rust has a *tiered* error-handling scheme: -* If something might reasonably be absent, Option is used -* If something goes wrong and can reasonably be handled, Result is used -* If something goes wrong and cannot reasonably be handled, the thread panics -* If something catastrophic happens, the program aborts +* If something might reasonably be absent, Option is used. +* If something goes wrong and can reasonably be handled, Result is used. +* If something goes wrong and cannot reasonably be handled, the thread panics. +* If something catastrophic happens, the program aborts. Option and Result are overwhelmingly preferred in most situations, especially since they can be promoted into a panic or abort at the API user's discretion. -However, anything and everything *can* panic, and you need to be ready for this. Panics cause the thread to halt normal execution and unwind its stack, calling destructors as if every function instantly returned. @@ -27,13 +26,13 @@ Rust very poor for long-running systems! As the Rust we know today came to be, this style of programming grew out of fashion in the push for less-and-less abstraction. Light-weight tasks were -killed in the name of heavy-weight OS threads. Still, panics could only be -caught by the parent thread. This means catching a panic requires spinning up -an entire OS thread! This unfortunately stands in conflict to Rust's philosophy -of zero-cost abstractions. +killed in the name of heavy-weight OS threads. Still, on stable Rust as of 1.0 +panics can only be caught by the parent thread. This means catching a panic +requires spinning up an entire OS thread! This unfortunately stands in conflict +to Rust's philosophy of zero-cost abstractions. -In the near future there will be a stable interface for catching panics in an -arbitrary location, though we would encourage you to still only do this +There is an *unstable* API called `catch_panic` that enables catching a panic +without spawning a thread. Still, we would encourage you to only do this sparingly. In particular, Rust's current unwinding implementation is heavily optimized for the "doesn't unwind" case. If a program doesn't unwind, there should be no runtime cost for the program being *ready* to unwind. As a @@ -41,251 +40,6 @@ consequence, *actually* unwinding will be more expensive than in e.g. Java. Don't build your programs to unwind under normal circumstances. Ideally, you should only panic for programming errors or *extreme* problems. - - - -# Exception Safety - -Being ready for unwinding is often referred to as *exception safety* -in the broader programming world. In Rust, their are two levels of exception -safety that one may concern themselves with: - -* In unsafe code, we *must* be exception safe to the point of not violating - memory safety. - -* In safe code, it is *good* to be exception safe to the point of your program - doing the right thing. - -As is the case in many places in Rust, unsafe code must be ready to deal with -bad safe code, and that includes code that panics. Code that transiently creates -unsound states must be careful that a panic does not cause that state to be -used. Generally this means ensuring that only non-panicking code is run while -these states exist, or making a guard that cleans up the state in the case of -a panic. This does not necessarily mean that the state a panic witnesses is a -fully *coherent* state. We need only guarantee that it's a *safe* state. - -Most unsafe code is leaf-like, and therefore fairly easy to make exception-safe. -It controls all the code that runs, and most of that code can't panic. However -it is often the case that code that works with arrays works with temporarily -uninitialized data while repeatedly invoking caller-provided code. Such code -needs to be careful, and consider exception-safety. - - - - - -## Vec::push_all - -`Vec::push_all` is a temporary hack to get extending a Vec by a slice reliably -effecient without specialization. Here's a simple implementation: - -```rust,ignore -impl Vec { - fn push_all(&mut self, to_push: &[T]) { - self.reserve(to_push.len()); - unsafe { - // can't overflow because we just reserved this - self.set_len(self.len() + to_push.len()); - - for (i, x) in to_push.iter().enumerate() { - self.ptr().offset(i as isize).write(x.clone()); - } - } - } -} -``` - -We bypass `push` in order to avoid redundant capacity and `len` checks on the -Vec that we definitely know has capacity. The logic is totally correct, except -there's a subtle problem with our code: it's not exception-safe! `set_len`, -`offset`, and `write` are all fine, but *clone* is the panic bomb we over-looked. - -Clone is completely out of our control, and is totally free to panic. If it does, -our function will exit early with the length of the Vec set too large. If -the Vec is looked at or dropped, uninitialized memory will be read! - -The fix in this case is fairly simple. If we want to guarantee that the values -we *did* clone are dropped we can set the len *in* the loop. If we just want to -guarantee that uninitialized memory can't be observed, we can set the len *after* -the loop. - - - - - -## BinaryHeap::sift_up - -Bubbling an element up a heap is a bit more complicated than extending a Vec. -The pseudocode is as follows: - -```text -bubble_up(heap, index): - while index != 0 && heap[index] < heap[parent(index)]: - heap.swap(index, parent(index)) - index = parent(index) - -``` - -A literal transcription of this code to Rust is totally fine, but has an annoying -performance characteristic: the `self` element is swapped over and over again -uselessly. We would *rather* have the following: - -```text -bubble_up(heap, index): - let elem = heap[index] - while index != 0 && element < heap[parent(index)]: - heap[index] = heap[parent(index)] - index = parent(index) - heap[index] = elem -``` - -This code ensures that each element is copied as little as possible (it is in -fact necessary that elem be copied twice in general). However it now exposes -some exception-safety trouble! At all times, there exists two copies of one -value. If we panic in this function something will be double-dropped. -Unfortunately, we also don't have full control of the code: that comparison is -user-defined! - -Unlike Vec, the fix isn't as easy here. One option is to break the user-defined -code and the unsafe code into two separate phases: - -```text -bubble_up(heap, index): - let end_index = index; - while end_index != 0 && heap[end_index] < heap[parent(end_index)]: - end_index = parent(end_index) - - let elem = heap[index] - while index != end_index: - heap[index] = heap[parent(index)] - index = parent(index) - heap[index] = elem -``` - -If the user-defined code blows up, that's no problem anymore, because we haven't -actually touched the state of the heap yet. Once we do start messing with the -heap, we're working with only data and functions that we trust, so there's no -concern of panics. - -Perhaps you're not happy with this design. Surely, it's cheating! And we have -to do the complex heap traversal *twice*! Alright, let's bite the bullet. Let's -intermix untrusted and unsafe code *for reals*. - -If Rust had `try` and `finally` like in Java, we could do the following: - -```text -bubble_up(heap, index): - let elem = heap[index] - try: - while index != 0 && element < heap[parent(index)]: - heap[index] = heap[parent(index)] - index = parent(index) - finally: - heap[index] = elem -``` - -The basic idea is simple: if the comparison panics, we just toss the loose -element in the logically uninitialized index and bail out. Anyone who observes -the heap will see a potentially *inconsistent* heap, but at least it won't -cause any double-drops! If the algorithm terminates normally, then this -operation happens to coincide precisely with the how we finish up regardless. - -Sadly, Rust has no such construct, so we're going to need to roll our own! The -way to do this is to store the algorithm's state in a separate struct with a -destructor for the "finally" logic. Whether we panic or not, that destructor -will run and clean up after us. - -```rust -struct Hole<'a, T: 'a> { - data: &'a mut [T], - /// `elt` is always `Some` from new until drop. - elt: Option, - pos: usize, -} - -impl<'a, T> Hole<'a, T> { - fn new(data: &'a mut [T], pos: usize) -> Self { - unsafe { - let elt = ptr::read(&data[pos]); - Hole { - data: data, - elt: Some(elt), - pos: pos, - } - } - } - - fn pos(&self) -> usize { self.pos } - - fn removed(&self) -> &T { self.elt.as_ref().unwrap() } - - unsafe fn get(&self, index: usize) -> &T { &self.data[index] } - - unsafe fn move_to(&mut self, index: usize) { - let index_ptr: *const _ = &self.data[index]; - let hole_ptr = &mut self.data[self.pos]; - ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1); - self.pos = index; - } -} - -impl<'a, T> Drop for Hole<'a, T> { - fn drop(&mut self) { - // fill the hole again - unsafe { - let pos = self.pos; - ptr::write(&mut self.data[pos], self.elt.take().unwrap()); - } - } -} - -impl BinaryHeap { - fn sift_up(&mut self, pos: usize) { - unsafe { - // Take out the value at `pos` and create a hole. - let mut hole = Hole::new(&mut self.data, pos); - - while hole.pos() != 0 { - let parent = parent(hole.pos()); - if hole.removed() <= hole.get(parent) { break } - hole.move_to(parent); - } - // Hole will be unconditionally filled here; panic or not! - } - } -} -``` - - - - -## Poisoning - -Although all unsafe code *must* ensure some minimal level of exception safety, -some types may choose to explicitly *poison* themselves if they witness a panic. -Poisoning doesn't entail anything in particular. Generally it just means -preventing normal usage from proceeding. The most notable example of this is the -standard library's Mutex type. A Mutex will poison itself if one of its -MutexGuards (the thing it returns when a lock is obtained) is dropped during a -panic. Any future attempts to lock the Mutex will return an `Err`. - -Mutex poisons not for *true* safety in the sense that Rust normally cares about. It -poisons as a safety-guard against blindly using the data that comes out of a Mutex -that has witnessed a panic while locked. The data in such a Mutex was likely in the -middle of being modified, and as such may be in an inconsistent or incomplete state. -It is important to note that one cannot violate memory safety with such a type -if it is correctly written. After all, it must be minimally exception safe! - -However if the Mutex contained, say, a BinaryHeap that does not actually have the -heap property, it's unlikely that any code that uses it will do -what the author intended. As such, the program should not proceed normally. -Still, if you're double-plus-sure that you can do *something* with the value, -the Err exposes a method to get the lock anyway. It *is* safe, after all. - - - -# FFI - Rust's unwinding strategy is not specified to be fundamentally compatible with any other language's unwinding. As such, unwinding into Rust from another language, or unwinding into another language from Rust is Undefined Behaviour. From d96a518316da8eb1ab4a7af1b8b34b1f5b00fd3f Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 22:36:09 -0700 Subject: [PATCH 066/104] several fixups --- other-reprs.md | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/other-reprs.md b/other-reprs.md index 068d30c5e3da..d168dcbe360b 100644 --- a/other-reprs.md +++ b/other-reprs.md @@ -26,9 +26,26 @@ the FFI boundary. * DSTs, tuples, and tagged unions are not a concept in C and as such are never FFI safe. -* **The drop flag will still be added** +* **The [drop flag][] will still be added** -* This is equivalent to `repr(u32)` for enums (see below) +* This is equivalent to one of `repr(u\*)` (see the next section) for enums. The + chosen size is the default enum size for the target platform's C ABI. Note that + enum representation in C is undefined, and this may be incorrect when the C + code is compiled with certain flags. + + + +# repr(u8), repr(u16), repr(u32), repr(u64) + +These specify the size to make a C-like enum. If the discriminant overflows the +integer it has to fit in, it will be an error. You can manually ask Rust to +allow this by setting the overflowing element to explicitly be 0. However Rust +will not allow you to create an enum where two variants have the same discriminant. + +On non-C-like enums, this will inhibit certain optimizations like the null-pointer +optimization. + +These reprs have no affect on a struct. @@ -40,22 +57,15 @@ byte. This may improve the memory footprint, but will likely have other negative side-effects. In particular, most architectures *strongly* prefer values to be aligned. This -may mean the unaligned loads are penalized (x86), or even fault (ARM). In -particular, the compiler may have trouble with references to unaligned fields. +may mean the unaligned loads are penalized (x86), or even fault (some ARM chips). +For simple cases like directly loading or storing a packed field, the compiler +might be able to paper over alignment issues with shifts and masks. However if +you take a reference to a packed field, it's unlikely that the compiler will be +able to emit code to avoid an unaligned load. `repr(packed)` is not to be used lightly. Unless you have extreme requirements, this should not be used. This repr is a modifier on `repr(C)` and `repr(rust)`. - - - -# repr(u8), repr(u16), repr(u32), repr(u64) - -These specify the size to make a C-like enum. If the discriminant overflows the -integer it has to fit in, it will be an error. You can manually ask Rust to -allow this by setting the overflowing element to explicitly be 0. However Rust -will not allow you to create an enum where two variants. - -These reprs have no affect on a struct or non-C-like enum. \ No newline at end of file +[drop flag]: drop-flags.html From 667afb82261103abf6533b3f287b8969beee5bb3 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 22:37:03 -0700 Subject: [PATCH 067/104] remove salsh --- other-reprs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other-reprs.md b/other-reprs.md index d168dcbe360b..829a15e6355b 100644 --- a/other-reprs.md +++ b/other-reprs.md @@ -28,7 +28,7 @@ the FFI boundary. * **The [drop flag][] will still be added** -* This is equivalent to one of `repr(u\*)` (see the next section) for enums. The +* This is equivalent to one of `repr(u*)` (see the next section) for enums. The chosen size is the default enum size for the target platform's C ABI. Note that enum representation in C is undefined, and this may be incorrect when the C code is compiled with certain flags. From c7919f2d9835578321bf7556ad1a01fa42e8a7e8 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 23:13:56 -0700 Subject: [PATCH 068/104] remove chaff --- FiraSans-Medium.woff | Bin 89883 -> 0 bytes FiraSans-Regular.woff | Bin 91946 -> 0 bytes Heuristica-Italic.woff | Bin 119956 -> 0 bytes SourceCodePro-Regular.woff | Bin 55472 -> 0 bytes SourceCodePro-Semibold.woff | Bin 55360 -> 0 bytes SourceSerifPro-Bold.woff | Bin 48720 -> 0 bytes SourceSerifPro-Regular.woff | Bin 49960 -> 0 bytes rust.css | 407 ------------------------------------ 8 files changed, 407 deletions(-) delete mode 100644 FiraSans-Medium.woff delete mode 100644 FiraSans-Regular.woff delete mode 100644 Heuristica-Italic.woff delete mode 100644 SourceCodePro-Regular.woff delete mode 100644 SourceCodePro-Semibold.woff delete mode 100644 SourceSerifPro-Bold.woff delete mode 100644 SourceSerifPro-Regular.woff delete mode 100644 rust.css diff --git a/FiraSans-Medium.woff b/FiraSans-Medium.woff deleted file mode 100644 index 5627227744ae5b2ffb83e632cb32b237428c8962..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89883 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�r0V}5GiG~jD5(}oW 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 JADJxw9RO|dotppv diff --git a/FiraSans-Regular.woff b/FiraSans-Regular.woff deleted file mode 100644 index 9ff40445bf4a6f459c4ba7399555ba89bbf39181..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91946 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 diff --git a/Heuristica-Italic.woff b/Heuristica-Italic.woff deleted file mode 100644 index b0cebf01de49b61c0f1ec5cb47f2687c64e918c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119956 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
iP2J|6?(P$8 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 diff --git a/SourceCodePro-Regular.woff b/SourceCodePro-Regular.woff deleted file mode 100644 index 5576670903aea90041f214624c8dd1176fdf6081..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55472 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 SbK%{4Uj1i(_C*df+z0@cHiz^8 diff --git a/SourceCodePro-Semibold.woff b/SourceCodePro-Semibold.woff deleted file mode 100644 index ca972a11dc428209dd66212e382b884f168e83f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55360 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∨L+#A0B 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 diff --git a/SourceSerifPro-Bold.woff b/SourceSerifPro-Bold.woff deleted file mode 100644 index ac1b1b3a0bb7a673d52495743d8f86fd55188b44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48720 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 TMcZC+MUG$MhoYLkF)#oC1SsqC diff --git a/SourceSerifPro-Regular.woff b/SourceSerifPro-Regular.woff deleted file mode 100644 index e8c43b852e10e1556268d6c17b47bd0644d6edec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49960 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 or the MIT license - * , at your - * option. This file may not be copied, modified, or distributed - * except according to those terms. - */ -@font-face { - font-family: 'Fira Sans'; - font-style: normal; - font-weight: 400; - src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff'); -} -@font-face { - font-family: 'Fira Sans'; - font-style: normal; - font-weight: 500; - src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff'); -} -@font-face { - font-family: 'Source Serif Pro'; - font-style: normal; - font-weight: 400; - src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff'); -} -@font-face { - font-family: 'Source Serif Pro'; - font-style: italic; - font-weight: 400; - src: url("Heuristica-Italic.woff") format('woff'); -} -@font-face { - font-family: 'Source Serif Pro'; - font-style: normal; - font-weight: 700; - src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff'); -} -@font-face { - font-family: 'Source Code Pro'; - font-style: normal; - font-weight: 400; - src: local('Source Code Pro'), url("SourceCodePro-Regular.woff") format('woff'); -} - -*:not(body) { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -/* General structure */ - -body { - background-color: white; - margin: 0 auto; - padding: 0 15px; - font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif; - font-size: 18px; - color: #333; - line-height: 1.428571429; - - -webkit-font-feature-settings: "kern", "liga"; - -moz-font-feature-settings: "kern", "liga"; - font-feature-settings: "kern", "liga"; -} -@media (min-width: 768px) { - body { - max-width: 750px; - } -} - -h1, h2, h3, h4, h5, h6, nav, #versioninfo { - font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; -} -h1, h2, h3, h4, h5, h6 { - color: black; - font-weight: 400; - line-height: 1.1; -} -h1, h2, h3 { - margin-top: 20px; - margin-bottom: 15px; -} -h1 { - margin-bottom: 20px; -} -h4, h5, h6 { - margin-top: 12px; - margin-bottom: 10px; - padding: 5px 10px; -} -h5, h6 { - text-decoration: underline; -} - -h1 { - font-size: 28px; - font-weight: 500; - padding: .1em .4em; - border-bottom: 2px solid #ddd; -} -h1.title { - line-height: 1.5em; -} -h2 { - font-size: 26px; - padding: .2em .5em; - border-bottom: 1px solid #ddd; -} -h3 { - font-size: 24px; - padding: .2em .7em; - border-bottom: 1px solid #DDE8FC; -} -h4 { - font-size: 22px; -} -h5 { - font-size: 20px; -} -h6 { - font-size: 18px; -} -@media (min-width: 992px) { - h1 { - font-size: 36px; - } - h2 { - font-size: 30px; - } - h3 { - font-size: 26px; - } -} - -nav { - column-count: 2; - -moz-column-count: 2; - -webkit-column-count: 2; - font-size: 15px; - margin: 0 0 1em 0; -} -p { - margin: 0 0 1em 0; -} - -strong { - font-weight: bold; -} - -em { - font-style: italic; -} - -footer { - border-top: 1px solid #ddd; - font-size: 14.3px; - font-style: italic; - padding-top: 5px; - margin-top: 3em; - margin-bottom: 1em; -} - -/* Links layout */ - -a { - text-decoration: none; - color: #428BCA; - background: transparent; -} -a:hover, a:focus { - color: #2A6496; - text-decoration: underline; -} -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -a:hover, a:active { - outline: 0; -} - -h1 a:link, h1 a:visited, h2 a:link, h2 a:visited, -h3 a:link, h3 a:visited, h4 a:link, h4 a:visited, -h5 a:link, h5 a:visited {color: black;} -h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, -h5 a:hover {text-decoration: none;} - -/* Code */ - -pre, code { - font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace; - word-wrap: break-word; -} -pre { - border-left: 2px solid #eee; - white-space: pre-wrap; - padding: 14px; - padding-right: 0; - margin: 20px 0; - font-size: 13px; - word-break: break-all; -} -code { - padding: 0 2px; - color: #8D1A38; -} -pre code { - padding: 0; - font-size: inherit; - color: inherit; -} - -a > code { - color: #428BCA; -} - -/* Code highlighting */ -pre.rust .kw { color: #8959A8; } -pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; } -pre.rust .number, pre.rust .string { color: #718C00; } -pre.rust .self, pre.rust .boolval, pre.rust .prelude-val, -pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; } -pre.rust .comment { color: #8E908C; } -pre.rust .doccomment { color: #4D4D4C; } -pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } -pre.rust .lifetime { color: #B76514; } - -/* The rest */ - -#versioninfo { - text-align: center; - margin: 0.5em; - font-size: 1.1em; -} -@media (min-width: 992px) { - #versioninfo { - font-size: 0.8em; - position: fixed; - bottom: 0px; - right: 0px; - } - .white-sticker { - background-color: #fff; - margin: 2px; - padding: 0 2px; - border-radius: .2em; - } -} -#versioninfo a.hash { - color: gray; - font-size: 80%; -} - -blockquote { - color: #000; - margin: 20px 0; - padding: 15px 20px; - background-color: #f2f7f9; - border-top: .1em solid #e5eef2; - border-bottom: .1em solid #e5eef2; -} -blockquote p { - font-size: 17px; - font-weight: 300; - line-height: 1.4; -} -blockquote p:last-child { - margin-bottom: 0; -} - -ul, ol { - padding-left: 25px; -} -ul ul, ol ul, ul ol, ol ol { - margin-bottom: 0; -} -dl { - margin-bottom: 20px; -} -dd { - margin-left: 0; -} - -nav ul { - list-style-type: none; - margin: 0; - padding-left: 0px; -} - -/* Only display one level of hierarchy in the TOC */ -nav ul ul { - display: none; -} - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; -} - -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eeeeee; -} - -table { - border-collapse: collapse; - border-spacing: 0; - overflow-x: auto; - display: block; -} - -table tr.odd { - background: #eee; -} - -table td, -table th { - border: 1px solid #ddd; - padding: 5px; -} - -/* Code snippets */ - -.rusttest { display: none; } -pre.rust { position: relative; } -.test-arrow { - display: inline-block; - position: absolute; - top: 0; - right: 10px; - font-size: 150%; - -webkit-transform: scaleX(-1); - transform: scaleX(-1); -} - -.unstable-feature { - border: 2px solid red; - padding: 5px; -} - -@media (min-width: 1170px) { - pre { - font-size: 15px; - } -} - -@media print { - * { - text-shadow: none !important; - color: #000 !important; - background: transparent !important; - box-shadow: none !important; - } - a, a:visited { - text-decoration: underline; - } - p a[href]:after { - content: " (" attr(href) ")"; - } - footer a[href]:after { - content: ""; - } - a[href^="javascript:"]:after, a[href^="#"]:after { - content: ""; - } - pre, blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - @page { - margin: 2cm .5cm; - } - h1:not(.title), h2, h3 { - border-bottom: 0px none; - } - p, h2, h3 { - orphans: 3; - widows: 3; - } - h2, h3 { - page-break-after: avoid; - } - table { - border-collapse: collapse !important; - } - table td, table th { - background-color: #fff !important; - } -} - -#keyword-table-marker + table thead { display: none; } -#keyword-table-marker + table td { border: none; } -#keyword-table-marker + table { - margin-left: 2em; - margin-bottom: 1em; -} From a54e64b3c41103c4f6ab840d8ddd3a56ec6b5da8 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 23:14:57 -0700 Subject: [PATCH 069/104] move everything to tarpl --- README.md => src/doc/tarpl/README.md | 0 SUMMARY.md => src/doc/tarpl/SUMMARY.md | 0 arc-and-mutex.md => src/doc/tarpl/arc-and-mutex.md | 0 atomics.md => src/doc/tarpl/atomics.md | 0 casts.md => src/doc/tarpl/casts.md | 0 checked-uninit.md => src/doc/tarpl/checked-uninit.md | 0 coercions.md => src/doc/tarpl/coercions.md | 0 concurrency.md => src/doc/tarpl/concurrency.md | 0 constructors.md => src/doc/tarpl/constructors.md | 0 conversions.md => src/doc/tarpl/conversions.md | 0 data.md => src/doc/tarpl/data.md | 0 destructors.md => src/doc/tarpl/destructors.md | 0 dot-operator.md => src/doc/tarpl/dot-operator.md | 0 drop-flags.md => src/doc/tarpl/drop-flags.md | 0 exception-safety.md => src/doc/tarpl/exception-safety.md | 0 exotic-sizes.md => src/doc/tarpl/exotic-sizes.md | 0 hrtb.md => src/doc/tarpl/hrtb.md | 0 leaking.md => src/doc/tarpl/leaking.md | 0 lifetime-elision.md => src/doc/tarpl/lifetime-elision.md | 0 lifetime-misc.md => src/doc/tarpl/lifetime-misc.md | 0 lifetime-mismatch.md => src/doc/tarpl/lifetime-mismatch.md | 0 lifetimes.md => src/doc/tarpl/lifetimes.md | 0 meet-safe-and-unsafe.md => src/doc/tarpl/meet-safe-and-unsafe.md | 0 other-reprs.md => src/doc/tarpl/other-reprs.md | 0 ownership.md => src/doc/tarpl/ownership.md | 0 poisoning.md => src/doc/tarpl/poisoning.md | 0 races.md => src/doc/tarpl/races.md | 0 raii.md => src/doc/tarpl/raii.md | 0 references.md => src/doc/tarpl/references.md | 0 repr-rust.md => src/doc/tarpl/repr-rust.md | 0 safe-unsafe-meaning.md => src/doc/tarpl/safe-unsafe-meaning.md | 0 send-and-sync.md => src/doc/tarpl/send-and-sync.md | 0 subtyping.md => src/doc/tarpl/subtyping.md | 0 transmutes.md => src/doc/tarpl/transmutes.md | 0 unbounded-lifetimes.md => src/doc/tarpl/unbounded-lifetimes.md | 0 unchecked-uninit.md => src/doc/tarpl/unchecked-uninit.md | 0 uninitialized.md => src/doc/tarpl/uninitialized.md | 0 unwinding.md => src/doc/tarpl/unwinding.md | 0 vec-alloc.md => src/doc/tarpl/vec-alloc.md | 0 vec-dealloc.md => src/doc/tarpl/vec-dealloc.md | 0 vec-deref.md => src/doc/tarpl/vec-deref.md | 0 vec-drain.md => src/doc/tarpl/vec-drain.md | 0 vec-final.md => src/doc/tarpl/vec-final.md | 0 vec-insert-remove.md => src/doc/tarpl/vec-insert-remove.md | 0 vec-into-iter.md => src/doc/tarpl/vec-into-iter.md | 0 vec-layout.md => src/doc/tarpl/vec-layout.md | 0 vec-push-pop.md => src/doc/tarpl/vec-push-pop.md | 0 vec.md => src/doc/tarpl/vec.md | 0 working-with-unsafe.md => src/doc/tarpl/working-with-unsafe.md | 0 49 files changed, 0 insertions(+), 0 deletions(-) rename README.md => src/doc/tarpl/README.md (100%) rename SUMMARY.md => src/doc/tarpl/SUMMARY.md (100%) rename arc-and-mutex.md => src/doc/tarpl/arc-and-mutex.md (100%) rename atomics.md => src/doc/tarpl/atomics.md (100%) rename casts.md => src/doc/tarpl/casts.md (100%) rename checked-uninit.md => src/doc/tarpl/checked-uninit.md (100%) rename coercions.md => src/doc/tarpl/coercions.md (100%) rename concurrency.md => src/doc/tarpl/concurrency.md (100%) rename constructors.md => src/doc/tarpl/constructors.md (100%) rename conversions.md => src/doc/tarpl/conversions.md (100%) rename data.md => src/doc/tarpl/data.md (100%) rename destructors.md => src/doc/tarpl/destructors.md (100%) rename dot-operator.md => src/doc/tarpl/dot-operator.md (100%) rename drop-flags.md => src/doc/tarpl/drop-flags.md (100%) rename exception-safety.md => src/doc/tarpl/exception-safety.md (100%) rename exotic-sizes.md => src/doc/tarpl/exotic-sizes.md (100%) rename hrtb.md => src/doc/tarpl/hrtb.md (100%) rename leaking.md => src/doc/tarpl/leaking.md (100%) rename lifetime-elision.md => src/doc/tarpl/lifetime-elision.md (100%) rename lifetime-misc.md => src/doc/tarpl/lifetime-misc.md (100%) rename lifetime-mismatch.md => src/doc/tarpl/lifetime-mismatch.md (100%) rename lifetimes.md => src/doc/tarpl/lifetimes.md (100%) rename meet-safe-and-unsafe.md => src/doc/tarpl/meet-safe-and-unsafe.md (100%) rename other-reprs.md => src/doc/tarpl/other-reprs.md (100%) rename ownership.md => src/doc/tarpl/ownership.md (100%) rename poisoning.md => src/doc/tarpl/poisoning.md (100%) rename races.md => src/doc/tarpl/races.md (100%) rename raii.md => src/doc/tarpl/raii.md (100%) rename references.md => src/doc/tarpl/references.md (100%) rename repr-rust.md => src/doc/tarpl/repr-rust.md (100%) rename safe-unsafe-meaning.md => src/doc/tarpl/safe-unsafe-meaning.md (100%) rename send-and-sync.md => src/doc/tarpl/send-and-sync.md (100%) rename subtyping.md => src/doc/tarpl/subtyping.md (100%) rename transmutes.md => src/doc/tarpl/transmutes.md (100%) rename unbounded-lifetimes.md => src/doc/tarpl/unbounded-lifetimes.md (100%) rename unchecked-uninit.md => src/doc/tarpl/unchecked-uninit.md (100%) rename uninitialized.md => src/doc/tarpl/uninitialized.md (100%) rename unwinding.md => src/doc/tarpl/unwinding.md (100%) rename vec-alloc.md => src/doc/tarpl/vec-alloc.md (100%) rename vec-dealloc.md => src/doc/tarpl/vec-dealloc.md (100%) rename vec-deref.md => src/doc/tarpl/vec-deref.md (100%) rename vec-drain.md => src/doc/tarpl/vec-drain.md (100%) rename vec-final.md => src/doc/tarpl/vec-final.md (100%) rename vec-insert-remove.md => src/doc/tarpl/vec-insert-remove.md (100%) rename vec-into-iter.md => src/doc/tarpl/vec-into-iter.md (100%) rename vec-layout.md => src/doc/tarpl/vec-layout.md (100%) rename vec-push-pop.md => src/doc/tarpl/vec-push-pop.md (100%) rename vec.md => src/doc/tarpl/vec.md (100%) rename working-with-unsafe.md => src/doc/tarpl/working-with-unsafe.md (100%) diff --git a/README.md b/src/doc/tarpl/README.md similarity index 100% rename from README.md rename to src/doc/tarpl/README.md diff --git a/SUMMARY.md b/src/doc/tarpl/SUMMARY.md similarity index 100% rename from SUMMARY.md rename to src/doc/tarpl/SUMMARY.md diff --git a/arc-and-mutex.md b/src/doc/tarpl/arc-and-mutex.md similarity index 100% rename from arc-and-mutex.md rename to src/doc/tarpl/arc-and-mutex.md diff --git a/atomics.md b/src/doc/tarpl/atomics.md similarity index 100% rename from atomics.md rename to src/doc/tarpl/atomics.md diff --git a/casts.md b/src/doc/tarpl/casts.md similarity index 100% rename from casts.md rename to src/doc/tarpl/casts.md diff --git a/checked-uninit.md b/src/doc/tarpl/checked-uninit.md similarity index 100% rename from checked-uninit.md rename to src/doc/tarpl/checked-uninit.md diff --git a/coercions.md b/src/doc/tarpl/coercions.md similarity index 100% rename from coercions.md rename to src/doc/tarpl/coercions.md diff --git a/concurrency.md b/src/doc/tarpl/concurrency.md similarity index 100% rename from concurrency.md rename to src/doc/tarpl/concurrency.md diff --git a/constructors.md b/src/doc/tarpl/constructors.md similarity index 100% rename from constructors.md rename to src/doc/tarpl/constructors.md diff --git a/conversions.md b/src/doc/tarpl/conversions.md similarity index 100% rename from conversions.md rename to src/doc/tarpl/conversions.md diff --git a/data.md b/src/doc/tarpl/data.md similarity index 100% rename from data.md rename to src/doc/tarpl/data.md diff --git a/destructors.md b/src/doc/tarpl/destructors.md similarity index 100% rename from destructors.md rename to src/doc/tarpl/destructors.md diff --git a/dot-operator.md b/src/doc/tarpl/dot-operator.md similarity index 100% rename from dot-operator.md rename to src/doc/tarpl/dot-operator.md diff --git a/drop-flags.md b/src/doc/tarpl/drop-flags.md similarity index 100% rename from drop-flags.md rename to src/doc/tarpl/drop-flags.md diff --git a/exception-safety.md b/src/doc/tarpl/exception-safety.md similarity index 100% rename from exception-safety.md rename to src/doc/tarpl/exception-safety.md diff --git a/exotic-sizes.md b/src/doc/tarpl/exotic-sizes.md similarity index 100% rename from exotic-sizes.md rename to src/doc/tarpl/exotic-sizes.md diff --git a/hrtb.md b/src/doc/tarpl/hrtb.md similarity index 100% rename from hrtb.md rename to src/doc/tarpl/hrtb.md diff --git a/leaking.md b/src/doc/tarpl/leaking.md similarity index 100% rename from leaking.md rename to src/doc/tarpl/leaking.md diff --git a/lifetime-elision.md b/src/doc/tarpl/lifetime-elision.md similarity index 100% rename from lifetime-elision.md rename to src/doc/tarpl/lifetime-elision.md diff --git a/lifetime-misc.md b/src/doc/tarpl/lifetime-misc.md similarity index 100% rename from lifetime-misc.md rename to src/doc/tarpl/lifetime-misc.md diff --git a/lifetime-mismatch.md b/src/doc/tarpl/lifetime-mismatch.md similarity index 100% rename from lifetime-mismatch.md rename to src/doc/tarpl/lifetime-mismatch.md diff --git a/lifetimes.md b/src/doc/tarpl/lifetimes.md similarity index 100% rename from lifetimes.md rename to src/doc/tarpl/lifetimes.md diff --git a/meet-safe-and-unsafe.md b/src/doc/tarpl/meet-safe-and-unsafe.md similarity index 100% rename from meet-safe-and-unsafe.md rename to src/doc/tarpl/meet-safe-and-unsafe.md diff --git a/other-reprs.md b/src/doc/tarpl/other-reprs.md similarity index 100% rename from other-reprs.md rename to src/doc/tarpl/other-reprs.md diff --git a/ownership.md b/src/doc/tarpl/ownership.md similarity index 100% rename from ownership.md rename to src/doc/tarpl/ownership.md diff --git a/poisoning.md b/src/doc/tarpl/poisoning.md similarity index 100% rename from poisoning.md rename to src/doc/tarpl/poisoning.md diff --git a/races.md b/src/doc/tarpl/races.md similarity index 100% rename from races.md rename to src/doc/tarpl/races.md diff --git a/raii.md b/src/doc/tarpl/raii.md similarity index 100% rename from raii.md rename to src/doc/tarpl/raii.md diff --git a/references.md b/src/doc/tarpl/references.md similarity index 100% rename from references.md rename to src/doc/tarpl/references.md diff --git a/repr-rust.md b/src/doc/tarpl/repr-rust.md similarity index 100% rename from repr-rust.md rename to src/doc/tarpl/repr-rust.md diff --git a/safe-unsafe-meaning.md b/src/doc/tarpl/safe-unsafe-meaning.md similarity index 100% rename from safe-unsafe-meaning.md rename to src/doc/tarpl/safe-unsafe-meaning.md diff --git a/send-and-sync.md b/src/doc/tarpl/send-and-sync.md similarity index 100% rename from send-and-sync.md rename to src/doc/tarpl/send-and-sync.md diff --git a/subtyping.md b/src/doc/tarpl/subtyping.md similarity index 100% rename from subtyping.md rename to src/doc/tarpl/subtyping.md diff --git a/transmutes.md b/src/doc/tarpl/transmutes.md similarity index 100% rename from transmutes.md rename to src/doc/tarpl/transmutes.md diff --git a/unbounded-lifetimes.md b/src/doc/tarpl/unbounded-lifetimes.md similarity index 100% rename from unbounded-lifetimes.md rename to src/doc/tarpl/unbounded-lifetimes.md diff --git a/unchecked-uninit.md b/src/doc/tarpl/unchecked-uninit.md similarity index 100% rename from unchecked-uninit.md rename to src/doc/tarpl/unchecked-uninit.md diff --git a/uninitialized.md b/src/doc/tarpl/uninitialized.md similarity index 100% rename from uninitialized.md rename to src/doc/tarpl/uninitialized.md diff --git a/unwinding.md b/src/doc/tarpl/unwinding.md similarity index 100% rename from unwinding.md rename to src/doc/tarpl/unwinding.md diff --git a/vec-alloc.md b/src/doc/tarpl/vec-alloc.md similarity index 100% rename from vec-alloc.md rename to src/doc/tarpl/vec-alloc.md diff --git a/vec-dealloc.md b/src/doc/tarpl/vec-dealloc.md similarity index 100% rename from vec-dealloc.md rename to src/doc/tarpl/vec-dealloc.md diff --git a/vec-deref.md b/src/doc/tarpl/vec-deref.md similarity index 100% rename from vec-deref.md rename to src/doc/tarpl/vec-deref.md diff --git a/vec-drain.md b/src/doc/tarpl/vec-drain.md similarity index 100% rename from vec-drain.md rename to src/doc/tarpl/vec-drain.md diff --git a/vec-final.md b/src/doc/tarpl/vec-final.md similarity index 100% rename from vec-final.md rename to src/doc/tarpl/vec-final.md diff --git a/vec-insert-remove.md b/src/doc/tarpl/vec-insert-remove.md similarity index 100% rename from vec-insert-remove.md rename to src/doc/tarpl/vec-insert-remove.md diff --git a/vec-into-iter.md b/src/doc/tarpl/vec-into-iter.md similarity index 100% rename from vec-into-iter.md rename to src/doc/tarpl/vec-into-iter.md diff --git a/vec-layout.md b/src/doc/tarpl/vec-layout.md similarity index 100% rename from vec-layout.md rename to src/doc/tarpl/vec-layout.md diff --git a/vec-push-pop.md b/src/doc/tarpl/vec-push-pop.md similarity index 100% rename from vec-push-pop.md rename to src/doc/tarpl/vec-push-pop.md diff --git a/vec.md b/src/doc/tarpl/vec.md similarity index 100% rename from vec.md rename to src/doc/tarpl/vec.md diff --git a/working-with-unsafe.md b/src/doc/tarpl/working-with-unsafe.md similarity index 100% rename from working-with-unsafe.md rename to src/doc/tarpl/working-with-unsafe.md From 04578f6611ca5da47b23fa0d10381f7858b3a325 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 13 Jul 2015 23:31:52 -0700 Subject: [PATCH 070/104] update build to make tarpl --- mk/docs.mk | 9 ++++++++- mk/tests.mk | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mk/docs.mk b/mk/docs.mk index 617c3ddf8dec..3acc3c68b8fd 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -77,7 +77,7 @@ ERR_IDX_GEN = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(ERR_IDX_GEN_EXE) D := $(S)src/doc -DOC_TARGETS := trpl style error-index +DOC_TARGETS := trpl tarpl style error-index COMPILER_DOC_TARGETS := DOC_L10N_TARGETS := @@ -287,6 +287,13 @@ doc/book/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/trpl/*.md) | doc/ $(Q)rm -rf doc/book $(Q)$(RUSTBOOK) build $(S)src/doc/trpl doc/book +tarpl: doc/adv-book/index.html + +doc/adv-book/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/tarpl/*.md) | doc/ + @$(call E, rustbook: $@) + $(Q)rm -rf doc/adv-book + $(Q)$(RUSTBOOK) build $(S)src/doc/tarpl doc/adv-book + style: doc/style/index.html doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/ diff --git a/mk/tests.mk b/mk/tests.mk index 185cc9b2f4c5..c0962a1b0e78 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -162,7 +162,8 @@ $(foreach doc,$(DOCS), \ $(eval $(call DOCTEST,md-$(doc),$(S)src/doc/$(doc).md))) $(foreach file,$(wildcard $(S)src/doc/trpl/*.md), \ $(eval $(call DOCTEST,$(file:$(S)src/doc/trpl/%.md=trpl-%),$(file)))) - +$(foreach file,$(wildcard $(S)src/doc/tarpl/*.md), \ + $(eval $(call DOCTEST,$(file:$(S)src/doc/tarpl/%.md=tarpl-%),$(file)))) ###################################################################### # Main test targets ###################################################################### From dba548d3634d1f69b6210b642e700c2c41e69ce9 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 14 Jul 2015 00:26:08 -0700 Subject: [PATCH 071/104] fix via mdinger --- src/doc/tarpl/repr-rust.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/tarpl/repr-rust.md b/src/doc/tarpl/repr-rust.md index caf60bed8c53..a1f5f29f8d85 100644 --- a/src/doc/tarpl/repr-rust.md +++ b/src/doc/tarpl/repr-rust.md @@ -109,7 +109,7 @@ struct FooRepr { And indeed this is approximately how it would be laid out in general (modulo the size and position of `tag`). However there are several cases where -such a representation is ineffiecient. The classic case of this is Rust's +such a representation is inefficient. The classic case of this is Rust's "null pointer optimization". Given a pointer that is known to not be null (e.g. `&u32`), an enum can *store* a discriminant bit *inside* the pointer by using null as a special value. The net result is that @@ -121,4 +121,4 @@ nested enums pooling their tags into a single descriminant, as they are by definition known to have a limited range of valid values. In principle enums can use fairly elaborate algorithms to cache bits throughout nested types with special constrained representations. As such it is *especially* desirable that -we leave enum layout unspecified today. \ No newline at end of file +we leave enum layout unspecified today. From 58f6f2d57a4d0a62f17003facd0d2406da75a035 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 14 Jul 2015 09:56:10 -0700 Subject: [PATCH 072/104] nits and realigning --- src/doc/tarpl/README.md | 6 +- src/doc/tarpl/arc-and-mutex.md | 2 +- src/doc/tarpl/atomics.md | 159 +++++++++++------------ src/doc/tarpl/casts.md | 27 ++-- src/doc/tarpl/checked-uninit.md | 56 ++++---- src/doc/tarpl/constructors.md | 30 +++-- src/doc/tarpl/conversions.md | 16 +-- src/doc/tarpl/destructors.md | 127 +++++++++--------- src/doc/tarpl/drop-flags.md | 56 ++++---- src/doc/tarpl/exception-safety.md | 13 +- src/doc/tarpl/exotic-sizes.md | 50 +++---- src/doc/tarpl/leaking.md | 209 +++++++++++++++--------------- src/doc/tarpl/other-reprs.md | 54 ++++---- src/doc/tarpl/references.md | 108 +++++++-------- src/doc/tarpl/send-and-sync.md | 61 ++++----- 15 files changed, 497 insertions(+), 477 deletions(-) diff --git a/src/doc/tarpl/README.md b/src/doc/tarpl/README.md index 874f6f2ac612..0b627737138a 100644 --- a/src/doc/tarpl/README.md +++ b/src/doc/tarpl/README.md @@ -34,6 +34,6 @@ Due to the nature of advanced Rust programming, we will be spending a lot of tim talking about *safety* and *guarantees*. In particular, a significant portion of the book will be dedicated to correctly writing and understanding Unsafe Rust. -[trpl]: https://doc.rust-lang.org/book/ -[The stack and heap]: https://doc.rust-lang.org/book/the-stack-and-the-heap.html -[Basic Rust]: https://doc.rust-lang.org/book/syntax-and-semantics.html +[trpl]: ../book/ +[The stack and heap]: ../book/the-stack-and-the-heap.html +[Basic Rust]: ../book/syntax-and-semantics.html diff --git a/src/doc/tarpl/arc-and-mutex.md b/src/doc/tarpl/arc-and-mutex.md index d28180fa9cf5..fcafe55e409b 100644 --- a/src/doc/tarpl/arc-and-mutex.md +++ b/src/doc/tarpl/arc-and-mutex.md @@ -1,6 +1,6 @@ % Implementing Arc and Mutex -Knowing the theory is all fine and good, but the *best* was to understand +Knowing the theory is all fine and good, but the *best* way to understand something is to use it. To better understand atomics and interior mutability, we'll be implementing versions of the standard library's Arc and Mutex types. diff --git a/src/doc/tarpl/atomics.md b/src/doc/tarpl/atomics.md index 82e69dd2e13f..8395b22c8d8e 100644 --- a/src/doc/tarpl/atomics.md +++ b/src/doc/tarpl/atomics.md @@ -2,21 +2,22 @@ Rust pretty blatantly just inherits C11's memory model for atomics. This is not due this model being particularly excellent or easy to understand. Indeed, this -model is quite complex and known to have [several flaws][C11-busted]. Rather, -it is a pragmatic concession to the fact that *everyone* is pretty bad at modeling +model is quite complex and known to have [several flaws][C11-busted]. Rather, it +is a pragmatic concession to the fact that *everyone* is pretty bad at modeling atomics. At very least, we can benefit from existing tooling and research around C. Trying to fully explain the model in this book is fairly hopeless. It's defined -in terms of madness-inducing causality graphs that require a full book to properly -understand in a practical way. If you want all the nitty-gritty details, you -should check out [C's specification (Section 7.17)][C11-model]. Still, we'll try -to cover the basics and some of the problems Rust developers face. +in terms of madness-inducing causality graphs that require a full book to +properly understand in a practical way. If you want all the nitty-gritty +details, you should check out [C's specification (Section 7.17)][C11-model]. +Still, we'll try to cover the basics and some of the problems Rust developers +face. -The C11 memory model is fundamentally about trying to bridge the gap between -the semantics we want, the optimizations compilers want, and the inconsistent -chaos our hardware wants. *We* would like to just write programs and have them -do exactly what we said but, you know, *fast*. Wouldn't that be great? +The C11 memory model is fundamentally about trying to bridge the gap between the +semantics we want, the optimizations compilers want, and the inconsistent chaos +our hardware wants. *We* would like to just write programs and have them do +exactly what we said but, you know, *fast*. Wouldn't that be great? @@ -41,13 +42,14 @@ x = 2; y = 3; ``` -This has inverted the order of events *and* completely eliminated one event. From -a single-threaded perspective this is completely unobservable: after all the -statements have executed we are in exactly the same state. But if our program is -multi-threaded, we may have been relying on `x` to *actually* be assigned to 1 before -`y` was assigned. We would *really* like the compiler to be able to make these kinds -of optimizations, because they can seriously improve performance. On the other hand, -we'd really like to be able to depend on our program *doing the thing we said*. +This has inverted the order of events *and* completely eliminated one event. +From a single-threaded perspective this is completely unobservable: after all +the statements have executed we are in exactly the same state. But if our +program is multi-threaded, we may have been relying on `x` to *actually* be +assigned to 1 before `y` was assigned. We would *really* like the compiler to be +able to make these kinds of optimizations, because they can seriously improve +performance. On the other hand, we'd really like to be able to depend on our +program *doing the thing we said*. @@ -55,19 +57,20 @@ we'd really like to be able to depend on our program *doing the thing we said*. # Hardware Reordering On the other hand, even if the compiler totally understood what we wanted and -respected our wishes, our *hardware* might instead get us in trouble. Trouble comes -from CPUs in the form of memory hierarchies. There is indeed a global shared memory -space somewhere in your hardware, but from the perspective of each CPU core it is -*so very far away* and *so very slow*. Each CPU would rather work with its local -cache of the data and only go through all the *anguish* of talking to shared -memory *only* when it doesn't actually have that memory in cache. +respected our wishes, our *hardware* might instead get us in trouble. Trouble +comes from CPUs in the form of memory hierarchies. There is indeed a global +shared memory space somewhere in your hardware, but from the perspective of each +CPU core it is *so very far away* and *so very slow*. Each CPU would rather work +with its local cache of the data and only go through all the *anguish* of +talking to shared memory *only* when it doesn't actually have that memory in +cache. After all, that's the whole *point* of the cache, right? If every read from the cache had to run back to shared memory to double check that it hadn't changed, what would the point be? The end result is that the hardware doesn't guarantee -that events that occur in the same order on *one* thread, occur in the same order -on *another* thread. To guarantee this, we must issue special instructions to -the CPU telling it to be a bit less smart. +that events that occur in the same order on *one* thread, occur in the same +order on *another* thread. To guarantee this, we must issue special instructions +to the CPU telling it to be a bit less smart. For instance, say we convince the compiler to emit this logic: @@ -82,27 +85,27 @@ x = 1; y *= 2; Ideally this program has 2 possible final states: -* `y = 3`: (thread 2 did the check before thread 1 completed) -* `y = 6`: (thread 2 did the check after thread 1 completed) +* `y = 3`: (thread 2 did the check before thread 1 completed) y = 6`: (thread 2 +* `did the check after thread 1 completed) However there's a third potential state that the hardware enables: * `y = 2`: (thread 2 saw `x = 2`, but not `y = 3`, and then overwrote `y = 3`) It's worth noting that different kinds of CPU provide different guarantees. It -is common to seperate hardware into two categories: strongly-ordered and weakly- -ordered. Most notably x86/64 provides strong ordering guarantees, while ARM and -provides weak ordering guarantees. This has two consequences for -concurrent programming: +is common to separate hardware into two categories: strongly-ordered and weakly- +ordered. Most notably x86/64 provides strong ordering guarantees, while ARM +provides weak ordering guarantees. This has two consequences for concurrent +programming: * Asking for stronger guarantees on strongly-ordered hardware may be cheap or even *free* because they already provide strong guarantees unconditionally. Weaker guarantees may only yield performance wins on weakly-ordered hardware. -* Asking for guarantees that are *too* weak on strongly-ordered hardware - is more likely to *happen* to work, even though your program is strictly - incorrect. If possible, concurrent algorithms should be tested on - weakly-ordered hardware. +* Asking for guarantees that are *too* weak on strongly-ordered hardware is + more likely to *happen* to work, even though your program is strictly + incorrect. If possible, concurrent algorithms should be tested on weakly- + ordered hardware. @@ -110,58 +113,54 @@ concurrent programming: # Data Accesses -The C11 memory model attempts to bridge the gap by allowing us to talk about -the *causality* of our program. Generally, this is by establishing a -*happens before* relationships between parts of the program and the threads -that are running them. This gives the hardware and compiler room to optimize the -program more aggressively where a strict happens-before relationship isn't -established, but forces them to be more careful where one *is* established. -The way we communicate these relationships are through *data accesses* and -*atomic accesses*. +The C11 memory model attempts to bridge the gap by allowing us to talk about the +*causality* of our program. Generally, this is by establishing a *happens +before* relationships between parts of the program and the threads that are +running them. This gives the hardware and compiler room to optimize the program +more aggressively where a strict happens-before relationship isn't established, +but forces them to be more careful where one *is* established. The way we +communicate these relationships are through *data accesses* and *atomic +accesses*. Data accesses are the bread-and-butter of the programming world. They are fundamentally unsynchronized and compilers are free to aggressively optimize -them. In particular, data accesses are free to be reordered by the compiler -on the assumption that the program is single-threaded. The hardware is also free -to propagate the changes made in data accesses to other threads -as lazily and inconsistently as it wants. Mostly critically, data accesses are -how data races happen. Data accesses are very friendly to the hardware and -compiler, but as we've seen they offer *awful* semantics to try to -write synchronized code with. Actually, that's too weak. *It is literally -impossible to write correct synchronized code using only data accesses*. +them. In particular, data accesses are free to be reordered by the compiler on +the assumption that the program is single-threaded. The hardware is also free to +propagate the changes made in data accesses to other threads as lazily and +inconsistently as it wants. Mostly critically, data accesses are how data races +happen. Data accesses are very friendly to the hardware and compiler, but as +we've seen they offer *awful* semantics to try to write synchronized code with. +Actually, that's too weak. *It is literally impossible to write correct +synchronized code using only data accesses*. Atomic accesses are how we tell the hardware and compiler that our program is -multi-threaded. Each atomic access can be marked with -an *ordering* that specifies what kind of relationship it establishes with -other accesses. In practice, this boils down to telling the compiler and hardware -certain things they *can't* do. For the compiler, this largely revolves -around re-ordering of instructions. For the hardware, this largely revolves -around how writes are propagated to other threads. The set of orderings Rust -exposes are: +multi-threaded. Each atomic access can be marked with an *ordering* that +specifies what kind of relationship it establishes with other accesses. In +practice, this boils down to telling the compiler and hardware certain things +they *can't* do. For the compiler, this largely revolves around re-ordering of +instructions. For the hardware, this largely revolves around how writes are +propagated to other threads. The set of orderings Rust exposes are: -* Sequentially Consistent (SeqCst) -* Release -* Acquire -* Relaxed +* Sequentially Consistent (SeqCst) Release Acquire Relaxed (Note: We explicitly do not expose the C11 *consume* ordering) -TODO: negative reasoning vs positive reasoning? -TODO: "can't forget to synchronize" +TODO: negative reasoning vs positive reasoning? TODO: "can't forget to +synchronize" # Sequentially Consistent Sequentially Consistent is the most powerful of all, implying the restrictions -of all other orderings. Intuitively, a sequentially consistent operation *cannot* -be reordered: all accesses on one thread that happen before and after it *stay* -before and after it. A data-race-free program that uses only sequentially consistent -atomics and data accesses has the very nice property that there is a single global -execution of the program's instructions that all threads agree on. This execution -is also particularly nice to reason about: it's just an interleaving of each thread's -individual executions. This *does not* hold if you start using the weaker atomic -orderings. +of all other orderings. Intuitively, a sequentially consistent operation +*cannot* be reordered: all accesses on one thread that happen before and after a +SeqCst access *stay* before and after it. A data-race-free program that uses +only sequentially consistent atomics and data accesses has the very nice +property that there is a single global execution of the program's instructions +that all threads agree on. This execution is also particularly nice to reason +about: it's just an interleaving of each thread's individual executions. This +*does not* hold if you start using the weaker atomic orderings. The relative developer-friendliness of sequential consistency doesn't come for free. Even on strongly-ordered platforms sequential consistency involves @@ -173,26 +172,26 @@ confident about the other memory orders. Having your program run a bit slower than it needs to is certainly better than it running incorrectly! It's also *mechanically* trivial to downgrade atomic operations to have a weaker consistency later on. Just change `SeqCst` to e.g. `Relaxed` and you're done! Of -course, proving that this transformation is *correct* is whole other matter. +course, proving that this transformation is *correct* is a whole other matter. # Acquire-Release -Acquire and Release are largely intended to be paired. Their names hint at -their use case: they're perfectly suited for acquiring and releasing locks, -and ensuring that critical sections don't overlap. +Acquire and Release are largely intended to be paired. Their names hint at their +use case: they're perfectly suited for acquiring and releasing locks, and +ensuring that critical sections don't overlap. Intuitively, an acquire access ensures that every access after it *stays* after it. However operations that occur before an acquire are free to be reordered to occur after it. Similarly, a release access ensures that every access before it -*stays* before it. However operations that occur after a release are free to -be reordered to occur before it. +*stays* before it. However operations that occur after a release are free to be +reordered to occur before it. When thread A releases a location in memory and then thread B subsequently acquires *the same* location in memory, causality is established. Every write -that happened *before* A's release will be observed by B *after* it's release. +that happened *before* A's release will be observed by B *after* its release. However no causality is established with any other threads. Similarly, no causality is established if A and B access *different* locations in memory. diff --git a/src/doc/tarpl/casts.md b/src/doc/tarpl/casts.md index 730d8499acfe..cbcf81d83712 100644 --- a/src/doc/tarpl/casts.md +++ b/src/doc/tarpl/casts.md @@ -1,12 +1,13 @@ % Casts -Casts are a superset of coercions: every coercion can be explicitly invoked via a -cast, but some conversions *require* a cast. These "true casts" are generally regarded -as dangerous or problematic actions. True casts revolve around raw pointers and -the primitive numeric types. True casts aren't checked. +Casts are a superset of coercions: every coercion can be explicitly invoked via +a cast, but some conversions *require* a cast. These "true casts" are generally +regarded as dangerous or problematic actions. True casts revolve around raw +pointers and the primitive numeric types. True casts aren't checked. Here's an exhaustive list of all the true casts. For brevity, we will use `*` -to denote either a `*const` or `*mut`, and `integer` to denote any integral primitive: +to denote either a `*const` or `*mut`, and `integer` to denote any integral +primitive: * `*T as *U` where `T, U: Sized` * `*T as *U` TODO: explain unsized situation @@ -37,19 +38,21 @@ expression, `e as U2` is not necessarily so (in fact it will only be valid if For numeric casts, there are quite a few cases to consider: * casting between two integers of the same size (e.g. i32 -> u32) is a no-op -* casting from a larger integer to a smaller integer (e.g. u32 -> u8) will truncate +* casting from a larger integer to a smaller integer (e.g. u32 -> u8) will + truncate * casting from a smaller integer to a larger integer (e.g. u8 -> u32) will * zero-extend if the source is unsigned * sign-extend if the source is signed * casting from a float to an integer will round the float towards zero * **NOTE: currently this will cause Undefined Behaviour if the rounded - value cannot be represented by the target integer type**. This is a bug - and will be fixed. (TODO: figure out what Inf and NaN do) -* casting from an integer to float will produce the floating point representation - of the integer, rounded if necessary (rounding strategy unspecified). -* casting from an f32 to an f64 is perfect and lossless. + value cannot be represented by the target integer type**. This includes + Inf and NaN. This is a bug and will be fixed. +* casting from an integer to float will produce the floating point + representation of the integer, rounded if necessary (rounding strategy + unspecified) +* casting from an f32 to an f64 is perfect and lossless * casting from an f64 to an f32 will produce the closest possible value - (rounding strategy unspecified). + (rounding strategy unspecified) * **NOTE: currently this will cause Undefined Behaviour if the value is finite but larger or smaller than the largest or smallest finite value representable by f32**. This is a bug and will be fixed. diff --git a/src/doc/tarpl/checked-uninit.md b/src/doc/tarpl/checked-uninit.md index 8896fc9de019..667afe012d55 100644 --- a/src/doc/tarpl/checked-uninit.md +++ b/src/doc/tarpl/checked-uninit.md @@ -1,13 +1,13 @@ % Checked Uninitialized Memory -Like C, all stack variables in Rust are uninitialized until a -value is explicitly assigned to them. Unlike C, Rust statically prevents you -from ever reading them until you do: +Like C, all stack variables in Rust are uninitialized until a value is +explicitly assigned to them. Unlike C, Rust statically prevents you from ever +reading them until you do: ```rust fn main() { - let x: i32; - println!("{}", x); + let x: i32; + println!("{}", x); } ``` @@ -25,13 +25,13 @@ or anything like that. So this compiles: ```rust fn main() { - let x: i32; + let x: i32; - if true { - x = 1; - } else { - x = 2; - } + if true { + x = 1; + } else { + x = 2; + } println!("{}", x); } @@ -41,30 +41,30 @@ but this doesn't: ```rust fn main() { - let x: i32; - if true { - x = 1; - } - println!("{}", x); + let x: i32; + if true { + x = 1; + } + println!("{}", x); } ``` ```text src/main.rs:6:17: 6:18 error: use of possibly uninitialized variable: `x` -src/main.rs:6 println!("{}", x); +src/main.rs:6 println!("{}", x); ``` while this does: ```rust fn main() { - let x: i32; - if true { - x = 1; - println!("{}", x); - } - // Don't care that there are branches where it's not initialized - // since we don't use the value in those branches + let x: i32; + if true { + x = 1; + println!("{}", x); + } + // Don't care that there are branches where it's not initialized + // since we don't use the value in those branches } ``` @@ -73,10 +73,10 @@ uninitialized if the type of the value isn't Copy. That is: ```rust fn main() { - let x = 0; - let y = Box::new(0); - let z1 = x; // x is still valid because i32 is Copy - let z2 = y; // y is now logically uninitialized because Box isn't Copy + let x = 0; + let y = Box::new(0); + let z1 = x; // x is still valid because i32 is Copy + let z2 = y; // y is now logically uninitialized because Box isn't Copy } ``` diff --git a/src/doc/tarpl/constructors.md b/src/doc/tarpl/constructors.md index 99bcf5e283ee..023dea08444a 100644 --- a/src/doc/tarpl/constructors.md +++ b/src/doc/tarpl/constructors.md @@ -5,31 +5,31 @@ and initialize all its fields at once: ```rust struct Foo { - a: u8, - b: u32, - c: bool, + a: u8, + b: u32, + c: bool, } enum Bar { - X(u32), - Y(bool), + X(u32), + Y(bool), } -struct Empty; +struct Unit; let foo = Foo { a: 0, b: 1, c: false }; let bar = Bar::X(0); -let empty = Empty; +let empty = Unit; ``` That's it. Every other way you make an instance of a type is just calling a totally vanilla function that does some stuff and eventually bottoms out to The One True Constructor. -Unlike C++, Rust does not come with a slew of built in kinds of constructor. +Unlike C++, Rust does not come with a slew of built-in kinds of constructor. There are no Copy, Default, Assignment, Move, or whatever constructors. The -reasons for this are varied, but it largely boils down to Rust's philosophy -of *being explicit*. +reasons for this are varied, but it largely boils down to Rust's philosophy of +*being explicit*. Move constructors are meaningless in Rust because we don't enable types to "care" about their location in memory. Every type must be ready for it to be @@ -37,9 +37,9 @@ blindly memcopied to somewhere else in memory. This means pure on-the-stack-but- still-movable intrusive linked lists are simply not happening in Rust (safely). Assignment and copy constructors similarly don't exist because move semantics -are the *only* semantics in Rust. At most `x = y` just moves the bits of y into the x -variable. Rust *does* provide two facilities for providing C++'s copy-oriented -semantics: `Copy` and `Clone`. Clone is our moral equivalent of a copy +are the *only* semantics in Rust. At most `x = y` just moves the bits of y into +the x variable. Rust *does* provide two facilities for providing C++'s copy- +oriented semantics: `Copy` and `Clone`. Clone is our moral equivalent of a copy constructor, but it's never implicitly invoked. You have to explicitly call `clone` on an element you want to be cloned. Copy is a special case of Clone where the implementation is just "copy the bits". Copy types *are* implicitly @@ -53,3 +53,7 @@ only useful for generic programming. In concrete contexts, a type will provide a static `new` method for any kind of "default" constructor. This has no relation to `new` in other languages and has no special meaning. It's just a naming convention. + +TODO: talk about "placement new"? + +[uninit]: uninitialized.html diff --git a/src/doc/tarpl/conversions.md b/src/doc/tarpl/conversions.md index 388516fc7e9e..56c050072b97 100644 --- a/src/doc/tarpl/conversions.md +++ b/src/doc/tarpl/conversions.md @@ -1,13 +1,13 @@ % Type Conversions -At the end of the day, everything is just a pile of bits somewhere, and type systems -are just there to help us use those bits right. Needing to reinterpret those piles -of bits as different types is a common problem and Rust consequently gives you -several ways to do that. +At the end of the day, everything is just a pile of bits somewhere, and type +systems are just there to help us use those bits right. Needing to reinterpret +those piles of bits as different types is a common problem and Rust consequently +gives you several ways to do that. -First we'll look at the ways that *Safe Rust* gives you to reinterpret values. The -most trivial way to do this is to just destructure a value into its constituent -parts and then build a new type out of them. e.g. +First we'll look at the ways that *Safe Rust* gives you to reinterpret values. +The most trivial way to do this is to just destructure a value into its +constituent parts and then build a new type out of them. e.g. ```rust struct Foo { @@ -26,6 +26,6 @@ fn reinterpret(foo: Foo) -> Bar { } ``` -But this is, at best, annoying to do. For common conversions, rust provides +But this is, at best, annoying to do. For common conversions, Rust provides more ergonomic alternatives. diff --git a/src/doc/tarpl/destructors.md b/src/doc/tarpl/destructors.md index 3bc75c132bf6..cf6378c3e25a 100644 --- a/src/doc/tarpl/destructors.md +++ b/src/doc/tarpl/destructors.md @@ -1,23 +1,24 @@ % Destructors -What the language *does* provide is full-blown automatic destructors through the `Drop` trait, -which provides the following method: +What the language *does* provide is full-blown automatic destructors through the +`Drop` trait, which provides the following method: ```rust fn drop(&mut self); ``` -This method gives the type time to somehow finish what it was doing. **After `drop` is run, -Rust will recursively try to drop all of the fields of `self`**. This is a -convenience feature so that you don't have to write "destructor boilerplate" to drop -children. If a struct has no special logic for being dropped other than dropping its -children, then it means `Drop` doesn't need to be implemented at all! +This method gives the type time to somehow finish what it was doing. **After +`drop` is run, Rust will recursively try to drop all of the fields of `self`**. +This is a convenience feature so that you don't have to write "destructor +boilerplate" to drop children. If a struct has no special logic for being +dropped other than dropping its children, then it means `Drop` doesn't need to +be implemented at all! -**There is no stable way to prevent this behaviour in Rust 1.0**. +**There is no stable way to prevent this behaviour in Rust 1.0. -Note that taking `&mut self` means that even if you *could* suppress recursive Drop, -Rust will prevent you from e.g. moving fields out of self. For most types, this -is totally fine. +Note that taking `&mut self` means that even if you *could* suppress recursive +Drop, Rust will prevent you from e.g. moving fields out of self. For most types, +this is totally fine. For instance, a custom implementation of `Box` might write `Drop` like this: @@ -25,18 +26,18 @@ For instance, a custom implementation of `Box` might write `Drop` like this: struct Box{ ptr: *mut T } impl Drop for Box { - fn drop(&mut self) { - unsafe { - (*self.ptr).drop(); - heap::deallocate(self.ptr); - } - } + fn drop(&mut self) { + unsafe { + (*self.ptr).drop(); + heap::deallocate(self.ptr); + } + } } ``` -and this works fine because when Rust goes to drop the `ptr` field it just sees a *mut that -has no actual `Drop` implementation. Similarly nothing can use-after-free the `ptr` because -the Box is immediately marked as uninitialized. +and this works fine because when Rust goes to drop the `ptr` field it just sees +a *mut that has no actual `Drop` implementation. Similarly nothing can use- +after-free the `ptr` because the Box is immediately marked as uninitialized. However this wouldn't work: @@ -44,24 +45,24 @@ However this wouldn't work: struct Box{ ptr: *mut T } impl Drop for Box { - fn drop(&mut self) { - unsafe { - (*self.ptr).drop(); - heap::deallocate(self.ptr); - } - } + fn drop(&mut self) { + unsafe { + (*self.ptr).drop(); + heap::deallocate(self.ptr); + } + } } struct SuperBox { box: Box } impl Drop for SuperBox { - fn drop(&mut self) { - unsafe { - // Hyper-optimized: deallocate the box's contents for it - // without `drop`ing the contents - heap::deallocate(self.box.ptr); - } - } + fn drop(&mut self) { + unsafe { + // Hyper-optimized: deallocate the box's contents for it + // without `drop`ing the contents + heap::deallocate(self.box.ptr); + } + } } ``` @@ -74,9 +75,9 @@ regardless of whether they implement Drop. Therefore something like ```rust struct Boxy { - data1: Box, - data2: Box, - info: u32, + data1: Box, + data2: Box, + info: u32, } ``` @@ -88,16 +89,18 @@ Similarly, ```rust enum Link { - Next(Box), - None, + Next(Box), + None, } ``` -will have its inner Box field dropped *if and only if* an instance stores the Next variant. +will have its inner Box field dropped *if and only if* an instance stores the +Next variant. -In general this works really nice because you don't need to worry about adding/removing -drops when you refactor your data layout. Still there's certainly many valid usecases for -needing to do trickier things with destructors. +In general this works really nice because you don't need to worry about +adding/removing drops when you refactor your data layout. Still there's +certainly many valid usecases for needing to do trickier things with +destructors. The classic safe solution to overriding recursive drop and allowing moving out of Self during `drop` is to use an Option: @@ -106,35 +109,35 @@ of Self during `drop` is to use an Option: struct Box{ ptr: *mut T } impl Drop for Box { - fn drop(&mut self) { - unsafe { - (*self.ptr).drop(); - heap::deallocate(self.ptr); - } - } + fn drop(&mut self) { + unsafe { + (*self.ptr).drop(); + heap::deallocate(self.ptr); + } + } } struct SuperBox { box: Option> } impl Drop for SuperBox { - fn drop(&mut self) { - unsafe { - // Hyper-optimized: deallocate the box's contents for it - // without `drop`ing the contents. Need to set the `box` - // field as `None` to prevent Rust from trying to Drop it. - heap::deallocate(self.box.take().unwrap().ptr); - } - } + fn drop(&mut self) { + unsafe { + // Hyper-optimized: deallocate the box's contents for it + // without `drop`ing the contents. Need to set the `box` + // field as `None` to prevent Rust from trying to Drop it. + heap::deallocate(self.box.take().unwrap().ptr); + } + } } ``` -However this has fairly odd semantics: you're saying that a field that *should* always -be Some may be None, just because that happens in the destructor. Of course this -conversely makes a lot of sense: you can call arbitrary methods on self during -the destructor, and this should prevent you from ever doing so after deinitializing -the field. Not that it will prevent you from producing any other +However this has fairly odd semantics: you're saying that a field that *should* +always be Some may be None, just because that happens in the destructor. Of +course this conversely makes a lot of sense: you can call arbitrary methods on +self during the destructor, and this should prevent you from ever doing so after +deinitializing the field. Not that it will prevent you from producing any other arbitrarily invalid state in there. On balance this is an ok choice. Certainly what you should reach for by default. However, in the future we expect there to be a first-class way to announce that -a field shouldn't be automatically dropped. \ No newline at end of file +a field shouldn't be automatically dropped. diff --git a/src/doc/tarpl/drop-flags.md b/src/doc/tarpl/drop-flags.md index 2d5bae6dcfe9..68f7ffc77b00 100644 --- a/src/doc/tarpl/drop-flags.md +++ b/src/doc/tarpl/drop-flags.md @@ -3,43 +3,43 @@ The examples in the previous section introduce an interesting problem for Rust. We have seen that's possible to conditionally initialize, deinitialize, and *reinitialize* locations of memory totally safely. For Copy types, this isn't -particularly notable since they're just a random pile of bits. However types with -destructors are a different story: Rust needs to know whether to call a destructor -whenever a variable is assigned to, or a variable goes out of scope. How can it -do this with conditional initialization? +particularly notable since they're just a random pile of bits. However types +with destructors are a different story: Rust needs to know whether to call a +destructor whenever a variable is assigned to, or a variable goes out of scope. +How can it do this with conditional initialization? -It turns out that Rust actually tracks whether a type should be dropped or not *at -runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for -that variable is toggled. When a variable *might* need to be dropped, this flag -is evaluated to determine if it *should* be dropped. +It turns out that Rust actually tracks whether a type should be dropped or not +*at runtime*. As a variable becomes initialized and uninitialized, a *drop flag* +for that variable is toggled. When a variable *might* need to be dropped, this +flag is evaluated to determine if it *should* be dropped. Of course, it is *often* the case that a value's initialization state can be *statically* known at every point in the program. If this is the case, then the -compiler can theoretically generate more effecient code! For instance, -straight-line code has such *static drop semantics*: +compiler can theoretically generate more effecient code! For instance, straight- +line code has such *static drop semantics*: ```rust -let mut x = Box::new(0); // x was uninit -let mut y = x; // y was uninit -x = Box::new(0); // x was uninit -y = x; // y was init; Drop y! - // y was init; Drop y! - // x was uninit +let mut x = Box::new(0); // x was uninit; just overwrite. +let mut y = x; // y was uninit; just overwrite and make x uninit. +x = Box::new(0); // x was uninit; just overwrite. +y = x; // y was init; Drop y, overwrite it, and make x uninit! + // y was init; Drop y! + // x was uninit; do nothing. ``` And even branched code where all branches have the same behaviour with respect to initialization: ```rust -let mut x = Box::new(0); // x was uninit +let mut x = Box::new(0); // x was uninit; just overwrite. if condition { - drop(x) // x gets moved out + drop(x) // x gets moved out; make x uninit. } else { - println!("{}", x); - drop(x) // x gets moved out + println!("{}", x); + drop(x) // x gets moved out; make x uninit. } -x = Box::new(0); // x was uninit - // x was init; Drop x! +x = Box::new(0); // x was uninit; just overwrite. + // x was init; Drop x! ``` However code like this *requires* runtime information to correctly Drop: @@ -47,18 +47,18 @@ However code like this *requires* runtime information to correctly Drop: ```rust let x; if condition { - x = Box::new(0); // x was uninit - println!("{}", x); + x = Box::new(0); // x was uninit; just overwrite. + println!("{}", x); } - // x might be uninit; check the flag! + // x *might* be uninit; check the flag! ``` Of course, in this case it's trivial to retrieve static drop semantics: ```rust if condition { - let x = Box::new(0); - println!("{}", x); + let x = Box::new(0); + println!("{}", x); } ``` @@ -75,4 +75,4 @@ as it requires fairly substantial changes to the compiler. Regardless, Rust programs don't need to worry about uninitialized values on the stack for correctness. Although they might care for performance. Thankfully, Rust makes it easy to take control here! Uninitialized values are there, and -you can work with them in Safe Rust, but you're *never* in danger. \ No newline at end of file +you can work with them in Safe Rust, but you're *never* in danger. diff --git a/src/doc/tarpl/exception-safety.md b/src/doc/tarpl/exception-safety.md index 12e000b5ef6e..ca3310978112 100644 --- a/src/doc/tarpl/exception-safety.md +++ b/src/doc/tarpl/exception-safety.md @@ -7,7 +7,7 @@ if it overflows. Unless you are very careful and tightly control what code runs, pretty much everything can unwind, and you need to be ready for it. Being ready for unwinding is often referred to as *exception safety* -in the broader programming world. In Rust, their are two levels of exception +in the broader programming world. In Rust, there are two levels of exception safety that one may concern themselves with: * In unsafe code, we *must* be exception safe to the point of not violating @@ -58,16 +58,17 @@ impl Vec { We bypass `push` in order to avoid redundant capacity and `len` checks on the Vec that we definitely know has capacity. The logic is totally correct, except there's a subtle problem with our code: it's not exception-safe! `set_len`, -`offset`, and `write` are all fine, but *clone* is the panic bomb we over-looked. +`offset`, and `write` are all fine, but *clone* is the panic bomb we over- +looked. -Clone is completely out of our control, and is totally free to panic. If it does, -our function will exit early with the length of the Vec set too large. If +Clone is completely out of our control, and is totally free to panic. If it +does, our function will exit early with the length of the Vec set too large. If the Vec is looked at or dropped, uninitialized memory will be read! The fix in this case is fairly simple. If we want to guarantee that the values we *did* clone are dropped we can set the len *in* the loop. If we just want to -guarantee that uninitialized memory can't be observed, we can set the len *after* -the loop. +guarantee that uninitialized memory can't be observed, we can set the len +*after* the loop. diff --git a/src/doc/tarpl/exotic-sizes.md b/src/doc/tarpl/exotic-sizes.md index ea8dc86d1f0a..5eeb4850d876 100644 --- a/src/doc/tarpl/exotic-sizes.md +++ b/src/doc/tarpl/exotic-sizes.md @@ -9,18 +9,19 @@ is not always the case, however. # Dynamically Sized Types (DSTs) -Rust also supports types without a statically known size. On the surface, -this is a bit nonsensical: Rust *must* know the size of something in order to -work with it! DSTs are generally produced as views, or through type-erasure -of types that *do* have a known size. Due to their lack of a statically known -size, these types can only exist *behind* some kind of pointer. They consequently -produce a *fat* pointer consisting of the pointer and the information that -*completes* them. +Rust also supports types without a statically known size. On the surface, this +is a bit nonsensical: Rust *must* know the size of something in order to work +with it! DSTs are generally produced as views, or through type-erasure of types +that *do* have a known size. Due to their lack of a statically known size, these +types can only exist *behind* some kind of pointer. They consequently produce a +*fat* pointer consisting of the pointer and the information that *completes* +them. -For instance, the slice type, `[T]`, is some statically unknown number of elements -stored contiguously. `&[T]` consequently consists of a `(&T, usize)` pair that specifies -where the slice starts, and how many elements it contains. Similarly, Trait Objects -support interface-oriented type erasure through a `(data_ptr, vtable_ptr)` pair. +For instance, the slice type, `[T]`, is some statically unknown number of +elements stored contiguously. `&[T]` consequently consists of a `(&T, usize)` +pair that specifies where the slice starts, and how many elements it contains. +Similarly, Trait Objects support interface-oriented type erasure through a +`(data_ptr, vtable_ptr)` pair. Structs can actually store a single DST directly as their last field, but this makes them a DST as well: @@ -50,38 +51,39 @@ struct Foo; // No fields = no size // All fields have no size = no size struct Baz { foo: Foo, - qux: (), // empty tuple has no size + qux: (), // empty tuple has no size baz: [u8; 0], // empty array has no size } ``` -On their own, ZSTs are, for obvious reasons, pretty useless. However -as with many curious layout choices in Rust, their potential is realized in a generic +On their own, ZSTs are, for obvious reasons, pretty useless. However as with +many curious layout choices in Rust, their potential is realized in a generic context. -Rust largely understands that any operation that produces or stores a ZST -can be reduced to a no-op. For instance, a `HashSet` can be effeciently implemented -as a thin wrapper around `HashMap` because all the operations `HashMap` normally -does to store and retrieve keys will be completely stripped in monomorphization. +Rust largely understands that any operation that produces or stores a ZST can be +reduced to a no-op. For instance, a `HashSet` can be effeciently implemented +as a thin wrapper around `HashMap` because all the operations `HashMap` +normally does to store and retrieve keys will be completely stripped in +monomorphization. Similarly `Result<(), ()>` and `Option<()>` are effectively just fancy `bool`s. Safe code need not worry about ZSTs, but *unsafe* code must be careful about the -consequence of types with no size. In particular, pointer offsets are no-ops, and -standard allocators (including jemalloc, the one used by Rust) generally consider -passing in `0` as Undefined Behaviour. +consequence of types with no size. In particular, pointer offsets are no-ops, +and standard allocators (including jemalloc, the one used by Rust) generally +consider passing in `0` as Undefined Behaviour. -# Void Types +# Empty Types Rust also enables types to be declared that *cannot even be instantiated*. These types can only be talked about at the type level, and never at the value level. ```rust -enum Foo { } // No variants = VOID +enum Foo { } // No variants = EMPTY ``` -TODO: WHY?! \ No newline at end of file +TODO: WHY?! diff --git a/src/doc/tarpl/leaking.md b/src/doc/tarpl/leaking.md index 5d66b1a424c4..1e1e95a243dd 100644 --- a/src/doc/tarpl/leaking.md +++ b/src/doc/tarpl/leaking.md @@ -1,46 +1,46 @@ % Leaking -Ownership based resource management is intended to simplify composition. You -acquire resources when you create the object, and you release the resources -when it gets destroyed. Since destruction is handled for you, it means you -can't forget to release the resources, and it happens as soon as possible! -Surely this is perfect and all of our problems are solved. +Ownership-based resource management is intended to simplify composition. You +acquire resources when you create the object, and you release the resources when +it gets destroyed. Since destruction is handled for you, it means you can't +forget to release the resources, and it happens as soon as possible! Surely this +is perfect and all of our problems are solved. Everything is terrible and we have new and exotic problems to try to solve. -Many people like to believe that Rust eliminates resource leaks, but this -is absolutely not the case, no matter how you look at it. In the strictest -sense, "leaking" is so abstract as to be unpreventable. It's quite trivial -to initialize a collection at the start of a program, fill it with tons of -objects with destructors, and then enter an infinite event loop that never -refers to it. The collection will sit around uselessly, holding on to its -precious resources until the program terminates (at which point all those -resources would have been reclaimed by the OS anyway). +Many people like to believe that Rust eliminates resource leaks, but this is +absolutely not the case, no matter how you look at it. In the strictest sense, +"leaking" is so abstract as to be unpreventable. It's quite trivial to +initialize a collection at the start of a program, fill it with tons of objects +with destructors, and then enter an infinite event loop that never refers to it. +The collection will sit around uselessly, holding on to its precious resources +until the program terminates (at which point all those resources would have been +reclaimed by the OS anyway). -We may consider a more restricted form of leak: failing to drop a value that -is unreachable. Rust also doesn't prevent this. In fact Rust has a *function -for doing this*: `mem::forget`. This function consumes the value it is passed -*and then doesn't run its destructor*. +We may consider a more restricted form of leak: failing to drop a value that is +unreachable. Rust also doesn't prevent this. In fact Rust has a *function for +doing this*: `mem::forget`. This function consumes the value it is passed *and +then doesn't run its destructor*. In the past `mem::forget` was marked as unsafe as a sort of lint against using it, since failing to call a destructor is generally not a well-behaved thing to do (though useful for some special unsafe code). However this was generally determined to be an untenable stance to take: there are *many* ways to fail to -call a destructor in safe code. The most famous example is creating a cycle -of reference counted pointers using interior mutability. +call a destructor in safe code. The most famous example is creating a cycle of +reference-counted pointers using interior mutability. -It is reasonable for safe code to assume that destructor leaks do not happen, -as any program that leaks destructors is probably wrong. However *unsafe* code +It is reasonable for safe code to assume that destructor leaks do not happen, as +any program that leaks destructors is probably wrong. However *unsafe* code cannot rely on destructors to be run to be *safe*. For most types this doesn't -matter: if you leak the destructor then the type is *by definition* inaccessible, -so it doesn't matter, right? For instance, if you leak a `Box` then you -waste some memory but that's hardly going to violate memory-safety. +matter: if you leak the destructor then the type is *by definition* +inaccessible, so it doesn't matter, right? For instance, if you leak a `Box` +then you waste some memory but that's hardly going to violate memory-safety. -However where we must be careful with destructor leaks are *proxy* types. -These are types which manage access to a distinct object, but don't actually -own it. Proxy objects are quite rare. Proxy objects you'll need to care about -are even rarer. However we'll focus on three interesting examples in the -standard library: +However where we must be careful with destructor leaks are *proxy* types. These +are types which manage access to a distinct object, but don't actually own it. +Proxy objects are quite rare. Proxy objects you'll need to care about are even +rarer. However we'll focus on three interesting examples in the standard +library: * `vec::Drain` * `Rc` @@ -58,7 +58,8 @@ after claiming ownership over all of its contents. It produces an iterator Now, consider Drain in the middle of iteration: some values have been moved out, and others haven't. This means that part of the Vec is now full of logically uninitialized data! We could backshift all the elements in the Vec every time we -remove a value, but this would have pretty catastrophic performance consequences. +remove a value, but this would have pretty catastrophic performance +consequences. Instead, we would like Drain to *fix* the Vec's backing storage when it is dropped. It should run itself to completion, backshift any elements that weren't @@ -71,35 +72,35 @@ Now consider the following: let mut vec = vec![Box::new(0); 4]; { - // start draining, vec can no longer be accessed - let mut drainer = vec.drain(..); + // start draining, vec can no longer be accessed + let mut drainer = vec.drain(..); - // pull out two elements and immediately drop them - drainer.next(); - drainer.next(); + // pull out two elements and immediately drop them + drainer.next(); + drainer.next(); - // get rid of drainer, but don't call its destructor - mem::forget(drainer); + // get rid of drainer, but don't call its destructor + mem::forget(drainer); } // Oops, vec[0] was dropped, we're reading a pointer into free'd memory! println!("{}", vec[0]); ``` -This is pretty clearly Not Good. Unfortunately, we're kind've stuck between -a rock and a hard place: maintaining consistent state at every step has -an enormous cost (and would negate any benefits of the API). Failing to maintain +This is pretty clearly Not Good. Unfortunately, we're kind've stuck between a +rock and a hard place: maintaining consistent state at every step has an +enormous cost (and would negate any benefits of the API). Failing to maintain consistent state gives us Undefined Behaviour in safe code (making the API unsound). So what can we do? Well, we can pick a trivially consistent state: set the Vec's len to be 0 when we *start* the iteration, and fix it up if necessary in the destructor. That way, if everything executes like normal we get the desired -behaviour with minimal overhead. But if someone has the *audacity* to mem::forget -us in the middle of the iteration, all that does is *leak even more* (and possibly -leave the Vec in an *unexpected* but consistent state). Since we've -accepted that mem::forget is safe, this is definitely safe. We call leaks causing -more leaks a *leak amplification*. +behaviour with minimal overhead. But if someone has the *audacity* to +mem::forget us in the middle of the iteration, all that does is *leak even more* +(and possibly leave the Vec in an *unexpected* but consistent state). Since +we've accepted that mem::forget is safe, this is definitely safe. We call leaks +causing more leaks a *leak amplification*. @@ -108,8 +109,8 @@ more leaks a *leak amplification*. Rc is an interesting case because at first glance it doesn't appear to be a proxy value at all. After all, it manages the data it points to, and dropping -all the Rcs for a value will drop that value. leaking an Rc doesn't seem like -it would be particularly dangerous. It will leave the refcount permanently +all the Rcs for a value will drop that value. Leaking an Rc doesn't seem like it +would be particularly dangerous. It will leave the refcount permanently incremented and prevent the data from being freed or dropped, but that seems just like Box, right? @@ -119,47 +120,47 @@ Let's consider a simplified implementation of Rc: ```rust struct Rc { - ptr: *mut RcBox, + ptr: *mut RcBox, } struct RcBox { - data: T, - ref_count: usize, + data: T, + ref_count: usize, } impl Rc { - fn new(data: T) -> Self { - unsafe { - // Wouldn't it be nice if heap::allocate worked like this? - let ptr = heap::allocate>(); - ptr::write(ptr, RcBox { - data: data, - ref_count: 1, - }); - Rc { ptr: ptr } - } - } + fn new(data: T) -> Self { + unsafe { + // Wouldn't it be nice if heap::allocate worked like this? + let ptr = heap::allocate>(); + ptr::write(ptr, RcBox { + data: data, + ref_count: 1, + }); + Rc { ptr: ptr } + } + } - fn clone(&self) -> Self { - unsafe { - (*self.ptr).ref_count += 1; - } - Rc { ptr: self.ptr } - } + fn clone(&self) -> Self { + unsafe { + (*self.ptr).ref_count += 1; + } + Rc { ptr: self.ptr } + } } impl Drop for Rc { - fn drop(&mut self) { - unsafe { - let inner = &mut ; - (*self.ptr).ref_count -= 1; - if (*self.ptr).ref_count == 0 { - // drop the data and then free it - ptr::read(self.ptr); - heap::deallocate(self.ptr); - } - } - } + fn drop(&mut self) { + unsafe { + let inner = &mut ; + (*self.ptr).ref_count -= 1; + if (*self.ptr).ref_count == 0 { + // drop the data and then free it + ptr::read(self.ptr); + heap::deallocate(self.ptr); + } + } + } } ``` @@ -185,24 +186,24 @@ data on the stack without any synchronization over that data. Usage looked like: ```rust let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; { - let guards = vec![]; - for x in &mut data { - // Move the mutable reference into the closure, and execute - // it on a different thread. The closure has a lifetime bound - // by the lifetime of the mutable reference `x` we store in it. - // The guard that is returned is in turn assigned the lifetime - // of the closure, so it also mutably borrows `data` as `x` did. - // This means we cannot access `data` until the guard goes away. - let guard = thread::scoped(move || { - *x *= 2; - }); - // store the thread's guard for later - guards.push(guard); - } - // All guards are dropped here, forcing the threads to join - // (this thread blocks here until the others terminate). - // Once the threads join, the borrow expires and the data becomes - // accessible again in this thread. + let guards = vec![]; + for x in &mut data { + // Move the mutable reference into the closure, and execute + // it on a different thread. The closure has a lifetime bound + // by the lifetime of the mutable reference `x` we store in it. + // The guard that is returned is in turn assigned the lifetime + // of the closure, so it also mutably borrows `data` as `x` did. + // This means we cannot access `data` until the guard goes away. + let guard = thread::scoped(move || { + *x *= 2; + }); + // store the thread's guard for later + guards.push(guard); + } + // All guards are dropped here, forcing the threads to join + // (this thread blocks here until the others terminate). + // Once the threads join, the borrow expires and the data becomes + // accessible again in this thread. } // data is definitely mutated here. ``` @@ -213,17 +214,17 @@ In principle, this totally works! Rust's ownership system perfectly ensures it! ``` let mut data = Box::new(0); { - let guard = thread::scoped(|| { - // This is at best a data race. At worst, it's *also* a use-after-free. - *data += 1; - }); - // Because the guard is forgotten, expiring the loan without blocking this - // thread. - mem::forget(guard); + let guard = thread::scoped(|| { + // This is at best a data race. At worst, it's *also* a use-after-free. + *data += 1; + }); + // Because the guard is forgotten, expiring the loan without blocking this + // thread. + mem::forget(guard); } // So the Box is dropped here while the scoped thread may or may not be trying // to access it. ``` Dang. Here the destructor running was pretty fundamental to the API, and it had -to be scrapped in favour of a completely different design. \ No newline at end of file +to be scrapped in favour of a completely different design. diff --git a/src/doc/tarpl/other-reprs.md b/src/doc/tarpl/other-reprs.md index 829a15e6355b..d4c6134c5432 100644 --- a/src/doc/tarpl/other-reprs.md +++ b/src/doc/tarpl/other-reprs.md @@ -8,30 +8,31 @@ Rust allows you to specify alternative data layout strategies from the default. # repr(C) This is the most important `repr`. It has fairly simple intent: do what C does. -The order, size, and alignment of fields is exactly what you would expect from -C or C++. Any type you expect to pass through an FFI boundary should have `repr(C)`, -as C is the lingua-franca of the programming world. This is also necessary -to soundly do more elaborate tricks with data layout such as reintepretting values -as a different type. +The order, size, and alignment of fields is exactly what you would expect from C +or C++. Any type you expect to pass through an FFI boundary should have +`repr(C)`, as C is the lingua-franca of the programming world. This is also +necessary to soundly do more elaborate tricks with data layout such as +reintepretting values as a different type. -However, the interaction with Rust's more exotic data layout features must be kept -in mind. Due to its dual purpose as "for FFI" and "for layout control", `repr(C)` -can be applied to types that will be nonsensical or problematic if passed through -the FFI boundary. +However, the interaction with Rust's more exotic data layout features must be +kept in mind. Due to its dual purpose as "for FFI" and "for layout control", +`repr(C)` can be applied to types that will be nonsensical or problematic if +passed through the FFI boundary. -* ZSTs are still zero-sized, even though this is not a standard behaviour - in C, and is explicitly contrary to the behaviour of an empty type in C++, which - still consumes a byte of space. +* ZSTs are still zero-sized, even though this is not a standard behaviour in +C, and is explicitly contrary to the behaviour of an empty type in C++, which +still consumes a byte of space. * DSTs, tuples, and tagged unions are not a concept in C and as such are never - FFI safe. +FFI safe. * **The [drop flag][] will still be added** * This is equivalent to one of `repr(u*)` (see the next section) for enums. The - chosen size is the default enum size for the target platform's C ABI. Note that - enum representation in C is undefined, and this may be incorrect when the C - code is compiled with certain flags. +chosen size is the default enum size for the target platform's C ABI. Note that +enum representation in C is implementation defined, so this is really a "best +guess". In particular, this may be incorrect when the C code of interest is +compiled with certain flags. @@ -40,10 +41,11 @@ the FFI boundary. These specify the size to make a C-like enum. If the discriminant overflows the integer it has to fit in, it will be an error. You can manually ask Rust to allow this by setting the overflowing element to explicitly be 0. However Rust -will not allow you to create an enum where two variants have the same discriminant. +will not allow you to create an enum where two variants have the same +discriminant. -On non-C-like enums, this will inhibit certain optimizations like the null-pointer -optimization. +On non-C-like enums, this will inhibit certain optimizations like the null- +pointer optimization. These reprs have no affect on a struct. @@ -53,15 +55,15 @@ These reprs have no affect on a struct. # repr(packed) `repr(packed)` forces rust to strip any padding, and only align the type to a -byte. This may improve the memory footprint, but will likely have other -negative side-effects. +byte. This may improve the memory footprint, but will likely have other negative +side-effects. In particular, most architectures *strongly* prefer values to be aligned. This -may mean the unaligned loads are penalized (x86), or even fault (some ARM chips). -For simple cases like directly loading or storing a packed field, the compiler -might be able to paper over alignment issues with shifts and masks. However if -you take a reference to a packed field, it's unlikely that the compiler will be -able to emit code to avoid an unaligned load. +may mean the unaligned loads are penalized (x86), or even fault (some ARM +chips). For simple cases like directly loading or storing a packed field, the +compiler might be able to paper over alignment issues with shifts and masks. +However if you take a reference to a packed field, it's unlikely that the +compiler will be able to emit code to avoid an unaligned load. `repr(packed)` is not to be used lightly. Unless you have extreme requirements, this should not be used. diff --git a/src/doc/tarpl/references.md b/src/doc/tarpl/references.md index 24c6b607840d..993e2a52aebf 100644 --- a/src/doc/tarpl/references.md +++ b/src/doc/tarpl/references.md @@ -2,13 +2,11 @@ There are two kinds of reference: -* Shared reference: `&` -* Mutable reference: `&mut` +* Shared reference: `&` Mutable reference: `&mut` Which obey the following rules: -* A reference cannot outlive its referent -* A mutable reference cannot be aliased +* A reference cannot outlive its referent A mutable reference cannot be aliased To define aliasing, we must define the notion of *paths* and *liveness*. @@ -17,60 +15,66 @@ To define aliasing, we must define the notion of *paths* and *liveness*. # Paths -If all Rust had were values, then every value would be uniquely owned -by a variable or composite structure. From this we naturally derive a *tree* -of ownership. The stack itself is the root of the tree, with every variable -as its direct children. Each variable's direct children would be their fields -(if any), and so on. +If all Rust had were values, then every value would be uniquely owned by a +variable or composite structure. From this we naturally derive a *tree* of +ownership. The stack itself is the root of the tree, with every variable as its +direct children. Each variable's direct children would be their fields (if any), +and so on. -From this view, every value in Rust has a unique *path* in the tree of ownership. -References to a value can subsequently be interpreted as a path in this tree. -Of particular interest are *ancestors* and *descendants*: if `x` owns `y`, then -`x` is an *ancestor* of `y`, and `y` is a *descendant* of `x`. Note that this is -an inclusive relationship: `x` is a descendant and ancestor of itself. +From this view, every value in Rust has a unique *path* in the tree of +ownership. References to a value can subsequently be interpreted as a path in +this tree. Of particular interest are *ancestors* and *descendants*: if `x` owns +`y`, then `x` is an *ancestor* of `y`, and `y` is a *descendant* of `x`. Note +that this is an inclusive relationship: `x` is a descendant and ancestor of +itself. -Tragically, plenty of data doesn't reside on the stack, and we must also accommodate this. -Globals and thread-locals are simple enough to model as residing at the bottom -of the stack (though we must be careful with mutable globals). Data on -the heap poses a different problem. +Tragically, plenty of data doesn't reside on the stack, and we must also +accommodate this. Globals and thread-locals are simple enough to model as +residing at the bottom of the stack (though we must be careful with mutable +globals). Data on the heap poses a different problem. If all Rust had on the heap was data uniquely owned by a pointer on the stack, -then we can just treat that pointer as a struct that owns the value on -the heap. Box, Vec, String, and HashMap, are examples of types which uniquely -own data on the heap. +then we can just treat that pointer as a struct that owns the value on the heap. +Box, Vec, String, and HashMap, are examples of types which uniquely own data on +the heap. Unfortunately, data on the heap is not *always* uniquely owned. Rc for instance introduces a notion of *shared* ownership. Shared ownership means there is no -unique path. A value with no unique path limits what we can do with it. In general, only -shared references can be created to these values. However mechanisms which ensure -mutual exclusion may establish One True Owner temporarily, establishing a unique path -to that value (and therefore all its children). +unique path. A value with no unique path limits what we can do with it. In +general, only shared references can be created to these values. However +mechanisms which ensure mutual exclusion may establish One True Owner +temporarily, establishing a unique path to that value (and therefore all its +children). The most common way to establish such a path is through *interior mutability*, in contrast to the *inherited mutability* that everything in Rust normally uses. -Cell, RefCell, Mutex, and RWLock are all examples of interior mutability types. These -types provide exclusive access through runtime restrictions. However it is also -possible to establish unique ownership without interior mutability. For instance, -if an Rc has refcount 1, then it is safe to mutate or move its internals. +Cell, RefCell, Mutex, and RWLock are all examples of interior mutability types. +These types provide exclusive access through runtime restrictions. However it is +also possible to establish unique ownership without interior mutability. For +instance, if an Rc has refcount 1, then it is safe to mutate or move its +internals. In order to correctly communicate to the type system that a variable or field of a struct can have interior mutability, it must be wrapped in an UnsafeCell. This -does not in itself make it safe to perform interior mutability operations on that -value. You still must yourself ensure that mutual exclusion is upheld. +does not in itself make it safe to perform interior mutability operations on +that value. You still must yourself ensure that mutual exclusion is upheld. # Liveness +Note: Liveness is not the same thing as a *lifetime*, which will be explained +in detail in the next section of this chapter. + Roughly, a reference is *live* at some point in a program if it can be -dereferenced. Shared references are always live unless they are literally unreachable -(for instance, they reside in freed or leaked memory). Mutable references can be -reachable but *not* live through the process of *reborrowing*. +dereferenced. Shared references are always live unless they are literally +unreachable (for instance, they reside in freed or leaked memory). Mutable +references can be reachable but *not* live through the process of *reborrowing*. A mutable reference can be reborrowed to either a shared or mutable reference to one of its descendants. A reborrowed reference will only be live again once all -reborrows derived from it expire. For instance, a mutable reference can be reborrowed -to point to a field of its referent: +reborrows derived from it expire. For instance, a mutable reference can be +reborrowed to point to a field of its referent: ```rust let x = &mut (1, 2); @@ -110,18 +114,18 @@ to make such a borrow*, just that Rust isn't as smart as you want. To simplify things, we can model variables as a fake type of reference: *owned* references. Owned references have much the same semantics as mutable references: -they can be re-borrowed in a mutable or shared manner, which makes them no longer -live. Live owned references have the unique property that they can be moved -out of (though mutable references *can* be swapped out of). This power is +they can be re-borrowed in a mutable or shared manner, which makes them no +longer live. Live owned references have the unique property that they can be +moved out of (though mutable references *can* be swapped out of). This power is only given to *live* owned references because moving its referent would of course invalidate all outstanding references prematurely. As a local lint against inappropriate mutation, only variables that are marked as `mut` can be borrowed mutably. -It is interesting to note that Box behaves exactly like an owned -reference. It can be moved out of, and Rust understands it sufficiently to -reason about its paths like a normal variable. +It is interesting to note that Box behaves exactly like an owned reference. It +can be moved out of, and Rust understands it sufficiently to reason about its +paths like a normal variable. @@ -130,21 +134,21 @@ reason about its paths like a normal variable. With liveness and paths defined, we can now properly define *aliasing*: -**A mutable reference is aliased if there exists another live reference to one of -its ancestors or descendants.** +**A mutable reference is aliased if there exists another live reference to one +of its ancestors or descendants.** (If you prefer, you may also say the two live references alias *each other*. This has no semantic consequences, but is probably a more useful notion when verifying the soundness of a construct.) -That's it. Super simple right? Except for the fact that it took us two pages -to define all of the terms in that definition. You know: Super. Simple. +That's it. Super simple right? Except for the fact that it took us two pages to +define all of the terms in that definition. You know: Super. Simple. -Actually it's a bit more complicated than that. In addition to references, -Rust has *raw pointers*: `*const T` and `*mut T`. Raw pointers have no inherent -ownership or aliasing semantics. As a result, Rust makes absolutely no effort -to track that they are used correctly, and they are wildly unsafe. +Actually it's a bit more complicated than that. In addition to references, Rust +has *raw pointers*: `*const T` and `*mut T`. Raw pointers have no inherent +ownership or aliasing semantics. As a result, Rust makes absolutely no effort to +track that they are used correctly, and they are wildly unsafe. **It is an open question to what degree raw pointers have alias semantics. -However it is important for these definitions to be sound that the existence -of a raw pointer does not imply some kind of live path.** +However it is important for these definitions to be sound that the existence of +a raw pointer does not imply some kind of live path.** diff --git a/src/doc/tarpl/send-and-sync.md b/src/doc/tarpl/send-and-sync.md index 0ac14a85f847..6045d3d0378a 100644 --- a/src/doc/tarpl/send-and-sync.md +++ b/src/doc/tarpl/send-and-sync.md @@ -1,38 +1,40 @@ % Send and Sync -Not everything obeys inherited mutability, though. Some types allow you to multiply -alias a location in memory while mutating it. Unless these types use synchronization -to manage this access, they are absolutely not thread safe. Rust captures this with -through the `Send` and `Sync` traits. +Not everything obeys inherited mutability, though. Some types allow you to +multiply alias a location in memory while mutating it. Unless these types use +synchronization to manage this access, they are absolutely not thread safe. Rust +captures this with through the `Send` and `Sync` traits. -* A type is Send if it is safe to send it to another thread. -* A type is Sync if it is safe to share between threads (`&T` is Send). +* A type is Send if it is safe to send it to another thread. A type is Sync if +* it is safe to share between threads (`&T` is Send). Send and Sync are *very* fundamental to Rust's concurrency story. As such, a substantial amount of special tooling exists to make them work right. First and -foremost, they're *unsafe traits*. This means that they are unsafe *to implement*, -and other unsafe code can *trust* that they are correctly implemented. Since -they're *marker traits* (they have no associated items like methods), correctly -implemented simply means that they have the intrinsic properties an implementor -should have. Incorrectly implementing Send or Sync can cause Undefined Behaviour. +foremost, they're *unsafe traits*. This means that they are unsafe *to +implement*, and other unsafe code can *trust* that they are correctly +implemented. Since they're *marker traits* (they have no associated items like +methods), correctly implemented simply means that they have the intrinsic +properties an implementor should have. Incorrectly implementing Send or Sync can +cause Undefined Behaviour. -Send and Sync are also what Rust calls *opt-in builtin traits*. -This means that, unlike every other trait, they are *automatically* derived: -if a type is composed entirely of Send or Sync types, then it is Send or Sync. -Almost all primitives are Send and Sync, and as a consequence pretty much -all types you'll ever interact with are Send and Sync. +Send and Sync are also what Rust calls *opt-in builtin traits*. This means that, +unlike every other trait, they are *automatically* derived: if a type is +composed entirely of Send or Sync types, then it is Send or Sync. Almost all +primitives are Send and Sync, and as a consequence pretty much all types you'll +ever interact with are Send and Sync. Major exceptions include: * raw pointers are neither Send nor Sync (because they have no safety guards) -* `UnsafeCell` isn't Sync (and therefore `Cell` and `RefCell` aren't) -* `Rc` isn't Send or Sync (because the refcount is shared and unsynchronized) +* `UnsafeCell` isn't Sync (and therefore `Cell` and `RefCell` aren't) `Rc` isn't +* Send or Sync (because the refcount is shared and unsynchronized) `Rc` and `UnsafeCell` are very fundamentally not thread-safe: they enable -unsynchronized shared mutable state. However raw pointers are, strictly speaking, -marked as thread-unsafe as more of a *lint*. Doing anything useful +unsynchronized shared mutable state. However raw pointers are, strictly +speaking, marked as thread-unsafe as more of a *lint*. Doing anything useful with a raw pointer requires dereferencing it, which is already unsafe. In that -sense, one could argue that it would be "fine" for them to be marked as thread safe. +sense, one could argue that it would be "fine" for them to be marked as thread +safe. However it's important that they aren't thread safe to prevent types that *contain them* from being automatically marked as thread safe. These types have @@ -60,17 +62,16 @@ impl !Send for SpecialThreadToken {} impl !Sync for SpecialThreadToken {} ``` -Note that *in and of itself* it is impossible to incorrectly derive Send and Sync. -Only types that are ascribed special meaning by other unsafe code can possible cause -trouble by being incorrectly Send or Sync. +Note that *in and of itself* it is impossible to incorrectly derive Send and +Sync. Only types that are ascribed special meaning by other unsafe code can +possible cause trouble by being incorrectly Send or Sync. Most uses of raw pointers should be encapsulated behind a sufficient abstraction that Send and Sync can be derived. For instance all of Rust's standard -collections are Send and Sync (when they contain Send and Sync types) -in spite of their pervasive use raw pointers to -manage allocations and complex ownership. Similarly, most iterators into these -collections are Send and Sync because they largely behave like an `&` or `&mut` -into the collection. +collections are Send and Sync (when they contain Send and Sync types) in spite +of their pervasive use raw pointers to manage allocations and complex ownership. +Similarly, most iterators into these collections are Send and Sync because they +largely behave like an `&` or `&mut` into the collection. TODO: better explain what can or can't be Send or Sync. Sufficient to appeal -only to data races? \ No newline at end of file +only to data races? From 7aee8448ea461a598075065491e98f941a570fea Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 14 Jul 2015 11:07:00 -0700 Subject: [PATCH 073/104] fix all the doc tests --- src/doc/tarpl/checked-uninit.md | 4 +- src/doc/tarpl/coercions.md | 2 +- src/doc/tarpl/destructors.md | 61 +++++++++++++++++++++------- src/doc/tarpl/drop-flags.md | 3 ++ src/doc/tarpl/exception-safety.md | 2 +- src/doc/tarpl/hrtb.md | 6 +-- src/doc/tarpl/leaking.md | 8 ++-- src/doc/tarpl/lifetime-elision.md | 6 +-- src/doc/tarpl/lifetime-misc.md | 18 ++++---- src/doc/tarpl/lifetimes.md | 12 +++--- src/doc/tarpl/ownership.md | 4 +- src/doc/tarpl/repr-rust.md | 2 +- src/doc/tarpl/send-and-sync.md | 2 + src/doc/tarpl/subtyping.md | 22 +++++----- src/doc/tarpl/unbounded-lifetimes.md | 2 +- src/doc/tarpl/unchecked-uninit.md | 33 ++++++++------- src/doc/tarpl/vec-alloc.md | 4 +- src/doc/tarpl/vec-dealloc.md | 4 +- src/doc/tarpl/vec-deref.md | 4 +- src/doc/tarpl/vec-drain.md | 16 ++++---- src/doc/tarpl/vec-final.md | 8 ++-- src/doc/tarpl/vec-insert-remove.md | 6 +-- src/doc/tarpl/vec-into-iter.md | 26 ++++++------ src/doc/tarpl/vec-layout.md | 6 ++- src/doc/tarpl/vec-push-pop.md | 6 +-- src/doc/tarpl/working-with-unsafe.md | 24 +++++++---- 26 files changed, 173 insertions(+), 118 deletions(-) diff --git a/src/doc/tarpl/checked-uninit.md b/src/doc/tarpl/checked-uninit.md index 667afe012d55..65bffd7d09fe 100644 --- a/src/doc/tarpl/checked-uninit.md +++ b/src/doc/tarpl/checked-uninit.md @@ -4,7 +4,7 @@ Like C, all stack variables in Rust are uninitialized until a value is explicitly assigned to them. Unlike C, Rust statically prevents you from ever reading them until you do: -```rust +```rust,ignore fn main() { let x: i32; println!("{}", x); @@ -39,7 +39,7 @@ fn main() { but this doesn't: -```rust +```rust,ignore fn main() { let x: i32; if true { diff --git a/src/doc/tarpl/coercions.md b/src/doc/tarpl/coercions.md index fad9b09c3c38..df0fdfa57ca1 100644 --- a/src/doc/tarpl/coercions.md +++ b/src/doc/tarpl/coercions.md @@ -51,7 +51,7 @@ receivers, see below). If there is an impl for some type `U` and `T` coerces to following will not type check, even though it is OK to coerce `t` to `&T` and there is an impl for `&T`: -```rust +```rust,ignore trait Trait {} fn foo(t: X) {} diff --git a/src/doc/tarpl/destructors.md b/src/doc/tarpl/destructors.md index cf6378c3e25a..e146ae4a1dac 100644 --- a/src/doc/tarpl/destructors.md +++ b/src/doc/tarpl/destructors.md @@ -3,7 +3,7 @@ What the language *does* provide is full-blown automatic destructors through the `Drop` trait, which provides the following method: -```rust +```rust,ignore fn drop(&mut self); ``` @@ -23,13 +23,22 @@ this is totally fine. For instance, a custom implementation of `Box` might write `Drop` like this: ```rust -struct Box{ ptr: *mut T } +#![feature(heap_api, core_intrinsics, unique)] + +use std::rt::heap; +use std::ptr::Unique; +use std::intrinsics::drop_in_place; +use std::mem; + +struct Box{ ptr: Unique } impl Drop for Box { fn drop(&mut self) { unsafe { - (*self.ptr).drop(); - heap::deallocate(self.ptr); + drop_in_place(*self.ptr); + heap::deallocate((*self.ptr) as *mut u8, + mem::size_of::(), + mem::align_of::()); } } } @@ -42,25 +51,36 @@ after-free the `ptr` because the Box is immediately marked as uninitialized. However this wouldn't work: ```rust -struct Box{ ptr: *mut T } +#![feature(heap_api, core_intrinsics, unique)] + +use std::rt::heap; +use std::ptr::Unique; +use std::intrinsics::drop_in_place; +use std::mem; + +struct Box{ ptr: Unique } impl Drop for Box { fn drop(&mut self) { unsafe { - (*self.ptr).drop(); - heap::deallocate(self.ptr); + drop_in_place(*self.ptr); + heap::deallocate((*self.ptr) as *mut u8, + mem::size_of::(), + mem::align_of::()); } } } -struct SuperBox { box: Box } +struct SuperBox { my_box: Box } impl Drop for SuperBox { fn drop(&mut self) { unsafe { // Hyper-optimized: deallocate the box's contents for it // without `drop`ing the contents - heap::deallocate(self.box.ptr); + heap::deallocate((*self.my_box.ptr) as *mut u8, + mem::size_of::(), + mem::align_of::()); } } } @@ -106,18 +126,27 @@ The classic safe solution to overriding recursive drop and allowing moving out of Self during `drop` is to use an Option: ```rust -struct Box{ ptr: *mut T } +#![feature(heap_api, core_intrinsics, unique)] + +use std::rt::heap; +use std::ptr::Unique; +use std::intrinsics::drop_in_place; +use std::mem; + +struct Box{ ptr: Unique } impl Drop for Box { fn drop(&mut self) { unsafe { - (*self.ptr).drop(); - heap::deallocate(self.ptr); + drop_in_place(*self.ptr); + heap::deallocate((*self.ptr) as *mut u8, + mem::size_of::(), + mem::align_of::()); } } } -struct SuperBox { box: Option> } +struct SuperBox { my_box: Option> } impl Drop for SuperBox { fn drop(&mut self) { @@ -125,7 +154,11 @@ impl Drop for SuperBox { // Hyper-optimized: deallocate the box's contents for it // without `drop`ing the contents. Need to set the `box` // field as `None` to prevent Rust from trying to Drop it. - heap::deallocate(self.box.take().unwrap().ptr); + let my_box = self.my_box.take().unwrap(); + heap::deallocate((*my_box.ptr) as *mut u8, + mem::size_of::(), + mem::align_of::()); + mem::forget(my_box); } } } diff --git a/src/doc/tarpl/drop-flags.md b/src/doc/tarpl/drop-flags.md index 68f7ffc77b00..e8c331cd0565 100644 --- a/src/doc/tarpl/drop-flags.md +++ b/src/doc/tarpl/drop-flags.md @@ -31,6 +31,7 @@ And even branched code where all branches have the same behaviour with respect to initialization: ```rust +# let condition = true; let mut x = Box::new(0); // x was uninit; just overwrite. if condition { drop(x) // x gets moved out; make x uninit. @@ -45,6 +46,7 @@ x = Box::new(0); // x was uninit; just overwrite. However code like this *requires* runtime information to correctly Drop: ```rust +# let condition = true; let x; if condition { x = Box::new(0); // x was uninit; just overwrite. @@ -56,6 +58,7 @@ if condition { Of course, in this case it's trivial to retrieve static drop semantics: ```rust +# let condition = true; if condition { let x = Box::new(0); println!("{}", x); diff --git a/src/doc/tarpl/exception-safety.md b/src/doc/tarpl/exception-safety.md index ca3310978112..9a3193409034 100644 --- a/src/doc/tarpl/exception-safety.md +++ b/src/doc/tarpl/exception-safety.md @@ -156,7 +156,7 @@ way to do this is to store the algorithm's state in a separate struct with a destructor for the "finally" logic. Whether we panic or not, that destructor will run and clean up after us. -```rust +```rust,ignore struct Hole<'a, T: 'a> { data: &'a mut [T], /// `elt` is always `Some` from new until drop. diff --git a/src/doc/tarpl/hrtb.md b/src/doc/tarpl/hrtb.md index c3f25026ef48..640742f9b149 100644 --- a/src/doc/tarpl/hrtb.md +++ b/src/doc/tarpl/hrtb.md @@ -28,7 +28,7 @@ fn main() { If we try to naively desugar this code in the same way that we did in the lifetimes section, we run into some trouble: -```rust +```rust,ignore struct Closure { data: (u8, u16), func: F, @@ -60,7 +60,7 @@ we enter the body of `call`! Also, that isn't some fixed lifetime; call works wi This job requires The Magic of Higher-Rank Trait Bounds. The way we desugar this is as follows: -```rust +```rust,ignore where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, ``` @@ -69,4 +69,4 @@ where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, `for<'a>` can be read as "for all choices of `'a`", and basically produces an *inifinite list* of trait bounds that F must satisfy. Intense. There aren't many places outside of the Fn traits where we encounter HRTBs, and even for those we -have a nice magic sugar for the common cases. \ No newline at end of file +have a nice magic sugar for the common cases. diff --git a/src/doc/tarpl/leaking.md b/src/doc/tarpl/leaking.md index 1e1e95a243dd..bb6f7bb4bda0 100644 --- a/src/doc/tarpl/leaking.md +++ b/src/doc/tarpl/leaking.md @@ -68,7 +68,7 @@ unwinding-safe! Easy! Now consider the following: -``` +```rust,ignore let mut vec = vec![Box::new(0); 4]; { @@ -118,7 +118,7 @@ Nope. Let's consider a simplified implementation of Rc: -```rust +```rust,ignore struct Rc { ptr: *mut RcBox, } @@ -183,7 +183,7 @@ in memory. The thread::scoped API intends to allow threads to be spawned that reference data on the stack without any synchronization over that data. Usage looked like: -```rust +```rust,ignore let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; { let guards = vec![]; @@ -211,7 +211,7 @@ let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; In principle, this totally works! Rust's ownership system perfectly ensures it! ...except it relies on a destructor being called to be safe. -``` +```rust,ignore let mut data = Box::new(0); { let guard = thread::scoped(|| { diff --git a/src/doc/tarpl/lifetime-elision.md b/src/doc/tarpl/lifetime-elision.md index eac24330911f..41014f46dd95 100644 --- a/src/doc/tarpl/lifetime-elision.md +++ b/src/doc/tarpl/lifetime-elision.md @@ -5,7 +5,7 @@ In order to make common patterns more ergonomic, Rust allows lifetimes to be A *lifetime position* is anywhere you can write a lifetime in a type: -```rust +```rust,ignore &'a T &'a mut T T<'a> @@ -38,7 +38,7 @@ Elision rules are as follows: Examples: -```rust +```rust,ignore fn print(s: &str); // elided fn print<'a>(s: &'a str); // expanded @@ -61,4 +61,4 @@ fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // exp fn new(buf: &mut [u8]) -> BufWriter; // elided fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded -``` \ No newline at end of file +``` diff --git a/src/doc/tarpl/lifetime-misc.md b/src/doc/tarpl/lifetime-misc.md index faf7f9a1f60b..bd44bb6964af 100644 --- a/src/doc/tarpl/lifetime-misc.md +++ b/src/doc/tarpl/lifetime-misc.md @@ -10,8 +10,8 @@ types or lifetimes are logically associated with a struct, but not actually part of a field. This most commonly occurs with lifetimes. For instance, the `Iter` for `&'a [T]` is (approximately) defined as follows: -```rust -pub struct Iter<'a, T: 'a> { +```rust,ignore +struct Iter<'a, T: 'a> { ptr: *const T, end: *const T, } @@ -33,7 +33,9 @@ Iter logically contains `&'a T`, so this is exactly what we tell the PhantomData to simulate: ``` -pub struct Iter<'a, T: 'a> { +use std::marker; + +struct Iter<'a, T: 'a> { ptr: *const T, end: *const T, _marker: marker::PhantomData<&'a T>, @@ -68,6 +70,8 @@ tell dropck that we *do* own values of type T, and may call destructors of that type, we must add extra PhantomData: ``` +use std::marker; + struct Vec { data: *const T, // *const for covariance! len: usize, @@ -115,7 +119,7 @@ println!("{} {} {} {}", a, b, c, c2); However borrowck doesn't understand arrays or slices in any way, so this doesn't work: -```rust +```rust,ignore let x = [1, 2, 3]; let a = &mut x[0]; let b = &mut x[1]; @@ -144,7 +148,7 @@ left of the index, and one for everything to the right. Intuitively we know this is safe because the slices don't alias. However the implementation requires some unsafety: -```rust +```rust,ignore fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { unsafe { let self2: &mut [T] = mem::transmute_copy(&self); @@ -189,8 +193,8 @@ Whether it's raw pointers, or safely composing on top of *another* IterMut. For instance, VecDeque's IterMut: -```rust -pub struct IterMut<'a, T:'a> { +```rust,ignore +struct IterMut<'a, T:'a> { // The whole backing array. Some of these indices are initialized! ring: &'a mut [T], tail: usize, diff --git a/src/doc/tarpl/lifetimes.md b/src/doc/tarpl/lifetimes.md index a06363a92d73..7282e4d843cf 100644 --- a/src/doc/tarpl/lifetimes.md +++ b/src/doc/tarpl/lifetimes.md @@ -38,7 +38,7 @@ let z = &y; The borrow checker always tries to minimize the extent of a lifetime, so it will likely desugar to the following: -```rust +```rust,ignore // NOTE: `'a: {` and `&'b x` is not valid syntax! 'a: { let x: i32 = 0; @@ -69,8 +69,8 @@ z = y; The borrow checker always tries to minimize the extent of a lifetime, so it will likely desugar to something like the following: -```rust -// NOTE: `'a: {` and `&'b x` is not valid syntax! +```rust,ignore +// NOTE: `'a: {` and `foo = &'b x` is not valid syntax! 'a: { let x: i32 = 0; 'b: { @@ -174,14 +174,14 @@ our implementation *just a bit*.) How about the other example: -```rust +```rust,ignore let mut data = vec![1, 2, 3]; let x = &data[0]; data.push(4); println!("{}", x); ``` -```rust +```rust,ignore 'a: { let mut data: Vec = vec![1, 2, 3]; 'b: { @@ -219,4 +219,4 @@ semantics we're actually interested in preserving. For the most part, *that's totally ok*, because it keeps us from spending all day explaining our program to the compiler. However it does mean that several programs that are *totally* correct with respect to Rust's *true* semantics are rejected because lifetimes -are too dumb. \ No newline at end of file +are too dumb. diff --git a/src/doc/tarpl/ownership.md b/src/doc/tarpl/ownership.md index 9c4f92a4394e..200337a2256e 100644 --- a/src/doc/tarpl/ownership.md +++ b/src/doc/tarpl/ownership.md @@ -16,7 +16,7 @@ issue...). This is a pervasive problem that C and C++ need to deal with. Consider this simple mistake that all of us who have used a non-GC'd language have made at one point: -```rust +```rust,ignore fn as_str(data: &u32) -> &str { // compute the string let s = format!("{}", data); @@ -45,7 +45,7 @@ verifying that references don't escape the scope of their referent. That's because ensuring pointers are always valid is much more complicated than this. For instance in this code, -```rust +```rust,ignore let mut data = vec![1, 2, 3]; // get an internal reference let x = &data[0]; diff --git a/src/doc/tarpl/repr-rust.md b/src/doc/tarpl/repr-rust.md index a1f5f29f8d85..b3a5a1278c78 100644 --- a/src/doc/tarpl/repr-rust.md +++ b/src/doc/tarpl/repr-rust.md @@ -67,7 +67,7 @@ fields in the order specified, we expect it to *pad* the values in the struct to their *alignment* requirements. So if Rust didn't reorder fields, we would expect Rust to produce the following: -```rust +```rust,ignore struct Foo { count: u16, data1: u16, diff --git a/src/doc/tarpl/send-and-sync.md b/src/doc/tarpl/send-and-sync.md index 6045d3d0378a..5b00709a1bf4 100644 --- a/src/doc/tarpl/send-and-sync.md +++ b/src/doc/tarpl/send-and-sync.md @@ -56,6 +56,8 @@ In the *incredibly rare* case that a type is *inappropriately* automatically derived to be Send or Sync, then one can also *unimplement* Send and Sync: ```rust +#![feature(optin_builtin_traits)] + struct SpecialThreadToken(u8); impl !Send for SpecialThreadToken {} diff --git a/src/doc/tarpl/subtyping.md b/src/doc/tarpl/subtyping.md index 24f974ca73ac..e43c365bf4f7 100644 --- a/src/doc/tarpl/subtyping.md +++ b/src/doc/tarpl/subtyping.md @@ -104,7 +104,7 @@ However what should happen when passing *by-value* is less obvious. It turns out that, yes, you can use subtyping when passing by-value. That is, this works: ```rust -fn get_box<'a>(&'a u8) -> Box<&'a str> { +fn get_box<'a>(str: &'a u8) -> Box<&'a str> { // string literals are `&'static str`s Box::new("hello") } @@ -123,7 +123,7 @@ must be invariant to avoid lifetime smuggling. `Fn(T) -> U` should be invariant over T, consider the following function signature: -```rust +```rust,ignore // 'a is derived from some parent scope fn foo(&'a str) -> usize; ``` @@ -131,7 +131,7 @@ fn foo(&'a str) -> usize; This signature claims that it can handle any `&str` that lives *at least* as long as `'a`. Now if this signature was variant with respect to `&str`, that would mean -```rust +```rust,ignore fn foo(&'static str) -> usize; ``` @@ -142,7 +142,7 @@ and nothing else. Therefore functions are not variant over their arguments. To see why `Fn(T) -> U` should be *variant* over U, consider the following function signature: -```rust +```rust,ignore // 'a is derived from some parent scope fn foo(usize) -> &'a str; ``` @@ -150,7 +150,7 @@ fn foo(usize) -> &'a str; This signature claims that it will return something that outlives `'a`. It is therefore completely reasonable to provide -```rust +```rust,ignore fn foo(usize) -> &'static str; ``` @@ -171,15 +171,17 @@ in multiple fields. * Otherwise, Foo is invariant over A ```rust -struct Foo<'a, 'b, A, B, C, D, E, F, G, H> { +use std::cell::Cell; + +struct Foo<'a, 'b, A: 'a, B: 'b, C, D, E, F, G, H> { a: &'a A, // variant over 'a and A b: &'b mut B, // invariant over 'b and B c: *const C, // variant over C d: *mut D, // invariant over D e: Vec, // variant over E f: Cell, // invariant over F - g: G // variant over G - h1: H // would also be variant over H except... - h2: Cell // invariant over H, because invariance wins + g: G, // variant over G + h1: H, // would also be variant over H except... + h2: Cell, // invariant over H, because invariance wins } -``` \ No newline at end of file +``` diff --git a/src/doc/tarpl/unbounded-lifetimes.md b/src/doc/tarpl/unbounded-lifetimes.md index 24caeeb36aaa..b540ab4ed5d9 100644 --- a/src/doc/tarpl/unbounded-lifetimes.md +++ b/src/doc/tarpl/unbounded-lifetimes.md @@ -17,7 +17,7 @@ boundaries. Given a function, any output lifetimes that don't derive from inputs are unbounded. For instance: -```rust +```rust,ignore fn get_str<'a>() -> &'a str; ``` diff --git a/src/doc/tarpl/unchecked-uninit.md b/src/doc/tarpl/unchecked-uninit.md index f5c0fb405993..9ab97b9e2d2d 100644 --- a/src/doc/tarpl/unchecked-uninit.md +++ b/src/doc/tarpl/unchecked-uninit.md @@ -46,27 +46,26 @@ locations of memory can break things are basically uncountable! Putting this all together, we get the following: ```rust -fn main() { - use std::mem; +use std::mem; +use std::ptr; - // size of the array is hard-coded but easy to change. This means we can't - // use [a, b, c] syntax to initialize the array, though! - const SIZE = 10; +// size of the array is hard-coded but easy to change. This means we can't +// use [a, b, c] syntax to initialize the array, though! +const SIZE: usize = 10; - let x: [Box; SIZE]; +let mut x: [Box; SIZE]; - unsafe { - // convince Rust that x is Totally Initialized - x = mem::uninitialized(); - for i in 0..SIZE { - // very carefully overwrite each index without reading it - // NOTE: exception safety is not a concern; Box can't panic - ptr::write(&mut x[i], Box::new(i)); - } +unsafe { + // convince Rust that x is Totally Initialized + x = mem::uninitialized(); + for i in 0..SIZE { + // very carefully overwrite each index without reading it + // NOTE: exception safety is not a concern; Box can't panic + ptr::write(&mut x[i], Box::new(i as u32)); } - - println!("{}", x); } + +println!("{:?}", x); ``` It's worth noting that you don't need to worry about ptr::write-style @@ -83,4 +82,4 @@ before it ends, if has a destructor. And that's about it for working with uninitialized memory! Basically nothing anywhere expects to be handed uninitialized memory, so if you're going to pass -it around at all, be sure to be *really* careful. \ No newline at end of file +it around at all, be sure to be *really* careful. diff --git a/src/doc/tarpl/vec-alloc.md b/src/doc/tarpl/vec-alloc.md index a51f23ca4b8b..e9c9f681ed84 100644 --- a/src/doc/tarpl/vec-alloc.md +++ b/src/doc/tarpl/vec-alloc.md @@ -2,7 +2,7 @@ So: -```rust +```rust,ignore #![feature(heap_api)] use std::rt::heap::EMPTY; @@ -69,7 +69,7 @@ Anything else will use up too much space. However since this is a tutorial, we're not going to be particularly optimal here, and just unconditionally check, rather than use clever platform-specific `cfg`s. -```rust +```rust,ignore fn grow(&mut self) { // this is all pretty delicate, so let's say it's all unsafe unsafe { diff --git a/src/doc/tarpl/vec-dealloc.md b/src/doc/tarpl/vec-dealloc.md index a83d24d7b49c..2ae2477bbacd 100644 --- a/src/doc/tarpl/vec-dealloc.md +++ b/src/doc/tarpl/vec-dealloc.md @@ -11,13 +11,13 @@ We must not call `heap::deallocate` when `self.cap == 0`, as in this case we hav actually allocated any memory. -```rust +```rust,ignore impl Drop for Vec { fn drop(&mut self) { if self.cap != 0 { while let Some(_) = self.pop() { } - let align = mem::min_align_of::(); + let align = mem::align_of::(); let elem_size = mem::size_of::(); let num_bytes = elem_size * self.cap; unsafe { diff --git a/src/doc/tarpl/vec-deref.md b/src/doc/tarpl/vec-deref.md index b07d784939ae..826d763f5bbc 100644 --- a/src/doc/tarpl/vec-deref.md +++ b/src/doc/tarpl/vec-deref.md @@ -9,7 +9,7 @@ conditions. All we need is `slice::from_raw_parts`. -```rust +```rust,ignore use std::ops::Deref; impl Deref for Vec { @@ -24,7 +24,7 @@ impl Deref for Vec { And let's do DerefMut too: -```rust +```rust,ignore use std::ops::DerefMut; impl DerefMut for Vec { diff --git a/src/doc/tarpl/vec-drain.md b/src/doc/tarpl/vec-drain.md index 0a53e8bdfad9..8dd085d6ebcd 100644 --- a/src/doc/tarpl/vec-drain.md +++ b/src/doc/tarpl/vec-drain.md @@ -51,7 +51,7 @@ impl RawValIter { And IntoIter becomes the following: -``` +```rust,ignore pub struct IntoIter { _buf: RawVec, // we don't actually care about this. Just need it to live. iter: RawValIter, @@ -96,7 +96,7 @@ We also take a slice to simplify Drain initialization. Alright, now Drain is really easy: -```rust +```rust,ignore use std::marker::PhantomData; pub struct Drain<'a, T: 'a> { @@ -174,7 +174,7 @@ overflow for zero-sized types. Due to our current architecture, all this means is writing 3 guards, one in each method of RawVec. -```rust +```rust,ignore impl RawVec { fn new() -> Self { unsafe { @@ -194,7 +194,7 @@ impl RawVec { // 0, getting to here necessarily means the Vec is overfull. assert!(elem_size != 0, "capacity overflow"); - let align = mem::min_align_of::(); + let align = mem::align_of::(); let (new_cap, ptr) = if self.cap == 0 { let ptr = heap::allocate(elem_size, align); @@ -223,7 +223,7 @@ impl Drop for RawVec { // don't free zero-sized allocations, as they were never allocated. if self.cap != 0 && elem_size != 0 { - let align = mem::min_align_of::(); + let align = mem::align_of::(); let num_bytes = elem_size * self.cap; unsafe { @@ -247,7 +247,7 @@ initialize `start` and `end` as the same value, and our iterators will yield nothing. The current solution to this is to cast the pointers to integers, increment, and then cast them back: -``` +```rust,ignore impl RawValIter { unsafe fn new(slice: &[T]) -> Self { RawValIter { @@ -270,7 +270,7 @@ Also, our size_hint computation code will divide by 0 for ZSTs. Since we'll basically be treating the two pointers as if they point to bytes, we'll just map size 0 to divide by 1. -``` +```rust,ignore impl Iterator for RawValIter { type Item = T; fn next(&mut self) -> Option { @@ -315,4 +315,4 @@ impl DoubleEndedIterator for RawValIter { } ``` -And that's it. Iteration works! \ No newline at end of file +And that's it. Iteration works! diff --git a/src/doc/tarpl/vec-final.md b/src/doc/tarpl/vec-final.md index 96fcf6d47103..847957e2ea97 100644 --- a/src/doc/tarpl/vec-final.md +++ b/src/doc/tarpl/vec-final.md @@ -38,7 +38,7 @@ impl RawVec { // 0, getting to here necessarily means the Vec is overfull. assert!(elem_size != 0, "capacity overflow"); - let align = mem::min_align_of::(); + let align = mem::align_of::(); let (new_cap, ptr) = if self.cap == 0 { let ptr = heap::allocate(elem_size, align); @@ -65,7 +65,7 @@ impl Drop for RawVec { fn drop(&mut self) { let elem_size = mem::size_of::(); if self.cap != 0 && elem_size != 0 { - let align = mem::min_align_of::(); + let align = mem::align_of::(); let num_bytes = elem_size * self.cap; unsafe { @@ -306,4 +306,6 @@ impl<'a, T> Drop for Drain<'a, T> { fn oom() { ::std::process::exit(-9999); } -``` \ No newline at end of file + +# fn main() {} +``` diff --git a/src/doc/tarpl/vec-insert-remove.md b/src/doc/tarpl/vec-insert-remove.md index 42d114c4a449..f21ed227d84c 100644 --- a/src/doc/tarpl/vec-insert-remove.md +++ b/src/doc/tarpl/vec-insert-remove.md @@ -11,7 +11,7 @@ here). If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]` using the *old* len. -```rust +```rust,ignore pub fn insert(&mut self, index: usize, elem: T) { // Note: `<=` because it's valid to insert after everything // which would be equivalent to push. @@ -34,7 +34,7 @@ pub fn insert(&mut self, index: usize, elem: T) { Remove behaves in the opposite manner. We need to shift all the elements from `[i+1 .. len + 1]` to `[i .. len]` using the *new* len. -```rust +```rust,ignore pub fn remove(&mut self, index: usize) -> T { // Note: `<` because it's *not* valid to remove after everything assert!(index < self.len, "index out of bounds"); @@ -47,4 +47,4 @@ pub fn remove(&mut self, index: usize) -> T { result } } -``` \ No newline at end of file +``` diff --git a/src/doc/tarpl/vec-into-iter.md b/src/doc/tarpl/vec-into-iter.md index b7e7d2bdc42d..d21cf940fcc1 100644 --- a/src/doc/tarpl/vec-into-iter.md +++ b/src/doc/tarpl/vec-into-iter.md @@ -37,7 +37,7 @@ indistinguishable from the case where there are no more elements to yield. So we're going to use the following struct: -```rust +```rust,ignore struct IntoIter { buf: Unique, cap: usize, @@ -63,7 +63,7 @@ cap or len being 0 to not do the offset. So this is what we end up with for initialization: -```rust +```rust,ignore impl Vec { fn into_iter(self) -> IntoIter { // Can't destructure Vec since it's Drop @@ -93,7 +93,7 @@ impl Vec { Here's iterating forward: -```rust +```rust,ignore impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { @@ -118,7 +118,7 @@ impl Iterator for IntoIter { And here's iterating backwards. -```rust +```rust,ignore impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { if self.start == self.end { @@ -138,14 +138,14 @@ to free it. However it *also* wants to implement Drop to drop any elements it contains that weren't yielded. -```rust +```rust,ignore impl Drop for IntoIter { fn drop(&mut self) { if self.cap != 0 { // drop any remaining elements for _ in &mut *self {} - let align = mem::min_align_of::(); + let align = mem::align_of::(); let elem_size = mem::size_of::(); let num_bytes = elem_size * self.cap; unsafe { @@ -164,7 +164,7 @@ compression. We're going to abstract out the `(ptr, cap)` pair and give them the logic for allocating, growing, and freeing: -```rust +```rust,ignore struct RawVec { ptr: Unique, @@ -182,7 +182,7 @@ impl RawVec { // unchanged from Vec fn grow(&mut self) { unsafe { - let align = mem::min_align_of::(); + let align = mem::align_of::(); let elem_size = mem::size_of::(); let (new_cap, ptr) = if self.cap == 0 { @@ -210,7 +210,7 @@ impl RawVec { impl Drop for RawVec { fn drop(&mut self) { if self.cap != 0 { - let align = mem::min_align_of::(); + let align = mem::align_of::(); let elem_size = mem::size_of::(); let num_bytes = elem_size * self.cap; unsafe { @@ -223,7 +223,7 @@ impl Drop for RawVec { And change vec as follows: -```rust +```rust,ignore pub struct Vec { buf: RawVec, len: usize, @@ -254,14 +254,14 @@ impl Drop for Vec { And finally we can really simplify IntoIter: -```rust +```rust,ignore struct IntoIter { _buf: RawVec, // we don't actually care about this. Just need it to live. start: *const T, end: *const T, } -// next and next_back litterally unchanged since they never referred to the buf +// next and next_back literally unchanged since they never referred to the buf impl Drop for IntoIter { fn drop(&mut self) { @@ -290,4 +290,4 @@ impl Vec { } ``` -Much better. \ No newline at end of file +Much better. diff --git a/src/doc/tarpl/vec-layout.md b/src/doc/tarpl/vec-layout.md index 0f85e4d27cef..128ad15f7950 100644 --- a/src/doc/tarpl/vec-layout.md +++ b/src/doc/tarpl/vec-layout.md @@ -4,11 +4,13 @@ First off, we need to come up with the struct layout. Naively we want this design: ```rust -struct Vec { +pub struct Vec { ptr: *mut T, cap: usize, len: usize, } + +# fn main() {} ``` And indeed this would compile. Unfortunately, it would be incorrect. The compiler @@ -32,6 +34,8 @@ pub struct Vec { cap: usize, len: usize, } + +# fn main() {} ``` As a recap, Unique is a wrapper around a raw pointer that declares that: diff --git a/src/doc/tarpl/vec-push-pop.md b/src/doc/tarpl/vec-push-pop.md index d1584a234210..2ef15e324b6e 100644 --- a/src/doc/tarpl/vec-push-pop.md +++ b/src/doc/tarpl/vec-push-pop.md @@ -17,7 +17,7 @@ target address with the bits of the value we provide. No evaluation involved. For `push`, if the old len (before push was called) is 0, then we want to write to the 0th index. So we should offset by the old len. -```rust +```rust,ignore pub fn push(&mut self, elem: T) { if self.len == self.cap { self.grow(); } @@ -41,7 +41,7 @@ of T there. For `pop`, if the old len is 1, we want to read out of the 0th index. So we should offset by the *new* len. -```rust +```rust,ignore pub fn pop(&mut self) -> Option { if self.len == 0 { None @@ -52,4 +52,4 @@ pub fn pop(&mut self) -> Option { } } } -``` \ No newline at end of file +``` diff --git a/src/doc/tarpl/working-with-unsafe.md b/src/doc/tarpl/working-with-unsafe.md index 69d0b31cf88d..0aeb2c0dc258 100644 --- a/src/doc/tarpl/working-with-unsafe.md +++ b/src/doc/tarpl/working-with-unsafe.md @@ -5,7 +5,7 @@ binary manner. Unfortunately, reality is significantly more complicated than tha For instance, consider the following toy function: ```rust -pub fn index(idx: usize, arr: &[u8]) -> Option { +fn index(idx: usize, arr: &[u8]) -> Option { if idx < arr.len() { unsafe { Some(*arr.get_unchecked(idx)) @@ -22,7 +22,7 @@ function, the scope of the unsafe block is questionable. Consider changing the `<` to a `<=`: ```rust -pub fn index(idx: usize, arr: &[u8]) -> Option { +fn index(idx: usize, arr: &[u8]) -> Option { if idx <= arr.len() { unsafe { Some(*arr.get_unchecked(idx)) @@ -44,7 +44,9 @@ Trickier than that is when we get into actual statefulness. Consider a simple implementation of `Vec`: ```rust -// Note this definition is insufficient. See the section on lifetimes. +use std::ptr; + +// Note this definition is insufficient. See the section on implementing Vec. pub struct Vec { ptr: *mut T, len: usize, @@ -61,21 +63,25 @@ impl Vec { self.reallocate(); } unsafe { - ptr::write(self.ptr.offset(len as isize), elem); + ptr::write(self.ptr.offset(self.len as isize), elem); self.len += 1; } } + + # fn reallocate(&mut self) { } } + +# fn main() {} ``` This code is simple enough to reasonably audit and verify. Now consider adding the following method: -```rust - fn make_room(&mut self) { - // grow the capacity - self.cap += 1; - } +```rust,ignore +fn make_room(&mut self) { + // grow the capacity + self.cap += 1; +} ``` This code is safe, but it is also completely unsound. Changing the capacity From 700895fdd7fcd19ffc00639d9fede532ffeb7952 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 14 Jul 2015 14:41:53 -0700 Subject: [PATCH 074/104] split out vec-zsts correctly --- src/doc/tarpl/SUMMARY.md | 1 + src/doc/tarpl/vec-zsts.md | 176 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 src/doc/tarpl/vec-zsts.md diff --git a/src/doc/tarpl/SUMMARY.md b/src/doc/tarpl/SUMMARY.md index 8a8ea6dfab79..4b38b7faca55 100644 --- a/src/doc/tarpl/SUMMARY.md +++ b/src/doc/tarpl/SUMMARY.md @@ -45,5 +45,6 @@ * [Insert and Remove](vec-insert-remove.md) * [IntoIter](vec-into-iter.md) * [Drain](vec-drain.md) + * [Handling Zero-Sized Types](vec-zsts.md) * [Final Code](vec-final.md) * [Implementing Arc and Mutex](arc-and-mutex.md) diff --git a/src/doc/tarpl/vec-zsts.md b/src/doc/tarpl/vec-zsts.md new file mode 100644 index 000000000000..931aed33ef5d --- /dev/null +++ b/src/doc/tarpl/vec-zsts.md @@ -0,0 +1,176 @@ +% Handling Zero-Sized Types + +It's time. We're going to fight the spectre that is zero-sized types. Safe Rust +*never* needs to care about this, but Vec is very intensive on raw pointers and +raw allocations, which are exactly the *only* two things that care about +zero-sized types. We need to be careful of two things: + +* The raw allocator API has undefined behaviour if you pass in 0 for an + allocation size. +* raw pointer offsets are no-ops for zero-sized types, which will break our + C-style pointer iterator. + +Thankfully we abstracted out pointer-iterators and allocating handling into +RawValIter and RawVec respectively. How mysteriously convenient. + + + + +## Allocating Zero-Sized Types + +So if the allocator API doesn't support zero-sized allocations, what on earth +do we store as our allocation? Why, `heap::EMPTY` of course! Almost every operation +with a ZST is a no-op since ZSTs have exactly one value, and therefore no state needs +to be considered to store or load them. This actually extends to `ptr::read` and +`ptr::write`: they won't actually look at the pointer at all. As such we *never* need +to change the pointer. + +Note however that our previous reliance on running out of memory before overflow is +no longer valid with zero-sized types. We must explicitly guard against capacity +overflow for zero-sized types. + +Due to our current architecture, all this means is writing 3 guards, one in each +method of RawVec. + +```rust,ignore +impl RawVec { + fn new() -> Self { + unsafe { + // !0 is usize::MAX. This branch should be stripped at compile time. + let cap = if mem::size_of::() == 0 { !0 } else { 0 }; + + // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" + RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } + } + } + + fn grow(&mut self) { + unsafe { + let elem_size = mem::size_of::(); + + // since we set the capacity to usize::MAX when elem_size is + // 0, getting to here necessarily means the Vec is overfull. + assert!(elem_size != 0, "capacity overflow"); + + let align = mem::align_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + let new_cap = 2 * self.cap; + let ptr = heap::reallocate(*self.ptr as *mut _, + self.cap * elem_size, + new_cap * elem_size, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom() } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } + } +} + +impl Drop for RawVec { + fn drop(&mut self) { + let elem_size = mem::size_of::(); + + // don't free zero-sized allocations, as they were never allocated. + if self.cap != 0 && elem_size != 0 { + let align = mem::align_of::(); + + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr as *mut _, num_bytes, align); + } + } + } +} +``` + +That's it. We support pushing and popping zero-sized types now. Our iterators +(that aren't provided by slice Deref) are still busted, though. + + + + +## Iterating Zero-Sized Types + +Zero-sized offsets are no-ops. This means that our current design will always +initialize `start` and `end` as the same value, and our iterators will yield +nothing. The current solution to this is to cast the pointers to integers, +increment, and then cast them back: + +```rust,ignore +impl RawValIter { + unsafe fn new(slice: &[T]) -> Self { + RawValIter { + start: slice.as_ptr(), + end: if mem::size_of::() == 0 { + ((slice.as_ptr() as usize) + slice.len()) as *const _ + } else if slice.len() == 0 { + slice.as_ptr() + } else { + slice.as_ptr().offset(slice.len() as isize) + } + } + } +} +``` + +Now we have a different bug. Instead of our iterators not running at all, our +iterators now run *forever*. We need to do the same trick in our iterator impls. +Also, our size_hint computation code will divide by 0 for ZSTs. Since we'll +basically be treating the two pointers as if they point to bytes, we'll just +map size 0 to divide by 1. + +```rust,ignore +impl Iterator for RawValIter { + type Item = T; + fn next(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + let result = ptr::read(self.start); + self.start = if mem::size_of::() == 0 { + (self.start as usize + 1) as *const _ + } else { + self.start.offset(1); + } + Some(result) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let elem_size = mem::size_of::(); + let len = (self.end as usize - self.start as usize) + / if elem_size == 0 { 1 } else { elem_size }; + (len, Some(len)) + } +} + +impl DoubleEndedIterator for RawValIter { + fn next_back(&mut self) -> Option { + if self.start == self.end { + None + } else { + unsafe { + self.end = if mem::size_of::() == 0 { + (self.end as usize - 1) as *const _ + } else { + self.end.offset(-1); + } + Some(ptr::read(self.end)) + } + } + } +} +``` + +And that's it. Iteration works! From c5a1b87c6f95e023ab465514aac143bdbd88f56b Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 14 Jul 2015 17:59:28 -0700 Subject: [PATCH 075/104] properly remove moved text --- src/doc/tarpl/vec-drain.md | 177 ------------------------------------- 1 file changed, 177 deletions(-) diff --git a/src/doc/tarpl/vec-drain.md b/src/doc/tarpl/vec-drain.md index 8dd085d6ebcd..df7cf00b99b6 100644 --- a/src/doc/tarpl/vec-drain.md +++ b/src/doc/tarpl/vec-drain.md @@ -139,180 +139,3 @@ impl Vec { - -# Handling Zero-Sized Types - -It's time. We're going to fight the spectre that is zero-sized types. Safe Rust -*never* needs to care about this, but Vec is very intensive on raw pointers and -raw allocations, which are exactly the *only* two things that care about -zero-sized types. We need to be careful of two things: - -* The raw allocator API has undefined behaviour if you pass in 0 for an - allocation size. -* raw pointer offsets are no-ops for zero-sized types, which will break our - C-style pointer iterator. - -Thankfully we abstracted out pointer-iterators and allocating handling into -RawValIter and RawVec respectively. How mysteriously convenient. - - - - -## Allocating Zero-Sized Types - -So if the allocator API doesn't support zero-sized allocations, what on earth -do we store as our allocation? Why, `heap::EMPTY` of course! Almost every operation -with a ZST is a no-op since ZSTs have exactly one value, and therefore no state needs -to be considered to store or load them. This actually extends to `ptr::read` and -`ptr::write`: they won't actually look at the pointer at all. As such we *never* need -to change the pointer. - -Note however that our previous reliance on running out of memory before overflow is -no longer valid with zero-sized types. We must explicitly guard against capacity -overflow for zero-sized types. - -Due to our current architecture, all this means is writing 3 guards, one in each -method of RawVec. - -```rust,ignore -impl RawVec { - fn new() -> Self { - unsafe { - // !0 is usize::MAX. This branch should be stripped at compile time. - let cap = if mem::size_of::() == 0 { !0 } else { 0 }; - - // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" - RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap } - } - } - - fn grow(&mut self) { - unsafe { - let elem_size = mem::size_of::(); - - // since we set the capacity to usize::MAX when elem_size is - // 0, getting to here necessarily means the Vec is overfull. - assert!(elem_size != 0, "capacity overflow"); - - let align = mem::align_of::(); - - let (new_cap, ptr) = if self.cap == 0 { - let ptr = heap::allocate(elem_size, align); - (1, ptr) - } else { - let new_cap = 2 * self.cap; - let ptr = heap::reallocate(*self.ptr as *mut _, - self.cap * elem_size, - new_cap * elem_size, - align); - (new_cap, ptr) - }; - - // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { oom() } - - self.ptr = Unique::new(ptr as *mut _); - self.cap = new_cap; - } - } -} - -impl Drop for RawVec { - fn drop(&mut self) { - let elem_size = mem::size_of::(); - - // don't free zero-sized allocations, as they were never allocated. - if self.cap != 0 && elem_size != 0 { - let align = mem::align_of::(); - - let num_bytes = elem_size * self.cap; - unsafe { - heap::deallocate(*self.ptr as *mut _, num_bytes, align); - } - } - } -} -``` - -That's it. We support pushing and popping zero-sized types now. Our iterators -(that aren't provided by slice Deref) are still busted, though. - - - - -## Iterating Zero-Sized Types - -Zero-sized offsets are no-ops. This means that our current design will always -initialize `start` and `end` as the same value, and our iterators will yield -nothing. The current solution to this is to cast the pointers to integers, -increment, and then cast them back: - -```rust,ignore -impl RawValIter { - unsafe fn new(slice: &[T]) -> Self { - RawValIter { - start: slice.as_ptr(), - end: if mem::size_of::() == 0 { - ((slice.as_ptr() as usize) + slice.len()) as *const _ - } else if slice.len() == 0 { - slice.as_ptr() - } else { - slice.as_ptr().offset(slice.len() as isize) - } - } - } -} -``` - -Now we have a different bug. Instead of our iterators not running at all, our -iterators now run *forever*. We need to do the same trick in our iterator impls. -Also, our size_hint computation code will divide by 0 for ZSTs. Since we'll -basically be treating the two pointers as if they point to bytes, we'll just -map size 0 to divide by 1. - -```rust,ignore -impl Iterator for RawValIter { - type Item = T; - fn next(&mut self) -> Option { - if self.start == self.end { - None - } else { - unsafe { - let result = ptr::read(self.start); - self.start = if mem::size_of::() == 0 { - (self.start as usize + 1) as *const _ - } else { - self.start.offset(1); - } - Some(result) - } - } - } - - fn size_hint(&self) -> (usize, Option) { - let elem_size = mem::size_of::(); - let len = (self.end as usize - self.start as usize) - / if elem_size == 0 { 1 } else { elem_size }; - (len, Some(len)) - } -} - -impl DoubleEndedIterator for RawValIter { - fn next_back(&mut self) -> Option { - if self.start == self.end { - None - } else { - unsafe { - self.end = if mem::size_of::() == 0 { - (self.end as usize - 1) as *const _ - } else { - self.end.offset(-1); - } - Some(ptr::read(self.end)) - } - } - } -} -``` - -And that's it. Iteration works! From d1b899e57a7aa5cec0380900465e0d7d443762d2 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 17 Jul 2015 11:46:02 -0700 Subject: [PATCH 076/104] update subtyping to be a bit clearer about reference variance --- src/doc/tarpl/subtyping.md | 119 ++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 49 deletions(-) diff --git a/src/doc/tarpl/subtyping.md b/src/doc/tarpl/subtyping.md index e43c365bf4f7..1b33c9abaa1b 100644 --- a/src/doc/tarpl/subtyping.md +++ b/src/doc/tarpl/subtyping.md @@ -1,27 +1,28 @@ % Subtyping and Variance -Although Rust doesn't have any notion of inheritance, it *does* include subtyping. -In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes are scopes, -we can partially order them based on the *contains* (outlives) relationship. We -can even express this as a generic bound. +Although Rust doesn't have any notion of inheritance, it *does* include +subtyping. In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes +are scopes, we can partially order them based on the *contains* (outlives) +relationship. We can even express this as a generic bound. -Subtyping on lifetimes in terms of that relationship: if `'a: 'b` -("a contains b" or "a outlives b"), then `'a` is a subtype of `'b`. This is a -large source of confusion, because it seems intuitively backwards to many: -the bigger scope is a *sub type* of the smaller scope. +Subtyping on lifetimes in terms of that relationship: if `'a: 'b` ("a contains +b" or "a outlives b"), then `'a` is a subtype of `'b`. This is a large source of +confusion, because it seems intuitively backwards to many: the bigger scope is a +*sub type* of the smaller scope. This does in fact make sense, though. The intuitive reason for this is that if -you expect an `&'a u8`, then it's totally fine for me to hand you an `&'static u8`, -in the same way that if you expect an Animal in Java, it's totally fine for me to -hand you a Cat. Cats are just Animals *and more*, just as `'static` is just `'a` -*and more*. +you expect an `&'a u8`, then it's totally fine for me to hand you an `&'static +u8`, in the same way that if you expect an Animal in Java, it's totally fine for +me to hand you a Cat. Cats are just Animals *and more*, just as `'static` is +just `'a` *and more*. -(Note, the subtyping relationship and typed-ness of lifetimes is a fairly arbitrary -construct that some disagree with. However it simplifies our analysis to treat -lifetimes and types uniformly.) +(Note, the subtyping relationship and typed-ness of lifetimes is a fairly +arbitrary construct that some disagree with. However it simplifies our analysis +to treat lifetimes and types uniformly.) -Higher-ranked lifetimes are also subtypes of every concrete lifetime. This is because -taking an arbitrary lifetime is strictly more general than taking a specific one. +Higher-ranked lifetimes are also subtypes of every concrete lifetime. This is +because taking an arbitrary lifetime is strictly more general than taking a +specific one. @@ -29,37 +30,49 @@ taking an arbitrary lifetime is strictly more general than taking a specific one Variance is where things get a bit complicated. -Variance is a property that *type constructors* have. A type constructor in Rust -is a generic type with unbound arguments. For instance `Vec` is a type constructor -that takes a `T` and returns a `Vec`. `&` and `&mut` are type constructors that -take a two types: a lifetime, and a type to point to. +Variance is a property that *type constructors* have with respect to their +arguments. A type constructor in Rust is a generic type with unbound arguments. +For instance `Vec` is a type constructor that takes a `T` and returns a +`Vec`. `&` and `&mut` are type constructors that take a two types: a +lifetime, and a type to point to. A type constructor's *variance* is how the subtyping of its inputs affects the subtyping of its outputs. There are two kinds of variance in Rust: -* F is *variant* if `T` being a subtype of `U` implies `F` is a subtype of `F` -* F is *invariant* otherwise (no subtyping relation can be derived) +* F is *variant* over `T` if `T` being a subtype of `U` implies + `F` is a subtype of `F` (subtyping "passes through") +* F is *invariant* over `T` otherwise (no subtyping relation can be derived) -(For those of you who are familiar with variance from other languages, what we refer -to as "just" variance is in fact *covariance*. Rust does not have contravariance. -Historically Rust did have some contravariance but it was scrapped due to poor -interactions with other features.) +(For those of you who are familiar with variance from other languages, what we +refer to as "just" variance is in fact *covariance*. Rust does not have +contravariance. Historically Rust did have some contravariance but it was +scrapped due to poor interactions with other features. If you experience +contravariance in Rust call your local compiler developer for medical advice.) Some important variances: -* `&` is variant (as is `*const` by metaphor) -* `&mut` is invariant -* `Fn(T) -> U` is invariant with respect to `T`, but variant with respect to `U` -* `Box`, `Vec`, and all other collections are variant -* `UnsafeCell`, `Cell`, `RefCell`, `Mutex` and all "interior mutability" - types are invariant (as is `*mut` by metaphor) +* `&'a T` is variant over `'a` and `T` (as is `*const T` by metaphor) +* `&'a mut T` is variant with over `'a` but invariant over `T` +* `Fn(T) -> U` is invariant over `T`, but variant over `U` +* `Box`, `Vec`, and all other collections are variant over their contents +* `UnsafeCell`, `Cell`, `RefCell`, `Mutex` and all other + interior mutability types are invariant over T (as is `*mut T` by metaphor) -To understand why these variances are correct and desirable, we will consider several -examples. We have already covered why `&` should be variant when introducing subtyping: -it's desirable to be able to pass longer-lived things where shorter-lived things are -needed. +To understand why these variances are correct and desirable, we will consider +several examples. -To see why `&mut` should be invariant, consider the following code: + +We have already covered why `&'a T` should be variant over `'a` when +introducing subtyping: it's desirable to be able to pass longer-lived things +where shorter-lived things are needed. + +Similar reasoning applies to why it should be variant over T. It is reasonable +to be able to pass `&&'static str` where an `&&'a str` is expected. The +additional level of indirection does not change the desire to be able to pass +longer lived things where shorted lived things are expected. + +However this logic *does not* apply to see why `&mut`. To see why &mut should +be invariant over T, consider the following code: ```rust,ignore fn overwrite(input: &mut T, new: &mut T) { @@ -78,17 +91,24 @@ fn main() { ``` The signature of `overwrite` is clearly valid: it takes mutable references to -two values of the same type, and overwrites one with the other. If `&mut` was -variant, then `&mut &'a str` would be a subtype of `&mut &'static str`, since -`&'a str` is a subtype of `&'static str`. Therefore the lifetime of +two values of the same type, and overwrites one with the other. If `&mut T` was +variant over T, then `&mut &'a str` would be a subtype of `&mut &'static str`, +since `&'a str` is a subtype of `&'static str`. Therefore the lifetime of `forever_str` would successfully be "shrunk" down to the shorter lifetime of `string`, and `overwrite` would be called successfully. `string` would subsequently be dropped, and `forever_str` would point to freed memory when we print it! Therefore `&mut` should be invariant. -This is the general theme of variance vs -invariance: if variance would allow you to *store* a short-lived value in a -longer-lived slot, then you must be invariant. +This is the general theme of variance vs invariance: if variance would allow you +to *store* a short-lived value over a longer-lived slot, then you must be +invariant. + +However it *is* sound for `&'a mut T` to be variant over `'a`. The key difference +between `'a` and T is that `'a` is a property of the reference itself, +while T is something the reference is borrowing. If you change T's type, then +the source still remembers the original type. However if you change the +lifetime's type, no one but the reference knows this information, so it's fine. +Put another way, `&'a mut T` owns `'a`, but only *borrows* T. `Box` and `Vec` are interesting cases because they're variant, but you can definitely store values in them! This is where Rust gets really clever: it's @@ -115,9 +135,9 @@ Weakening when you pass by-value is fine because there's no one else who trouble was because there's always someone else who remembers the original subtype: the actual owner. -The invariance of the cell types can be seen as follows: `&` is like an `&mut` for a -cell, because you can still store values in them through an `&`. Therefore cells -must be invariant to avoid lifetime smuggling. +The invariance of the cell types can be seen as follows: `&` is like an `&mut` +for a cell, because you can still store values in them through an `&`. Therefore +cells must be invariant to avoid lifetime smuggling. `Fn` is the most subtle case because it has mixed variance. To see why `Fn(T) -> U` should be invariant over T, consider the following function @@ -128,8 +148,9 @@ signature: fn foo(&'a str) -> usize; ``` -This signature claims that it can handle any `&str` that lives *at least* as long -as `'a`. Now if this signature was variant with respect to `&str`, that would mean +This signature claims that it can handle any `&str` that lives *at least* as +long as `'a`. Now if this signature was variant over `&'a str`, that +would mean ```rust,ignore fn foo(&'static str) -> usize; From eba459a5c2abf1c6869f0947e297b0805cdc27ef Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 17 Jul 2015 22:20:11 -0700 Subject: [PATCH 077/104] shard out misc section on lifetimes properly --- src/doc/tarpl/SUMMARY.md | 4 +- src/doc/tarpl/dropck.md | 127 +++++++++++++++++++++++++ src/doc/tarpl/lifetime-splitting.md | 140 ++++++++++++++++++++++++++++ src/doc/tarpl/phantom-data.md | 87 +++++++++++++++++ 4 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 src/doc/tarpl/dropck.md create mode 100644 src/doc/tarpl/lifetime-splitting.md create mode 100644 src/doc/tarpl/phantom-data.md diff --git a/src/doc/tarpl/SUMMARY.md b/src/doc/tarpl/SUMMARY.md index 4b38b7faca55..b0d75bfc85c9 100644 --- a/src/doc/tarpl/SUMMARY.md +++ b/src/doc/tarpl/SUMMARY.md @@ -15,7 +15,9 @@ * [Unbounded Lifetimes](unbounded-lifetimes.md) * [Higher-Rank Trait Bounds](hrtb.md) * [Subtyping and Variance](subtyping.md) - * [Misc](lifetime-misc.md) + * [Drop Check](dropck.md) + * [PhantomData](phantom-data.md) + * [Splitting Lifetimes](lifetime-splitting.md) * [Type Conversions](conversions.md) * [Coercions](coercions.md) * [The Dot Operator](dot-operator.md) diff --git a/src/doc/tarpl/dropck.md b/src/doc/tarpl/dropck.md new file mode 100644 index 000000000000..e1a25f513c7f --- /dev/null +++ b/src/doc/tarpl/dropck.md @@ -0,0 +1,127 @@ +% Drop Check + +We have seen how lifetimes provide us some fairly simple rules for ensuring +that never read dangling references. However up to this point we have only ever +interacted with the *outlives* relationship in an inclusive manner. That is, +when we talked about `'a: 'b`, it was ok for `'a` to live *exactly* as long as +`'b`. At first glance, this seems to be a meaningless distinction. Nothing ever +gets dropped at the same time as another, right? This is why we used the +following desugarring of `let` statements: + +```rust +let x; +let y; +``` + +```rust +{ + let x; + { + let y; + } +} +``` + +Each creates its own scope, clearly establishing that one drops before the +other. However, what if we do the following? + +```rust +let (x, y) = (vec![], vec![]); +``` + +Does either value strictly outlive the other? The answer is in fact *no*, +neither value strictly outlives the other. Of course, one of x or y will be +dropped before the other, but the actual order is not specified. Tuples aren't +special in this regard; composite structures just don't guarantee their +destruction order as of Rust 1.0. + +We *could* specify this for the fields of built-in composites like tuples and +structs. However, what about something like Vec? Vec has to manually drop its +elements via pure-library code. In general, anything that implements Drop has +a chance to fiddle with its innards during its final death knell. Therefore +the compiler can't sufficiently reason about the actual destruction order +of the contents of any type that implements Drop. + +So why do we care? We care because if the type system isn't careful, it could +accidentally make dangling pointers. Consider the following simple program: + +```rust +struct Inspector<'a>(&'a u8); + +fn main() { + let (days, inspector); + days = Box::new(1); + inspector = Inspector(&days); +} +``` + +This program is totally sound and compiles today. The fact that `days` does +not *strictly* outlive `inspector` doesn't matter. As long as the `inspector` +is alive, so is days. + +However if we add a destructor, the program will no longer compile! + +```rust,ignore +struct Inspector<'a>(&'a u8); + +impl<'a> Drop for Inspector<'a> { + fn drop(&mut self) { + println!("I was only {} days from retirement!", self.0); + } +} + +fn main() { + let (days, inspector); + days = Box::new(1); + inspector = Inspector(&days); + // Let's say `days` happens to get dropped first. + // Then when Inspector is dropped, it will try to read free'd memory! +} +``` + +```text +:12:28: 12:32 error: `days` does not live long enough +:12 inspector = Inspector(&days); + ^~~~ +:9:11: 15:2 note: reference must be valid for the block at 9:10... +:9 fn main() { +:10 let (days, inspector); +:11 days = Box::new(1); +:12 inspector = Inspector(&days); +:13 // Let's say `days` happens to get dropped first. +:14 // Then when Inspector is dropped, it will try to read free'd memory! + ... +:10:27: 15:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 10:26 +:10 let (days, inspector); +:11 days = Box::new(1); +:12 inspector = Inspector(&days); +:13 // Let's say `days` happens to get dropped first. +:14 // Then when Inspector is dropped, it will try to read free'd memory! +:15 } +``` + +Implementing Drop lets the Inspector execute some arbitrary code *during* its +death. This means it can potentially observe that types that are supposed to +live as long as it does actually were destroyed first. + +Interestingly, only *generic* types need to worry about this. If they aren't +generic, then the only lifetimes they can harbor are `'static`, which will truly +live *forever*. This is why this problem is referred to as *sound generic drop*. +Sound generic drop is enforced by the *drop checker*. As of this writing, some +of the finer details of how the drop checker validates types is totally up in +the air. However The Big Rule is the subtlety that we have focused on this whole +section: + +**For a generic type to soundly implement drop, it must strictly outlive all of +its generic arguments.** + +This rule is sufficient but not necessary to satisfy the drop checker. That is, +if your type obeys this rule then it's *definitely* sound to drop. However +there are special cases where you can fail to satisfy this, but still +successfully pass the borrow checker. These are the precise rules that are +currently up in the air. + +It turns out that when writing unsafe code, we generally don't need to +worry at all about doing the right thing for the drop checker. However there +is *one* special case that you need to worry about, which we will look at in +the next section. diff --git a/src/doc/tarpl/lifetime-splitting.md b/src/doc/tarpl/lifetime-splitting.md new file mode 100644 index 000000000000..7ab2d379ffd5 --- /dev/null +++ b/src/doc/tarpl/lifetime-splitting.md @@ -0,0 +1,140 @@ +% Splitting Lifetimes + +The mutual exclusion property of mutable references can be very limiting when +working with a composite structure. The borrow checker understands some basic stuff, but +will fall over pretty easily. It *does* understand structs sufficiently to +know that it's possible to borrow disjoint fields of a struct simultaneously. +So this works today: + +```rust +struct Foo { + a: i32, + b: i32, + c: i32, +} + +let mut x = Foo {a: 0, b: 0, c: 0}; +let a = &mut x.a; +let b = &mut x.b; +let c = &x.c; +*b += 1; +let c2 = &x.c; +*a += 10; +println!("{} {} {} {}", a, b, c, c2); +``` + +However borrowck doesn't understand arrays or slices in any way, so this doesn't +work: + +```rust,ignore +let x = [1, 2, 3]; +let a = &mut x[0]; +let b = &mut x[1]; +println!("{} {}", a, b); +``` + +```text +:3:18: 3:22 error: cannot borrow immutable indexed content `x[..]` as mutable +:3 let a = &mut x[0]; + ^~~~ +:4:18: 4:22 error: cannot borrow immutable indexed content `x[..]` as mutable +:4 let b = &mut x[1]; + ^~~~ +error: aborting due to 2 previous errors +``` + +While it was plausible that borrowck could understand this simple case, it's +pretty clearly hopeless for borrowck to understand disjointness in general +container types like a tree, especially if distinct keys actually *do* map +to the same value. + +In order to "teach" borrowck that what we're doing is ok, we need to drop down +to unsafe code. For instance, mutable slices expose a `split_at_mut` function that +consumes the slice and returns *two* mutable slices. One for everything to the +left of the index, and one for everything to the right. Intuitively we know this +is safe because the slices don't alias. However the implementation requires some +unsafety: + +```rust,ignore +fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + unsafe { + let self2: &mut [T] = mem::transmute_copy(&self); + + (ops::IndexMut::index_mut(self, ops::RangeTo { end: mid } ), + ops::IndexMut::index_mut(self2, ops::RangeFrom { start: mid } )) + } +} +``` + +This is pretty plainly dangerous. We use transmute to duplicate the slice with an +*unbounded* lifetime, so that it can be treated as disjoint from the other until +we unify them when we return. + +However more subtle is how iterators that yield mutable references work. +The iterator trait is defined as follows: + +```rust +trait Iterator { + type Item; + + fn next(&mut self) -> Option; +} +``` + +Given this definition, Self::Item has *no* connection to `self`. This means +that we can call `next` several times in a row, and hold onto all the results +*concurrently*. This is perfectly fine for by-value iterators, which have exactly +these semantics. It's also actually fine for shared references, as they admit +arbitrarily many references to the same thing (although the +iterator needs to be a separate object from the thing being shared). But mutable +references make this a mess. At first glance, they might seem completely +incompatible with this API, as it would produce multiple mutable references to +the same object! + +However it actually *does* work, exactly because iterators are one-shot objects. +Everything an IterMut yields will be yielded *at most* once, so we don't *actually* +ever yield multiple mutable references to the same piece of data. + +In general all mutable iterators require *some* unsafe code *somewhere*, though. +Whether it's raw pointers, or safely composing on top of *another* IterMut. + +For instance, VecDeque's IterMut: + +```rust,ignore +struct IterMut<'a, T:'a> { + // The whole backing array. Some of these indices are initialized! + ring: &'a mut [T], + tail: usize, + head: usize, +} + +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + fn next(&mut self) -> Option<&'a mut T> { + if self.tail == self.head { + return None; + } + let tail = self.tail; + self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); + + unsafe { + // might as well do unchecked indexing since wrap_index has us + // in-bounds, and many of the "middle" indices are uninitialized + // anyway. + let elem = self.ring.get_unchecked_mut(tail); + + // round-trip through a raw pointer to unbound the lifetime from + // ourselves + Some(&mut *(elem as *mut _)) + } + } +} +``` + +A very subtle but interesting detail in this design is that it *relies on +privacy to be sound*. Borrowck works on some very simple rules. One of those rules +is that if we have a live &mut Foo and Foo contains an &mut Bar, then that &mut +Bar is *also* live. Since IterMut is always live when `next` can be called, if +`ring` were public then we could mutate `ring` while outstanding mutable borrows +to it exist! diff --git a/src/doc/tarpl/phantom-data.md b/src/doc/tarpl/phantom-data.md new file mode 100644 index 000000000000..034f31784295 --- /dev/null +++ b/src/doc/tarpl/phantom-data.md @@ -0,0 +1,87 @@ +% PhantomData + +When working with unsafe code, we can often end up in a situation where +types or lifetimes are logically associated with a struct, but not actually +part of a field. This most commonly occurs with lifetimes. For instance, the +`Iter` for `&'a [T]` is (approximately) defined as follows: + +```rust,ignore +struct Iter<'a, T: 'a> { + ptr: *const T, + end: *const T, +} +``` + +However because `'a` is unused within the struct's body, it's *unbounded*. +Because of the troubles this has historically caused, unbounded lifetimes and +types are *illegal* in struct definitions. Therefore we must somehow refer +to these types in the body. Correctly doing this is necessary to have +correct variance and drop checking. + +We do this using *PhantomData*, which is a special marker type. PhantomData +consumes no space, but simulates a field of the given type for the purpose of +static analysis. This was deemed to be less error-prone than explicitly telling +the type-system the kind of variance that you want, while also providing other +useful such as the information needed by drop check. + +Iter logically contains a bunch of `&'a T`s, so this is exactly what we tell +the PhantomData to simulate: + +``` +use std::marker; + +struct Iter<'a, T: 'a> { + ptr: *const T, + end: *const T, + _marker: marker::PhantomData<&'a T>, +} +``` + +and that's it. The lifetime will be bounded, and your iterator will be variant +over `'a` and `T`. Everything Just Works. + +Another important example is Vec, which is (approximately) defined as follows: + +``` +struct Vec { + data: *const T, // *const for variance! + len: usize, + cap: usize, +} +``` + +Unlike the previous example it *appears* that everything is exactly as we +want. Every generic argument to Vec shows up in the at least one field. +Good to go! + +Nope. + +The drop checker will generously determine that Vec does not own any values +of type T. This will in turn make it conclude that it does *not* need to worry +about Vec dropping any T's in its destructor for determining drop check +soundness. This will in turn allow people to create unsoundness using +Vec's destructor. + +In order to tell dropck that we *do* own values of type T, and therefore may +drop some T's when *we* drop, we must add an extra PhantomData saying exactly +that: + +``` +use std::marker; + +struct Vec { + data: *const T, // *const for covariance! + len: usize, + cap: usize, + _marker: marker::PhantomData, +} +``` + +Raw pointers that own an allocation is such a pervasive pattern that the +standard library made a utility for itself called `Unique` which: + +* wraps a `*const T` for variance +* includes a `PhantomData`, +* auto-derives Send/Sync as if T was contained +* marks the pointer as NonZero for the null-pointer optimization + From fc2d29450ed5bd0f72179a2a3da8ac4ecf86c47a Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 17 Jul 2015 22:20:44 -0700 Subject: [PATCH 078/104] no really I deleted you --- src/doc/tarpl/lifetime-misc.md | 233 --------------------------------- 1 file changed, 233 deletions(-) delete mode 100644 src/doc/tarpl/lifetime-misc.md diff --git a/src/doc/tarpl/lifetime-misc.md b/src/doc/tarpl/lifetime-misc.md deleted file mode 100644 index bd44bb6964af..000000000000 --- a/src/doc/tarpl/lifetime-misc.md +++ /dev/null @@ -1,233 +0,0 @@ -% misc - -This is just a dumping ground while I work out what to do with this stuff - - -# PhantomData - -When working with unsafe code, we can often end up in a situation where -types or lifetimes are logically associated with a struct, but not actually -part of a field. This most commonly occurs with lifetimes. For instance, the `Iter` -for `&'a [T]` is (approximately) defined as follows: - -```rust,ignore -struct Iter<'a, T: 'a> { - ptr: *const T, - end: *const T, -} -``` - -However because `'a` is unused within the struct's body, it's *unbound*. -Because of the troubles this has historically caused, unbound lifetimes and -types are *illegal* in struct definitions. Therefore we must somehow refer -to these types in the body. Correctly doing this is necessary to have -correct variance and drop checking. - -We do this using *PhantomData*, which is a special marker type. PhantomData -consumes no space, but simulates a field of the given type for the purpose of -static analysis. This was deemed to be less error-prone than explicitly telling -the type-system the kind of variance that you want, while also providing other -useful information. - -Iter logically contains `&'a T`, so this is exactly what we tell -the PhantomData to simulate: - -``` -use std::marker; - -struct Iter<'a, T: 'a> { - ptr: *const T, - end: *const T, - _marker: marker::PhantomData<&'a T>, -} -``` - - - - -# Dropck - -When a type is going out of scope, Rust will try to Drop it. Drop executes -arbitrary code, and in fact allows us to "smuggle" arbitrary code execution -into many places. As such additional soundness checks (dropck) are necessary to -ensure that a type T can be safely instantiated and dropped. It turns out that we -*really* don't need to care about dropck in practice, as it often "just works". - -However the one exception is with PhantomData. Given a struct like Vec: - -``` -struct Vec { - data: *const T, // *const for variance! - len: usize, - cap: usize, -} -``` - -dropck will generously determine that Vec does not own any values of -type T. This will unfortunately allow people to construct unsound Drop -implementations that access data that has already been dropped. In order to -tell dropck that we *do* own values of type T, and may call destructors of that -type, we must add extra PhantomData: - -``` -use std::marker; - -struct Vec { - data: *const T, // *const for covariance! - len: usize, - cap: usize, - _marker: marker::PhantomData, -} -``` - -Raw pointers that own an allocation is such a pervasive pattern that the -standard library made a utility for itself called `Unique` which: - -* wraps a `*const T`, -* includes a `PhantomData`, -* auto-derives Send/Sync as if T was contained -* marks the pointer as NonZero for the null-pointer optimization - - - - -# Splitting Lifetimes - -The mutual exclusion property of mutable references can be very limiting when -working with a composite structure. The borrow checker understands some basic stuff, but -will fall over pretty easily. It *does* understand structs sufficiently to -know that it's possible to borrow disjoint fields of a struct simultaneously. -So this works today: - -```rust -struct Foo { - a: i32, - b: i32, - c: i32, -} - -let mut x = Foo {a: 0, b: 0, c: 0}; -let a = &mut x.a; -let b = &mut x.b; -let c = &x.c; -*b += 1; -let c2 = &x.c; -*a += 10; -println!("{} {} {} {}", a, b, c, c2); -``` - -However borrowck doesn't understand arrays or slices in any way, so this doesn't -work: - -```rust,ignore -let x = [1, 2, 3]; -let a = &mut x[0]; -let b = &mut x[1]; -println!("{} {}", a, b); -``` - -```text -:3:18: 3:22 error: cannot borrow immutable indexed content `x[..]` as mutable -:3 let a = &mut x[0]; - ^~~~ -:4:18: 4:22 error: cannot borrow immutable indexed content `x[..]` as mutable -:4 let b = &mut x[1]; - ^~~~ -error: aborting due to 2 previous errors -``` - -While it was plausible that borrowck could understand this simple case, it's -pretty clearly hopeless for borrowck to understand disjointness in general -container types like a tree, especially if distinct keys actually *do* map -to the same value. - -In order to "teach" borrowck that what we're doing is ok, we need to drop down -to unsafe code. For instance, mutable slices expose a `split_at_mut` function that -consumes the slice and returns *two* mutable slices. One for everything to the -left of the index, and one for everything to the right. Intuitively we know this -is safe because the slices don't alias. However the implementation requires some -unsafety: - -```rust,ignore -fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { - unsafe { - let self2: &mut [T] = mem::transmute_copy(&self); - - (ops::IndexMut::index_mut(self, ops::RangeTo { end: mid } ), - ops::IndexMut::index_mut(self2, ops::RangeFrom { start: mid } )) - } -} -``` - -This is pretty plainly dangerous. We use transmute to duplicate the slice with an -*unbounded* lifetime, so that it can be treated as disjoint from the other until -we unify them when we return. - -However more subtle is how iterators that yield mutable references work. -The iterator trait is defined as follows: - -```rust -trait Iterator { - type Item; - - fn next(&mut self) -> Option; -} -``` - -Given this definition, Self::Item has *no* connection to `self`. This means -that we can call `next` several times in a row, and hold onto all the results -*concurrently*. This is perfectly fine for by-value iterators, which have exactly -these semantics. It's also actually fine for shared references, as they admit -arbitrarily many references to the same thing (although the -iterator needs to be a separate object from the thing being shared). But mutable -references make this a mess. At first glance, they might seem completely -incompatible with this API, as it would produce multiple mutable references to -the same object! - -However it actually *does* work, exactly because iterators are one-shot objects. -Everything an IterMut yields will be yielded *at most* once, so we don't *actually* -ever yield multiple mutable references to the same piece of data. - -In general all mutable iterators require *some* unsafe code *somewhere*, though. -Whether it's raw pointers, or safely composing on top of *another* IterMut. - -For instance, VecDeque's IterMut: - -```rust,ignore -struct IterMut<'a, T:'a> { - // The whole backing array. Some of these indices are initialized! - ring: &'a mut [T], - tail: usize, - head: usize, -} - -impl<'a, T> Iterator for IterMut<'a, T> { - type Item = &'a mut T; - - fn next(&mut self) -> Option<&'a mut T> { - if self.tail == self.head { - return None; - } - let tail = self.tail; - self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); - - unsafe { - // might as well do unchecked indexing since wrap_index has us - // in-bounds, and many of the "middle" indices are uninitialized - // anyway. - let elem = self.ring.get_unchecked_mut(tail); - - // round-trip through a raw pointer to unbound the lifetime from - // ourselves - Some(&mut *(elem as *mut _)) - } - } -} -``` - -A very subtle but interesting detail in this design is that it *relies on -privacy to be sound*. Borrowck works on some very simple rules. One of those rules -is that if we have a live &mut Foo and Foo contains an &mut Bar, then that &mut -Bar is *also* live. Since IterMut is always live when `next` can be called, if -`ring` were public then we could mutate `ring` while outstanding mutable borrows -to it exist! From b79d279418db10728d5067fc872c0a9f273ba123 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sat, 18 Jul 2015 09:10:01 -0700 Subject: [PATCH 079/104] fix typo --- src/doc/tarpl/exotic-sizes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/tarpl/exotic-sizes.md b/src/doc/tarpl/exotic-sizes.md index 5eeb4850d876..100c526c4c61 100644 --- a/src/doc/tarpl/exotic-sizes.md +++ b/src/doc/tarpl/exotic-sizes.md @@ -63,7 +63,7 @@ context. Rust largely understands that any operation that produces or stores a ZST can be reduced to a no-op. For instance, a `HashSet` can be effeciently implemented as a thin wrapper around `HashMap` because all the operations `HashMap` -normally does to store and retrieve keys will be completely stripped in +normally does to store and retrieve values will be completely stripped in monomorphization. Similarly `Result<(), ()>` and `Option<()>` are effectively just fancy `bool`s. From c97673c7b0fffe131822f2a5be520cf408c68319 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sat, 18 Jul 2015 11:44:41 -0700 Subject: [PATCH 080/104] fix up lifetimes --- src/doc/tarpl/lifetimes.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/doc/tarpl/lifetimes.md b/src/doc/tarpl/lifetimes.md index 7282e4d843cf..350a4ead1309 100644 --- a/src/doc/tarpl/lifetimes.md +++ b/src/doc/tarpl/lifetimes.md @@ -66,11 +66,7 @@ let y = &x; z = y; ``` -The borrow checker always tries to minimize the extent of a lifetime, so it will -likely desugar to something like the following: - ```rust,ignore -// NOTE: `'a: {` and `foo = &'b x` is not valid syntax! 'a: { let x: i32 = 0; 'b: { @@ -191,8 +187,6 @@ println!("{}", x); 'c: { // Temporary scope because we don't need the // &mut to last any longer. - - // NOTE: Vec::push is not valid syntax Vec::push(&'c mut data, 4); } println!("{}", x); From 13b2605ed985a37481dc497357dc6dcdf37ba6ff Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sun, 19 Jul 2015 20:48:51 -0700 Subject: [PATCH 081/104] fixup and cool example for checked-uninit --- src/doc/tarpl/checked-uninit.md | 23 +++++++++++++++++++++++ src/doc/tarpl/other-reprs.md | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/doc/tarpl/checked-uninit.md b/src/doc/tarpl/checked-uninit.md index 65bffd7d09fe..8b03cd497b74 100644 --- a/src/doc/tarpl/checked-uninit.md +++ b/src/doc/tarpl/checked-uninit.md @@ -68,6 +68,29 @@ fn main() { } ``` +Of course, while the analysis doesn't consider actual values, it does +have a relatively sophisticated understanding of dependencies and control +flow. For instance, this works: + +```rust +let x: i32; + +loop { + // Rust doesn't understand that this branch will be taken unconditionally, + // because it relies on actual values. + if true { + // But it does understand that it will only be taken once because + // we *do* unconditionally break out of it. Therefore `x` doesn't + // need to be marked as mutable. + x = 0; + break; + } +} +// It also knows that it's impossible to get here without reaching the break. +// And therefore that `x` must be initialized here! +println!("{}", x); +``` + If a value is moved out of a variable, that variable becomes logically uninitialized if the type of the value isn't Copy. That is: diff --git a/src/doc/tarpl/other-reprs.md b/src/doc/tarpl/other-reprs.md index d4c6134c5432..26e0192a536d 100644 --- a/src/doc/tarpl/other-reprs.md +++ b/src/doc/tarpl/other-reprs.md @@ -47,7 +47,7 @@ discriminant. On non-C-like enums, this will inhibit certain optimizations like the null- pointer optimization. -These reprs have no affect on a struct. +These reprs have no effect on a struct. From 94a89e561a62d54d25dd64329ef8af396d8ec032 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sun, 19 Jul 2015 21:43:17 -0700 Subject: [PATCH 082/104] some conversions cleanup --- src/doc/tarpl/casts.md | 27 +++++++++++++++++---------- src/doc/tarpl/coercions.md | 6 +++--- src/doc/tarpl/conversions.md | 11 +++++++---- src/doc/tarpl/transmutes.md | 18 ++++++++++++------ 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/doc/tarpl/casts.md b/src/doc/tarpl/casts.md index cbcf81d83712..37f84ead7974 100644 --- a/src/doc/tarpl/casts.md +++ b/src/doc/tarpl/casts.md @@ -1,9 +1,21 @@ % Casts -Casts are a superset of coercions: every coercion can be explicitly invoked via -a cast, but some conversions *require* a cast. These "true casts" are generally -regarded as dangerous or problematic actions. True casts revolve around raw -pointers and the primitive numeric types. True casts aren't checked. +Casts are a superset of coercions: every coercion can be explicitly +invoked via a cast. However some conversions *require* a cast. +While coercions are pervasive and largely harmless, these "true casts" +are rare and potentially dangerous. As such, casts must be explicitly invoked +using the `as` keyword: `expr as Type`. + +True casts generally revolve around raw pointers and the primitive numeric +types. Even though they're dangerous, these casts are *infallible* at runtime. +If a cast triggers some subtle corner case no indication will be given that +this occurred. The cast will simply succeed. + +That said, casts aren't `unsafe` because they generally can't violate memory +safety *on their own*. For instance, converting an integer to a raw pointer can +very easily lead to terrible things. However the act of creating the pointer +itself is safe, because actually using a raw pointer is already marked as +`unsafe`. Here's an exhaustive list of all the true casts. For brevity, we will use `*` to denote either a `*const` or `*mut`, and `integer` to denote any integral @@ -22,13 +34,8 @@ primitive: * `fn as *T` where `T: Sized` * `fn as integer` -where `&.T` and `*T` are references of either mutability, -and where unsize_kind(`T`) is the kind of the unsize info -in `T` - the vtable for a trait definition (e.g. `fmt::Display` or -`Iterator`, not `Iterator`) or a length (or `()` if `T: Sized`). - Note that lengths are not adjusted when casting raw slices - -`T: *const [u16] as *const [u8]` creates a slice that only includes +`*const [u16] as *const [u8]` creates a slice that only includes half of the original memory. Casting is not transitive, that is, even if `e as U1 as U2` is a valid diff --git a/src/doc/tarpl/coercions.md b/src/doc/tarpl/coercions.md index df0fdfa57ca1..0eb03d271c45 100644 --- a/src/doc/tarpl/coercions.md +++ b/src/doc/tarpl/coercions.md @@ -9,8 +9,7 @@ Here's all the kinds of coercion: Coercion is allowed between the following types: -* Subtyping: `T` to `U` if `T` is a [subtype](lifetimes.html#subtyping-and-variance) - of `U` +* Subtyping: `T` to `U` if `T` is a [subtype][] of `U` * Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` * Pointer Weakening: * `&mut T` to `&T` @@ -25,7 +24,6 @@ only implemented automatically, and enables the following transformations: * `[T, ..n]` => `[T]` * `T` => `Trait` where `T: Trait` -* `SubTrait` => `Trait` where `SubTrait: Trait` (TODO: is this now implied by the previous?) * `Foo<..., T, ...>` => `Foo<..., U, ...>` where: * `T: Unsize` * `Foo` is a struct @@ -70,3 +68,5 @@ fn main() { :10 foo(t); ^~~ ``` + +[subtype]: subtyping.html diff --git a/src/doc/tarpl/conversions.md b/src/doc/tarpl/conversions.md index 56c050072b97..2309c45c6a84 100644 --- a/src/doc/tarpl/conversions.md +++ b/src/doc/tarpl/conversions.md @@ -1,9 +1,12 @@ % Type Conversions At the end of the day, everything is just a pile of bits somewhere, and type -systems are just there to help us use those bits right. Needing to reinterpret -those piles of bits as different types is a common problem and Rust consequently -gives you several ways to do that. +systems are just there to help us use those bits right. There are two common +problems with typing bits: needing to reinterpret those exact bits as a +different type, and needing to change the bits to have equivalent meaning for +a different type. Because Rust encourages encoding important properties in the +type system, these problems are incredibly pervasive. As such, Rust +consequently gives you several ways to solve them. First we'll look at the ways that *Safe Rust* gives you to reinterpret values. The most trivial way to do this is to just destructure a value into its @@ -26,6 +29,6 @@ fn reinterpret(foo: Foo) -> Bar { } ``` -But this is, at best, annoying to do. For common conversions, Rust provides +But this is, at best, annoying. For common conversions, Rust provides more ergonomic alternatives. diff --git a/src/doc/tarpl/transmutes.md b/src/doc/tarpl/transmutes.md index 577d35ddb56d..f19dda0d8b81 100644 --- a/src/doc/tarpl/transmutes.md +++ b/src/doc/tarpl/transmutes.md @@ -1,10 +1,10 @@ % Transmutes Get out of our way type system! We're going to reinterpret these bits or die -trying! Even though this book is all about doing things that are unsafe, I really -can't emphasize that you should deeply think about finding Another Way than the -operations covered in this section. This is really, truly, the most horribly -unsafe thing you can do in Rust. The railguards here are dental floss. +trying! Even though this book is all about doing things that are unsafe, I +really can't emphasize that you should deeply think about finding Another Way +than the operations covered in this section. This is really, truly, the most +horribly unsafe thing you can do in Rust. The railguards here are dental floss. `mem::transmute` takes a value of type `T` and reinterprets it to have type `U`. The only restriction is that the `T` and `U` are verified to have the @@ -17,8 +17,11 @@ same size. The ways to cause Undefined Behaviour with this are mind boggling. * Making a primitive with an invalid value is UB * Transmuting between non-repr(C) types is UB * Transmuting an & to &mut is UB + * Transmuting an & to &mut is *always* UB + * No you can't do it + * No you're not special * Transmuting to a reference without an explicitly provided lifetime - produces an [unbound lifetime](lifetimes.html#unbounded-lifetimes) + produces an [unbounded lifetime][] `mem::transmute_copy` somehow manages to be *even more* wildly unsafe than this. It copies `size_of` bytes out of an `&T` and interprets them as a `U`. @@ -26,4 +29,7 @@ The size check that `mem::transmute` has is gone (as it may be valid to copy out a prefix), though it is Undefined Behaviour for `U` to be larger than `T`. Also of course you can get most of the functionality of these functions using -pointer casts. \ No newline at end of file +pointer casts. + + +[unbounded lifetime]: unbounded-lifetimes.html From 42c2f107c120e9da046c9b26aa34238fcd6549b6 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Jul 2015 11:02:45 -0700 Subject: [PATCH 083/104] flesh out void types --- src/doc/tarpl/exotic-sizes.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/doc/tarpl/exotic-sizes.md b/src/doc/tarpl/exotic-sizes.md index 100c526c4c61..d4df9492da77 100644 --- a/src/doc/tarpl/exotic-sizes.md +++ b/src/doc/tarpl/exotic-sizes.md @@ -81,9 +81,33 @@ consider passing in `0` as Undefined Behaviour. Rust also enables types to be declared that *cannot even be instantiated*. These types can only be talked about at the type level, and never at the value level. +Empty types can be declared by specifying an enum with no variants: ```rust -enum Foo { } // No variants = EMPTY +enum Void {} // No variants = EMPTY ``` -TODO: WHY?! +Empty types are even more marginal than ZSTs. The primary motivating example for +Void types is type-level unreachability. For instance, suppose an API needs to +return a Result in general, but a specific case actually is infallible. It's +actually possible to communicate this at the type level by returning a +`Result`. Consumers of the API can confidently unwrap such a Result +knowing that it's *statically impossible* for this value to be an `Err`, as +this would require providing a value of type Void. + +In principle, Rust can do some interesting analysees and optimizations based +on this fact. For instance, `Result` could be represented as just `T`, +because the Err case doesn't actually exist. Also in principle the following +could compile: + +```rust,ignore +enum Void {} + +let res: Result = Ok(0); + +// Err doesn't exist anymore, so Ok is actually irrefutable. +let Ok(num) = res; +``` + +But neither of these tricks work today, so all Void types get you today is +the ability to be confident that certain situations are statically impossible. From 5f6e0abe27aa6632f95492ad8864d8084c1bacef Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Jul 2015 11:31:29 -0700 Subject: [PATCH 084/104] clean up vec chapter of tarpl --- src/doc/tarpl/SUMMARY.md | 1 + src/doc/tarpl/vec-alloc.md | 2 +- src/doc/tarpl/vec-dealloc.md | 12 +-- src/doc/tarpl/vec-deref.md | 20 ++-- src/doc/tarpl/vec-drain.md | 9 +- src/doc/tarpl/vec-insert-remove.md | 9 +- src/doc/tarpl/vec-into-iter.md | 159 +++-------------------------- src/doc/tarpl/vec-layout.md | 21 ++-- src/doc/tarpl/vec-raw.md | 136 ++++++++++++++++++++++++ 9 files changed, 192 insertions(+), 177 deletions(-) create mode 100644 src/doc/tarpl/vec-raw.md diff --git a/src/doc/tarpl/SUMMARY.md b/src/doc/tarpl/SUMMARY.md index b0d75bfc85c9..d8b348760765 100644 --- a/src/doc/tarpl/SUMMARY.md +++ b/src/doc/tarpl/SUMMARY.md @@ -46,6 +46,7 @@ * [Deref](vec-deref.md) * [Insert and Remove](vec-insert-remove.md) * [IntoIter](vec-into-iter.md) + * [RawVec](vec-raw.md) * [Drain](vec-drain.md) * [Handling Zero-Sized Types](vec-zsts.md) * [Final Code](vec-final.md) diff --git a/src/doc/tarpl/vec-alloc.md b/src/doc/tarpl/vec-alloc.md index e9c9f681ed84..14b9b462afc6 100644 --- a/src/doc/tarpl/vec-alloc.md +++ b/src/doc/tarpl/vec-alloc.md @@ -46,7 +46,7 @@ Okay, now we can write growing. Roughly, we want to have this logic: if cap == 0: allocate() cap = 1 -else +else: reallocate cap *= 2 ``` diff --git a/src/doc/tarpl/vec-dealloc.md b/src/doc/tarpl/vec-dealloc.md index 2ae2477bbacd..b767caa49123 100644 --- a/src/doc/tarpl/vec-dealloc.md +++ b/src/doc/tarpl/vec-dealloc.md @@ -2,13 +2,13 @@ Next we should implement Drop so that we don't massively leak tons of resources. The easiest way is to just call `pop` until it yields None, and then deallocate -our buffer. Note that calling `pop` is uneeded if `T: !Drop`. In theory we can -ask Rust if T needs_drop and omit the calls to `pop`. However in practice LLVM -is *really* good at removing simple side-effect free code like this, so I wouldn't -bother unless you notice it's not being stripped (in this case it is). +our buffer. Note that calling `pop` is unneeded if `T: !Drop`. In theory we can +ask Rust if `T` `needs_drop` and omit the calls to `pop`. However in practice +LLVM is *really* good at removing simple side-effect free code like this, so I +wouldn't bother unless you notice it's not being stripped (in this case it is). -We must not call `heap::deallocate` when `self.cap == 0`, as in this case we haven't -actually allocated any memory. +We must not call `heap::deallocate` when `self.cap == 0`, as in this case we +haven't actually allocated any memory. ```rust,ignore diff --git a/src/doc/tarpl/vec-deref.md b/src/doc/tarpl/vec-deref.md index 826d763f5bbc..6460eab479bd 100644 --- a/src/doc/tarpl/vec-deref.md +++ b/src/doc/tarpl/vec-deref.md @@ -1,13 +1,15 @@ % Deref -Alright! We've got a decent minimal ArrayStack implemented. We can push, we can -pop, and we can clean up after ourselves. However there's a whole mess of functionality -we'd reasonably want. In particular, we have a proper array, but none of the slice -functionality. That's actually pretty easy to solve: we can implement `Deref`. -This will magically make our Vec coerce to and behave like a slice in all sorts of -conditions. +Alright! We've got a decent minimal stack implemented. We can push, we can +pop, and we can clean up after ourselves. However there's a whole mess of +functionality we'd reasonably want. In particular, we have a proper array, but +none of the slice functionality. That's actually pretty easy to solve: we can +implement `Deref`. This will magically make our Vec coerce to, and +behave like, a slice in all sorts of conditions. -All we need is `slice::from_raw_parts`. +All we need is `slice::from_raw_parts`. It will correctly handle empty slices +for us. Later once we set up zero-sized type support it will also Just Work +for those too. ```rust,ignore use std::ops::Deref; @@ -36,5 +38,5 @@ impl DerefMut for Vec { } ``` -Now we have `len`, `first`, `last`, indexing, slicing, sorting, `iter`, `iter_mut`, -and all other sorts of bells and whistles provided by slice. Sweet! +Now we have `len`, `first`, `last`, indexing, slicing, sorting, `iter`, +`iter_mut`, and all other sorts of bells and whistles provided by slice. Sweet! diff --git a/src/doc/tarpl/vec-drain.md b/src/doc/tarpl/vec-drain.md index df7cf00b99b6..b6b282666007 100644 --- a/src/doc/tarpl/vec-drain.md +++ b/src/doc/tarpl/vec-drain.md @@ -2,7 +2,7 @@ Let's move on to Drain. Drain is largely the same as IntoIter, except that instead of consuming the Vec, it borrows the Vec and leaves its allocation -free. For now we'll only implement the "basic" full-range version. +untouched. For now we'll only implement the "basic" full-range version. ```rust,ignore use std::marker::PhantomData; @@ -38,6 +38,9 @@ impl RawValIter { RawValIter { start: slice.as_ptr(), end: if slice.len() == 0 { + // if `len = 0`, then this is not actually allocated memory. + // Need to avoid offsetting because that will give wrong + // information to LLVM via GEP. slice.as_ptr() } else { slice.as_ptr().offset(slice.len() as isize) @@ -137,5 +140,7 @@ impl Vec { } ``` +For more details on the `mem::forget` problem, see the +[section on leaks][leaks]. - +[leaks]: leaking.html diff --git a/src/doc/tarpl/vec-insert-remove.md b/src/doc/tarpl/vec-insert-remove.md index f21ed227d84c..6f88a77b32a7 100644 --- a/src/doc/tarpl/vec-insert-remove.md +++ b/src/doc/tarpl/vec-insert-remove.md @@ -1,12 +1,13 @@ % Insert and Remove -Something *not* provided but slice is `insert` and `remove`, so let's do those next. +Something *not* provided by slice is `insert` and `remove`, so let's do those +next. Insert needs to shift all the elements at the target index to the right by one. To do this we need to use `ptr::copy`, which is our version of C's `memmove`. -This copies some chunk of memory from one location to another, correctly handling -the case where the source and destination overlap (which will definitely happen -here). +This copies some chunk of memory from one location to another, correctly +handling the case where the source and destination overlap (which will +definitely happen here). If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]` using the *old* len. diff --git a/src/doc/tarpl/vec-into-iter.md b/src/doc/tarpl/vec-into-iter.md index d21cf940fcc1..566cad75b512 100644 --- a/src/doc/tarpl/vec-into-iter.md +++ b/src/doc/tarpl/vec-into-iter.md @@ -11,19 +11,20 @@ allocation. IntoIter needs to be DoubleEnded as well, to enable reading from both ends. Reading from the back could just be implemented as calling `pop`, but reading from the front is harder. We could call `remove(0)` but that would be insanely -expensive. Instead we're going to just use ptr::read to copy values out of either -end of the Vec without mutating the buffer at all. +expensive. Instead we're going to just use ptr::read to copy values out of +either end of the Vec without mutating the buffer at all. To do this we're going to use a very common C idiom for array iteration. We'll -make two pointers; one that points to the start of the array, and one that points -to one-element past the end. When we want an element from one end, we'll read out -the value pointed to at that end and move the pointer over by one. When the two -pointers are equal, we know we're done. +make two pointers; one that points to the start of the array, and one that +points to one-element past the end. When we want an element from one end, we'll +read out the value pointed to at that end and move the pointer over by one. When +the two pointers are equal, we know we're done. Note that the order of read and offset are reversed for `next` and `next_back` For `next_back` the pointer is always *after* the element it wants to read next, while for `next` the pointer is always *at* the element it wants to read next. -To see why this is, consider the case where every element but one has been yielded. +To see why this is, consider the case where every element but one has been +yielded. The array looks like this: @@ -35,6 +36,10 @@ The array looks like this: If E pointed directly at the element it wanted to yield next, it would be indistinguishable from the case where there are no more elements to yield. +Although we don't actually care about it during iteration, we also need to hold +onto the Vec's allocation information in order to free it once IntoIter is +dropped. + So we're going to use the following struct: ```rust,ignore @@ -46,8 +51,8 @@ struct IntoIter { } ``` -One last subtle detail: if our Vec is empty, we want to produce an empty iterator. -This will actually technically fall out doing the naive thing of: +One last subtle detail: if our Vec is empty, we want to produce an empty +iterator. This will actually technically fall out doing the naive thing of: ```text start = ptr @@ -155,139 +160,3 @@ impl Drop for IntoIter { } } ``` - -We've actually reached an interesting situation here: we've duplicated the logic -for specifying a buffer and freeing its memory. Now that we've implemented it and -identified *actual* logic duplication, this is a good time to perform some logic -compression. - -We're going to abstract out the `(ptr, cap)` pair and give them the logic for -allocating, growing, and freeing: - -```rust,ignore - -struct RawVec { - ptr: Unique, - cap: usize, -} - -impl RawVec { - fn new() -> Self { - assert!(mem::size_of::() != 0, "TODO: implement ZST support"); - unsafe { - RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: 0 } - } - } - - // unchanged from Vec - fn grow(&mut self) { - unsafe { - let align = mem::align_of::(); - let elem_size = mem::size_of::(); - - let (new_cap, ptr) = if self.cap == 0 { - let ptr = heap::allocate(elem_size, align); - (1, ptr) - } else { - let new_cap = 2 * self.cap; - let ptr = heap::reallocate(*self.ptr as *mut _, - self.cap * elem_size, - new_cap * elem_size, - align); - (new_cap, ptr) - }; - - // If allocate or reallocate fail, we'll get `null` back - if ptr.is_null() { oom() } - - self.ptr = Unique::new(ptr as *mut _); - self.cap = new_cap; - } - } -} - - -impl Drop for RawVec { - fn drop(&mut self) { - if self.cap != 0 { - let align = mem::align_of::(); - let elem_size = mem::size_of::(); - let num_bytes = elem_size * self.cap; - unsafe { - heap::deallocate(*self.ptr as *mut _, num_bytes, align); - } - } - } -} -``` - -And change vec as follows: - -```rust,ignore -pub struct Vec { - buf: RawVec, - len: usize, -} - -impl Vec { - fn ptr(&self) -> *mut T { *self.buf.ptr } - - fn cap(&self) -> usize { self.buf.cap } - - pub fn new() -> Self { - Vec { buf: RawVec::new(), len: 0 } - } - - // push/pop/insert/remove largely unchanged: - // * `self.ptr -> self.ptr()` - // * `self.cap -> self.cap()` - // * `self.grow -> self.buf.grow()` -} - -impl Drop for Vec { - fn drop(&mut self) { - while let Some(_) = self.pop() {} - // deallocation is handled by RawVec - } -} -``` - -And finally we can really simplify IntoIter: - -```rust,ignore -struct IntoIter { - _buf: RawVec, // we don't actually care about this. Just need it to live. - start: *const T, - end: *const T, -} - -// next and next_back literally unchanged since they never referred to the buf - -impl Drop for IntoIter { - fn drop(&mut self) { - // only need to ensure all our elements are read; - // buffer will clean itself up afterwards. - for _ in &mut *self {} - } -} - -impl Vec { - pub fn into_iter(self) -> IntoIter { - unsafe { - // need to use ptr::read to unsafely move the buf out since it's - // not Copy. - let buf = ptr::read(&self.buf); - let len = self.len; - mem::forget(self); - - IntoIter { - start: *buf.ptr, - end: buf.ptr.offset(len as isize), - _buf: buf, - } - } - } -} -``` - -Much better. diff --git a/src/doc/tarpl/vec-layout.md b/src/doc/tarpl/vec-layout.md index 128ad15f7950..4e440846ec7d 100644 --- a/src/doc/tarpl/vec-layout.md +++ b/src/doc/tarpl/vec-layout.md @@ -13,15 +13,15 @@ pub struct Vec { # fn main() {} ``` -And indeed this would compile. Unfortunately, it would be incorrect. The compiler -will give us too strict variance, so e.g. an `&Vec<&'static str>` couldn't be used -where an `&Vec<&'a str>` was expected. More importantly, it will give incorrect -ownership information to dropck, as it will conservatively assume we don't own -any values of type `T`. See [the chapter on ownership and lifetimes] -(lifetimes.html) for details. +And indeed this would compile. Unfortunately, it would be incorrect. The +compiler will give us too strict variance, so e.g. an `&Vec<&'static str>` +couldn't be used where an `&Vec<&'a str>` was expected. More importantly, it +will give incorrect ownership information to dropck, as it will conservatively +assume we don't own any values of type `T`. See [the chapter on ownership and +lifetimes] (lifetimes.html) for details. -As we saw in the lifetimes chapter, we should use `Unique` in place of `*mut T` -when we have a raw pointer to an allocation we own: +As we saw in the lifetimes chapter, we should use `Unique` in place of +`*mut T` when we have a raw pointer to an allocation we own: ```rust @@ -40,9 +40,10 @@ pub struct Vec { As a recap, Unique is a wrapper around a raw pointer that declares that: -* We own at least one value of type `T` +* We may own a value of type `T` * We are Send/Sync iff `T` is Send/Sync -* Our pointer is never null (and therefore `Option` is null-pointer-optimized) +* Our pointer is never null (and therefore `Option` is + null-pointer-optimized) That last point is subtle. First, it makes `Unique::new` unsafe to call, because putting `null` inside of it is Undefined Behaviour. It also throws a diff --git a/src/doc/tarpl/vec-raw.md b/src/doc/tarpl/vec-raw.md new file mode 100644 index 000000000000..40de0196f29a --- /dev/null +++ b/src/doc/tarpl/vec-raw.md @@ -0,0 +1,136 @@ +% RawVec + +We've actually reached an interesting situation here: we've duplicated the logic +for specifying a buffer and freeing its memory. Now that we've implemented it +and identified *actual* logic duplication, this is a good time to perform some +logic compression. + +We're going to abstract out the `(ptr, cap)` pair and give them the logic for +allocating, growing, and freeing: + +```rust,ignore +struct RawVec { + ptr: Unique, + cap: usize, +} + +impl RawVec { + fn new() -> Self { + assert!(mem::size_of::() != 0, "TODO: implement ZST support"); + unsafe { + RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: 0 } + } + } + + // unchanged from Vec + fn grow(&mut self) { + unsafe { + let align = mem::align_of::(); + let elem_size = mem::size_of::(); + + let (new_cap, ptr) = if self.cap == 0 { + let ptr = heap::allocate(elem_size, align); + (1, ptr) + } else { + let new_cap = 2 * self.cap; + let ptr = heap::reallocate(*self.ptr as *mut _, + self.cap * elem_size, + new_cap * elem_size, + align); + (new_cap, ptr) + }; + + // If allocate or reallocate fail, we'll get `null` back + if ptr.is_null() { oom() } + + self.ptr = Unique::new(ptr as *mut _); + self.cap = new_cap; + } + } +} + + +impl Drop for RawVec { + fn drop(&mut self) { + if self.cap != 0 { + let align = mem::align_of::(); + let elem_size = mem::size_of::(); + let num_bytes = elem_size * self.cap; + unsafe { + heap::deallocate(*self.ptr as *mut _, num_bytes, align); + } + } + } +} +``` + +And change vec as follows: + +```rust,ignore +pub struct Vec { + buf: RawVec, + len: usize, +} + +impl Vec { + fn ptr(&self) -> *mut T { *self.buf.ptr } + + fn cap(&self) -> usize { self.buf.cap } + + pub fn new() -> Self { + Vec { buf: RawVec::new(), len: 0 } + } + + // push/pop/insert/remove largely unchanged: + // * `self.ptr -> self.ptr()` + // * `self.cap -> self.cap()` + // * `self.grow -> self.buf.grow()` +} + +impl Drop for Vec { + fn drop(&mut self) { + while let Some(_) = self.pop() {} + // deallocation is handled by RawVec + } +} +``` + +And finally we can really simplify IntoIter: + +```rust,ignore +struct IntoIter { + _buf: RawVec, // we don't actually care about this. Just need it to live. + start: *const T, + end: *const T, +} + +// next and next_back literally unchanged since they never referred to the buf + +impl Drop for IntoIter { + fn drop(&mut self) { + // only need to ensure all our elements are read; + // buffer will clean itself up afterwards. + for _ in &mut *self {} + } +} + +impl Vec { + pub fn into_iter(self) -> IntoIter { + unsafe { + // need to use ptr::read to unsafely move the buf out since it's + // not Copy, and Vec implements Drop (so we can't destructure it). + let buf = ptr::read(&self.buf); + let len = self.len; + mem::forget(self); + + IntoIter { + start: *buf.ptr, + end: buf.ptr.offset(len as isize), + _buf: buf, + } + } + } +} +``` + +Much better. From 99043dde9dd2d0507ad2e3cda65b9d3e9244f13f Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Jul 2015 11:36:26 -0700 Subject: [PATCH 085/104] mention void pointers --- src/doc/tarpl/exotic-sizes.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/doc/tarpl/exotic-sizes.md b/src/doc/tarpl/exotic-sizes.md index d4df9492da77..68ce061d8c8b 100644 --- a/src/doc/tarpl/exotic-sizes.md +++ b/src/doc/tarpl/exotic-sizes.md @@ -95,10 +95,9 @@ actually possible to communicate this at the type level by returning a knowing that it's *statically impossible* for this value to be an `Err`, as this would require providing a value of type Void. -In principle, Rust can do some interesting analysees and optimizations based +In principle, Rust can do some interesting analyses and optimizations based on this fact. For instance, `Result` could be represented as just `T`, -because the Err case doesn't actually exist. Also in principle the following -could compile: +because the Err case doesn't actually exist. The following *could* also compile: ```rust,ignore enum Void {} @@ -111,3 +110,9 @@ let Ok(num) = res; But neither of these tricks work today, so all Void types get you today is the ability to be confident that certain situations are statically impossible. + +One final subtle detail about empty types is that raw pointers to them are +actually valid to construct, but dereferencing them is Undefined Behaviour +because that doesn't actually make sense. That is, you could model C's `void *` +type with `*const Void`, but this doesn't necessarily gain anything over using +e.g. `*const ()`, which *is* safe to randomly dereference. From 7a47ffcbc73fa3bd02429c92841dcb0792a1f9b8 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Jul 2015 11:37:15 -0700 Subject: [PATCH 086/104] UB is src bzns --- src/doc/tarpl/vec-into-iter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/tarpl/vec-into-iter.md b/src/doc/tarpl/vec-into-iter.md index 566cad75b512..0ffc23c45233 100644 --- a/src/doc/tarpl/vec-into-iter.md +++ b/src/doc/tarpl/vec-into-iter.md @@ -63,7 +63,7 @@ However because `offset` is marked as a GEP inbounds instruction, this will tell LLVM that ptr is allocated and won't alias other allocated memory. This is fine for zero-sized types, as they can't alias anything. However if we're using `heap::EMPTY` as a sentinel for a non-allocation for a *non-zero-sized* type, -this can cause undefined behaviour. Alas, we must therefore special case either +this can cause Undefined Behaviour. Alas, we must therefore special case either cap or len being 0 to not do the offset. So this is what we end up with for initialization: From 0a36ea7db130dfaa6012d76ccf80b9b77e15796b Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Jul 2015 15:32:52 -0700 Subject: [PATCH 087/104] get into the weeds over GEP and allocations --- src/doc/tarpl/vec-alloc.md | 154 ++++++++++++++++++++++++++++++------ src/doc/tarpl/vec-layout.md | 95 ++++++++++++++-------- src/doc/tarpl/vec.md | 16 +++- 3 files changed, 208 insertions(+), 57 deletions(-) diff --git a/src/doc/tarpl/vec-alloc.md b/src/doc/tarpl/vec-alloc.md index 14b9b462afc6..6f98220ebc97 100644 --- a/src/doc/tarpl/vec-alloc.md +++ b/src/doc/tarpl/vec-alloc.md @@ -1,5 +1,22 @@ % Allocating Memory +Using Unique throws a wrench in an important feature of Vec (and indeed all of +the std collections): an empty Vec doesn't actually allocate at all. So if we +can't allocate, but also can't put a null pointer in `ptr`, what do we do in +`Vec::new`? Well, we just put some other garbage in there! + +This is perfectly fine because we already have `cap == 0` as our sentinel for no +allocation. We don't even need to handle it specially in almost any code because +we usually need to check if `cap > len` or `len > 0` anyway. The traditional +Rust value to put here is `0x01`. The standard library actually exposes this +as `std::rt::heap::EMPTY`. There are quite a few places where we'll +want to use `heap::EMPTY` because there's no real allocation to talk about but +`null` would make the compiler do bad things. + +All of the `heap` API is totally unstable under the `heap_api` feature, though. +We could trivially define `heap::EMPTY` ourselves, but we'll want the rest of +the `heap` API anyway, so let's just get that dependency over with. + So: ```rust,ignore @@ -24,15 +41,29 @@ I slipped in that assert there because zero-sized types will require some special handling throughout our code, and I want to defer the issue for now. Without this assert, some of our early drafts will do some Very Bad Things. -Next we need to figure out what to actually do when we *do* want space. For that, -we'll need to use the rest of the heap APIs. These basically allow us to -talk directly to Rust's instance of jemalloc. +Next we need to figure out what to actually do when we *do* want space. For +that, we'll need to use the rest of the heap APIs. These basically allow us to +talk directly to Rust's allocator (jemalloc by default). -We'll also need a way to handle out-of-memory conditions. The standard library -calls the `abort` intrinsic, but calling intrinsics from normal Rust code is a -pretty bad idea. Unfortunately, the `abort` exposed by the standard library -allocates. Not something we want to do during `oom`! Instead, we'll call -`std::process::exit`. +We'll also need a way to handle out-of-memory (OOM) conditions. The standard +library calls the `abort` intrinsic, which just calls an illegal instruction to +crash the whole program. The reason we abort and don't panic is because +unwinding can cause allocations to happen, and that seems like a bad thing to do +when your allocator just came back with "hey I don't have any more memory". + +Of course, this is a bit silly since most platforms don't actually run out of +memory in a conventional way. Your operating system will probably kill the +application by another means if you legitimately start using up all the memory. +The most likely way we'll trigger OOM is by just asking for ludicrous quantities +of memory at once (e.g. half the theoretical address space). As such it's +*probably* fine to panic and nothing bad will happen. Still, we're trying to be +like the standard library as much as possible, so we'll just kill the whole +program. + +We said we don't want to use intrinsics, so doing *exactly* what `std` does is +out. `std::rt::util::abort` actually exists, but it takes a message to print, +which will probably allocate. Also it's still unstable. Instead, we'll call +`std::process::exit` with some random number. ```rust fn oom() { @@ -51,29 +82,104 @@ else: cap *= 2 ``` -But Rust's only supported allocator API is so low level that we'll need to -do a fair bit of extra work, though. We also need to guard against some special -conditions that can occur with really large allocations. In particular, we index -into arrays using unsigned integers, but `ptr::offset` takes signed integers. This -means Bad Things will happen if we ever manage to grow to contain more than -`isize::MAX` elements. Thankfully, this isn't something we need to worry about -in most cases. +But Rust's only supported allocator API is so low level that we'll need to do a +fair bit of extra work. We also need to guard against some special +conditions that can occur with really large allocations or empty allocations. -On 64-bit targets we're artifically limited to only 48-bits, so we'll run out -of memory far before we reach that point. However on 32-bit targets, particularly -those with extensions to use more of the address space, it's theoretically possible -to successfully allocate more than `isize::MAX` bytes of memory. Still, we only -really need to worry about that if we're allocating elements that are a byte large. -Anything else will use up too much space. +In particular, `ptr::offset` will cause us *a lot* of trouble, because it has +the semantics of LLVM's GEP inbounds instruction. If you're fortunate enough to +not have dealt with this instruction, here's the basic story with GEP: alias +analysis, alias analysis, alias analysis. It's super important to an optimizing +compiler to be able to reason about data dependencies and aliasing. -However since this is a tutorial, we're not going to be particularly optimal here, -and just unconditionally check, rather than use clever platform-specific `cfg`s. +As a simple example, consider the following fragment of code: + +```rust +# let x = &mut 0; +# let y = &mut 0; +*x *= 7; +*y *= 3; +``` + +If the compiler can prove that `x` and `y` point to different locations in +memory, the two operations can in theory be executed in parallel (by e.g. +loading them into different registers and working on them independently). +However in *general* the compiler can't do this because if x and y point to +the same location in memory, the operations need to be done to the same value, +and they can't just be merged afterwards. + +When you use GEP inbounds, you are specifically telling LLVM that the offsets +you're about to do are within the bounds of a single allocated entity. The +ultimate payoff being that LLVM can assume that if two pointers are known to +point to two disjoint objects, all the offsets of those pointers are *also* +known to not alias (because you won't just end up in some random place in +memory). LLVM is heavily optimized to work with GEP offsets, and inbounds +offsets are the best of all, so it's important that we use them as much as +possible. + +So that's what GEP's about, how can it cause us trouble? + +The first problem is that we index into arrays with unsigned integers, but +GEP (and as a consequence `ptr::offset`) takes a *signed integer*. This means +that half of the seemingly valid indices into an array will overflow GEP and +actually go in the wrong direction! As such we must limit all allocations to +`isize::MAX` elements. This actually means we only need to worry about +byte-sized objects, because e.g. `> isize::MAX` `u16`s will truly exhaust all of +the system's memory. However in order to avoid subtle corner cases where someone +reinterprets some array of `< isize::MAX` objects as bytes, std limits all +allocations to `isize::MAX` bytes. + +On all 64-bit targets that Rust currently supports we're artificially limited +to significantly less than all 64 bits of the address space (modern x64 +platforms only expose 48-bit addressing), so we can rely on just running out of +memory first. However on 32-bit targets, particularly those with extensions to +use more of the address space (PAE x86 or x32), it's theoretically possible to +successfully allocate more than `isize::MAX` bytes of memory. + +However since this is a tutorial, we're not going to be particularly optimal +here, and just unconditionally check, rather than use clever platform-specific +`cfg`s. + +The other corner-case we need to worry about is *empty* allocations. There will +be two kinds of empty allocations we need to worry about: `cap = 0` for all T, +and `cap > 0` for zero-sized types. + +These cases are tricky because they come +down to what LLVM means by "allocated". LLVM's notion of an +allocation is significantly more abstract than how we usually use it. Because +LLVM needs to work with different languages' semantics and custom allocators, +it can't really intimately understand allocation. Instead, the main idea behind +allocation is "doesn't overlap with other stuff". That is, heap allocations, +stack allocations, and globals don't randomly overlap. Yep, it's about alias +analysis. As such, Rust can technically play a bit fast an loose with the notion of +an allocation as long as it's *consistent*. + +Getting back to the empty allocation case, there are a couple of places where +we want to offset by 0 as a consequence of generic code. The question is then: +is it consistent to do so? For zero-sized types, we have concluded that it is +indeed consistent to do a GEP inbounds offset by an arbitrary number of +elements. This is a runtime no-op because every element takes up no space, +and it's fine to pretend that there's infinite zero-sized types allocated +at `0x01`. No allocator will ever allocate that address, because they won't +allocate `0x00` and they generally allocate to some minimal alignment higher +than a byte. + +However what about for positive-sized types? That one's a bit trickier. In +principle, you can argue that offsetting by 0 gives LLVM no information: either +there's an element before the address, or after it, but it can't know which. +However we've chosen to conservatively assume that it may do bad things. As +such we *will* guard against this case explicitly. + +*Phew* + +Ok with all the nonsense out of the way, let's actually allocate some memory: ```rust,ignore fn grow(&mut self) { // this is all pretty delicate, so let's say it's all unsafe unsafe { - let align = mem::min_align_of::(); + // current API requires us to specify size and alignment manually. + let align = mem::align_of::(); let elem_size = mem::size_of::(); let (new_cap, ptr) = if self.cap == 0 { diff --git a/src/doc/tarpl/vec-layout.md b/src/doc/tarpl/vec-layout.md index 4e440846ec7d..bce9a2f22f4d 100644 --- a/src/doc/tarpl/vec-layout.md +++ b/src/doc/tarpl/vec-layout.md @@ -13,15 +13,64 @@ pub struct Vec { # fn main() {} ``` -And indeed this would compile. Unfortunately, it would be incorrect. The -compiler will give us too strict variance, so e.g. an `&Vec<&'static str>` +And indeed this would compile. Unfortunately, it would be incorrect. First, the +compiler will give us too strict variance. So a `&Vec<&'static str>` couldn't be used where an `&Vec<&'a str>` was expected. More importantly, it -will give incorrect ownership information to dropck, as it will conservatively -assume we don't own any values of type `T`. See [the chapter on ownership and -lifetimes] (lifetimes.html) for details. +will give incorrect ownership information to the drop checker, as it will +conservatively assume we don't own any values of type `T`. See [the chapter +on ownership and lifetimes][ownership] for all the details on variance and +drop check. -As we saw in the lifetimes chapter, we should use `Unique` in place of -`*mut T` when we have a raw pointer to an allocation we own: +As we saw in the ownership chapter, we should use `Unique` in place of +`*mut T` when we have a raw pointer to an allocation we own. Unique is unstable, +so we'd like to not use it if possible, though. + +As a recap, Unique is a wrapper around a raw pointer that declares that: + +* We are variant over `T` +* We may own a value of type `T` (for drop check) +* We are Send/Sync if `T` is Send/Sync +* We deref to `*mut T` (so it largely acts like a `*mut` in our code) +* Our pointer is never null (so `Option>` is null-pointer-optimized) + +We can implement all of the above requirements except for the last +one in stable Rust: + +```rust +use std::marker::PhantomData; +use std::ops::Deref; +use std::mem; + +struct Unique { + ptr: *const T, // *const for variance + _marker: PhantomData, // For the drop checker +} + +// Deriving Send and Sync is safe because we are the Unique owners +// of this data. It's like Unique is "just" T. +unsafe impl Send for Unique {} +unsafe impl Sync for Unique {} + +impl Unique { + pub fn new(ptr: *mut T) -> Self { + Unique { ptr: ptr, _marker: PhantomData } + } +} + +impl Deref for Unique { + type Target = *mut T; + fn deref(&self) -> &*mut T { + // There's no way to cast the *const to a *mut + // while also taking a reference. So we just + // transmute it since it's all "just pointers". + unsafe { mem::transmute(&self.ptr) } + } +} +``` + +Unfortunately the mechanism for stating that your value is non-zero is +unstable and unlikely to be stabilized soon. As such we're just going to +take the hit and use std's Unique: ```rust @@ -38,29 +87,11 @@ pub struct Vec { # fn main() {} ``` -As a recap, Unique is a wrapper around a raw pointer that declares that: - -* We may own a value of type `T` -* We are Send/Sync iff `T` is Send/Sync -* Our pointer is never null (and therefore `Option` is - null-pointer-optimized) - -That last point is subtle. First, it makes `Unique::new` unsafe to call, because -putting `null` inside of it is Undefined Behaviour. It also throws a -wrench in an important feature of Vec (and indeed all of the std collections): -an empty Vec doesn't actually allocate at all. So if we can't allocate, -but also can't put a null pointer in `ptr`, what do we do in -`Vec::new`? Well, we just put some other garbage in there! - -This is perfectly fine because we already have `cap == 0` as our sentinel for no -allocation. We don't even need to handle it specially in almost any code because -we usually need to check if `cap > len` or `len > 0` anyway. The traditional -Rust value to put here is `0x01`. The standard library actually exposes this -as `std::rt::heap::EMPTY`. There are quite a few places where we'll want to use -`heap::EMPTY` because there's no real allocation to talk about but `null` would -make the compiler angry. - -All of the `heap` API is totally unstable under the `heap_api` feature, though. -We could trivially define `heap::EMPTY` ourselves, but we'll want the rest of -the `heap` API anyway, so let's just get that dependency over with. +If you don't care about the null-pointer optimization, then you can use the +stable code. However we will be designing the rest of the code around enabling +the optimization. In particular, `Unique::new` is unsafe to call, because +putting `null` inside of it is Undefined Behaviour. Our stable Unique doesn't +need `new` to be unsafe because it doesn't make any interesting guarantees about +its contents. +[ownership]: ownership.html diff --git a/src/doc/tarpl/vec.md b/src/doc/tarpl/vec.md index a613f259b70f..39d9686ccac7 100644 --- a/src/doc/tarpl/vec.md +++ b/src/doc/tarpl/vec.md @@ -2,5 +2,19 @@ To bring everything together, we're going to write `std::Vec` from scratch. Because all the best tools for writing unsafe code are unstable, this -project will only work on nightly (as of Rust 1.2.0). +project will only work on nightly (as of Rust 1.2.0). With the exception of the +allocator API, much of the unstable code we'll use is expected to be stabilized +in a similar form as it is today. +However we will generally try to avoid unstable code where possible. In +particular we won't use any intrinsics that could make a code a little +bit nicer or efficient because intrinsics are permanently unstable. Although +many intrinsics *do* become stabilized elsewhere (`std::ptr` and `str::mem` +consist of many intrinsics). + +Ultimately this means out implementation may not take advantage of all +possible optimizations, though it will be by no means *naive*. We will +definitely get into the weeds over nitty-gritty details, even +when the problem doesn't *really* merit it. + +You wanted advanced. We're gonna go advanced. From 06ded9c04e23ceaa41a4a5d01dd54432aaafd0db Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Jul 2015 15:35:33 -0700 Subject: [PATCH 088/104] explain phantom --- src/doc/tarpl/vec-drain.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doc/tarpl/vec-drain.md b/src/doc/tarpl/vec-drain.md index b6b282666007..23671978369a 100644 --- a/src/doc/tarpl/vec-drain.md +++ b/src/doc/tarpl/vec-drain.md @@ -8,6 +8,9 @@ untouched. For now we'll only implement the "basic" full-range version. use std::marker::PhantomData; struct Drain<'a, T: 'a> { + // Need to bound the lifetime here, so we do it with `&'a mut Vec` + // because that's semantically what we contain. We're "just" calling + // `pop()` and `remove(0)`. vec: PhantomData<&'a mut Vec> start: *const T, end: *const T, From 14bc45477085222dcf2b87bef75ca3e7d0b5274a Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Jul 2015 15:36:50 -0700 Subject: [PATCH 089/104] remove redundant explanation --- src/doc/tarpl/vec-into-iter.md | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/doc/tarpl/vec-into-iter.md b/src/doc/tarpl/vec-into-iter.md index 0ffc23c45233..a9c1917feb9c 100644 --- a/src/doc/tarpl/vec-into-iter.md +++ b/src/doc/tarpl/vec-into-iter.md @@ -51,22 +51,7 @@ struct IntoIter { } ``` -One last subtle detail: if our Vec is empty, we want to produce an empty -iterator. This will actually technically fall out doing the naive thing of: - -```text -start = ptr -end = ptr.offset(len) -``` - -However because `offset` is marked as a GEP inbounds instruction, this will tell -LLVM that ptr is allocated and won't alias other allocated memory. This is fine -for zero-sized types, as they can't alias anything. However if we're using -`heap::EMPTY` as a sentinel for a non-allocation for a *non-zero-sized* type, -this can cause Undefined Behaviour. Alas, we must therefore special case either -cap or len being 0 to not do the offset. - -So this is what we end up with for initialization: +And this is what we end up with for initialization: ```rust,ignore impl Vec { From 5f02de3c226bce60c58ce2bc436e69c55b90a616 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Jul 2015 15:50:47 -0700 Subject: [PATCH 090/104] clarify casts are checked at compile time --- src/doc/tarpl/casts.md | 4 +++- src/doc/tarpl/repr-rust.md | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/doc/tarpl/casts.md b/src/doc/tarpl/casts.md index 37f84ead7974..a5527b250755 100644 --- a/src/doc/tarpl/casts.md +++ b/src/doc/tarpl/casts.md @@ -9,7 +9,9 @@ using the `as` keyword: `expr as Type`. True casts generally revolve around raw pointers and the primitive numeric types. Even though they're dangerous, these casts are *infallible* at runtime. If a cast triggers some subtle corner case no indication will be given that -this occurred. The cast will simply succeed. +this occurred. The cast will simply succeed. That said, casts must be valid +at the type level, or else they will be prevented statically. For instance, +`7u8 as bool` will not compile. That said, casts aren't `unsafe` because they generally can't violate memory safety *on their own*. For instance, converting an integer to a raw pointer can diff --git a/src/doc/tarpl/repr-rust.md b/src/doc/tarpl/repr-rust.md index b3a5a1278c78..f7ed15f1e870 100644 --- a/src/doc/tarpl/repr-rust.md +++ b/src/doc/tarpl/repr-rust.md @@ -12,7 +12,11 @@ An enum is said to be *C-like* if none of its variants have associated data. For all these, individual fields are aligned to their preferred alignment. For primitives this is usually equal to their size. For instance, a u32 will be aligned to a multiple of 32 bits, and a u16 will be aligned to a multiple of 16 -bits. Composite structures will have a preferred alignment equal to the maximum +bits. Note that some primitives may be emulated on different platforms, and as +such may have strange alignment. For instance, a u64 on x86 may actually be +emulated as a pair of u32s, and thus only have 32-bit alignment. + +Composite structures will have a preferred alignment equal to the maximum of their fields' preferred alignment, and a size equal to a multiple of their preferred alignment. This ensures that arrays of T can be correctly iterated by offsetting by their size. So for instance, From 3f8e029bedba23b8b2d174fac2718f970a396676 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 20 Jul 2015 16:18:52 -0700 Subject: [PATCH 091/104] remove subtyping from coercions, it's something else --- src/doc/tarpl/coercions.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/doc/tarpl/coercions.md b/src/doc/tarpl/coercions.md index 0eb03d271c45..8bb82843ba0d 100644 --- a/src/doc/tarpl/coercions.md +++ b/src/doc/tarpl/coercions.md @@ -1,16 +1,16 @@ % Coercions Types can implicitly be coerced to change in certain contexts. These changes are -generally just *weakening* of types, largely focused around pointers and lifetimes. -They mostly exist to make Rust "just work" in more cases, and are largely harmless. +generally just *weakening* of types, largely focused around pointers and +lifetimes. They mostly exist to make Rust "just work" in more cases, and are +largely harmless. Here's all the kinds of coercion: - Coercion is allowed between the following types: -* Subtyping: `T` to `U` if `T` is a [subtype][] of `U` -* Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` +* Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to + `T_3` * Pointer Weakening: * `&mut T` to `&T` * `*mut T` to `*const T` @@ -68,5 +68,3 @@ fn main() { :10 foo(t); ^~~ ``` - -[subtype]: subtyping.html From f54c5ad5660e81972b772be1c8852e1ef2969f28 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 24 Jul 2015 10:02:16 -0700 Subject: [PATCH 092/104] fix accident --- src/doc/tarpl/references.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/tarpl/references.md b/src/doc/tarpl/references.md index 993e2a52aebf..a109bf5d012f 100644 --- a/src/doc/tarpl/references.md +++ b/src/doc/tarpl/references.md @@ -2,7 +2,8 @@ There are two kinds of reference: -* Shared reference: `&` Mutable reference: `&mut` +* Shared reference: `&` +* Mutable reference: `&mut` Which obey the following rules: From 36a8b94464dd0cc7763fe3fb2fe9a3fbed273d06 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sun, 26 Jul 2015 18:12:36 -0700 Subject: [PATCH 093/104] expand lifetime splitting to show IterMut is totally safe --- src/doc/tarpl/lifetime-splitting.md | 243 ++++++++++++++++++++++------ 1 file changed, 192 insertions(+), 51 deletions(-) diff --git a/src/doc/tarpl/lifetime-splitting.md b/src/doc/tarpl/lifetime-splitting.md index 7ab2d379ffd5..9b6b769520fa 100644 --- a/src/doc/tarpl/lifetime-splitting.md +++ b/src/doc/tarpl/lifetime-splitting.md @@ -1,10 +1,10 @@ % Splitting Lifetimes The mutual exclusion property of mutable references can be very limiting when -working with a composite structure. The borrow checker understands some basic stuff, but -will fall over pretty easily. It *does* understand structs sufficiently to -know that it's possible to borrow disjoint fields of a struct simultaneously. -So this works today: +working with a composite structure. The borrow checker understands some basic +stuff, but will fall over pretty easily. It *does* understand structs +sufficiently to know that it's possible to borrow disjoint fields of a struct +simultaneously. So this works today: ```rust struct Foo { @@ -49,11 +49,11 @@ container types like a tree, especially if distinct keys actually *do* map to the same value. In order to "teach" borrowck that what we're doing is ok, we need to drop down -to unsafe code. For instance, mutable slices expose a `split_at_mut` function that -consumes the slice and returns *two* mutable slices. One for everything to the -left of the index, and one for everything to the right. Intuitively we know this -is safe because the slices don't alias. However the implementation requires some -unsafety: +to unsafe code. For instance, mutable slices expose a `split_at_mut` function +that consumes the slice and returns *two* mutable slices. One for everything to +the left of the index, and one for everything to the right. Intuitively we know +this is safe because the slices don't alias. However the implementation requires +some unsafety: ```rust,ignore fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { @@ -66,9 +66,9 @@ fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { } ``` -This is pretty plainly dangerous. We use transmute to duplicate the slice with an -*unbounded* lifetime, so that it can be treated as disjoint from the other until -we unify them when we return. +This is pretty plainly dangerous. We use transmute to duplicate the slice with +an *unbounded* lifetime, so that it can be treated as disjoint from the other +until we unify them when we return. However more subtle is how iterators that yield mutable references work. The iterator trait is defined as follows: @@ -81,60 +81,201 @@ trait Iterator { } ``` -Given this definition, Self::Item has *no* connection to `self`. This means -that we can call `next` several times in a row, and hold onto all the results -*concurrently*. This is perfectly fine for by-value iterators, which have exactly -these semantics. It's also actually fine for shared references, as they admit -arbitrarily many references to the same thing (although the -iterator needs to be a separate object from the thing being shared). But mutable -references make this a mess. At first glance, they might seem completely -incompatible with this API, as it would produce multiple mutable references to -the same object! +Given this definition, Self::Item has *no* connection to `self`. This means that +we can call `next` several times in a row, and hold onto all the results +*concurrently*. This is perfectly fine for by-value iterators, which have +exactly these semantics. It's also actually fine for shared references, as they +admit arbitrarily many references to the same thing (although the iterator needs +to be a separate object from the thing being shared). + +But mutable references make this a mess. At first glance, they might seem +completely incompatible with this API, as it would produce multiple mutable +references to the same object! However it actually *does* work, exactly because iterators are one-shot objects. -Everything an IterMut yields will be yielded *at most* once, so we don't *actually* -ever yield multiple mutable references to the same piece of data. +Everything an IterMut yields will be yielded *at most* once, so we don't +*actually* ever yield multiple mutable references to the same piece of data. -In general all mutable iterators require *some* unsafe code *somewhere*, though. -Whether it's raw pointers, or safely composing on top of *another* IterMut. +Perhaps surprisingly, mutable iterators *don't* require unsafe code to be +implemented for many types! -For instance, VecDeque's IterMut: +For instance here's a singly linked list: -```rust,ignore -struct IterMut<'a, T:'a> { - // The whole backing array. Some of these indices are initialized! - ring: &'a mut [T], - tail: usize, - head: usize, +```rust +# fn main() {} +type Link = Option>>; + +struct Node { + elem: T, + next: Link, +} + +pub struct LinkedList { + head: Link, +} + +pub struct IterMut<'a, T: 'a>(Option<&'a mut Node>); + +impl LinkedList { + fn iter_mut(&mut self) -> IterMut { + IterMut(self.head.as_mut().map(|node| &mut **node)) + } } impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; - fn next(&mut self) -> Option<&'a mut T> { - if self.tail == self.head { - return None; + fn next(&mut self) -> Option { + self.0.take().map(|node| { + self.0 = node.next.as_mut().map(|node| &mut **node); + &mut node.elem + }) + } +} +``` + +Here's a mutable slice: + +```rust +use std::mem; + +pub struct IterMut<'a, T: 'a>(&'a mut[T]); + +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + fn next(&mut self) -> Option { + let slice = mem::replace(&mut self.0, &mut []); + if slice.is_empty() { return None; } + + let (l, r) = slice.split_at_mut(1); + self.0 = r; + l.get_mut(0) + } +} + +impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { + fn next_back(&mut self) -> Option { + let slice = mem::replace(&mut self.0, &mut []); + if slice.is_empty() { return None; } + + let new_len = slice.len() - 1; + let (l, r) = slice.split_at_mut(new_len); + self.0 = l; + r.get_mut(0) + } +} +``` + +And here's a binary tree: + +```rust +use std::collections::VecDeque; + +type Link = Option>>; + +struct Node { + elem: T, + left: Link, + right: Link, +} + +pub struct Tree { + root: Link, +} + +struct NodeIterMut<'a, T: 'a> { + elem: Option<&'a mut T>, + left: Option<&'a mut Node>, + right: Option<&'a mut Node>, +} + +enum State<'a, T: 'a> { + Elem(&'a mut T), + Node(&'a mut Node), +} + +pub struct IterMut<'a, T: 'a>(VecDeque>); + +impl Tree { + pub fn iter_mut(&mut self) -> IterMut { + let mut deque = VecDeque::new(); + self.root.as_mut().map(|root| deque.push_front(root.iter_mut())); + IterMut(deque) + } +} + +impl Node { + pub fn iter_mut(&mut self) -> NodeIterMut { + NodeIterMut { + elem: Some(&mut self.elem), + left: self.left.as_mut().map(|node| &mut **node), + right: self.right.as_mut().map(|node| &mut **node), } - let tail = self.tail; - self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); + } +} - unsafe { - // might as well do unchecked indexing since wrap_index has us - // in-bounds, and many of the "middle" indices are uninitialized - // anyway. - let elem = self.ring.get_unchecked_mut(tail); - // round-trip through a raw pointer to unbound the lifetime from - // ourselves - Some(&mut *(elem as *mut _)) +impl<'a, T> Iterator for NodeIterMut<'a, T> { + type Item = State<'a, T>; + + fn next(&mut self) -> Option { + match self.left.take() { + Some(node) => Some(State::Node(node)), + None => match self.elem.take() { + Some(elem) => Some(State::Elem(elem)), + None => match self.right.take() { + Some(node) => Some(State::Node(node)), + None => None, + } + } + } + } +} + +impl<'a, T> DoubleEndedIterator for NodeIterMut<'a, T> { + fn next_back(&mut self) -> Option { + match self.right.take() { + Some(node) => Some(State::Node(node)), + None => match self.elem.take() { + Some(elem) => Some(State::Elem(elem)), + None => match self.left.take() { + Some(node) => Some(State::Node(node)), + None => None, + } + } + } + } +} + +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + fn next(&mut self) -> Option { + loop { + match self.0.front_mut().and_then(|node_it| node_it.next()) { + Some(State::Elem(elem)) => return Some(elem), + Some(State::Node(node)) => self.0.push_front(node.iter_mut()), + None => if let None = self.0.pop_front() { return None }, + } + } + } +} + +impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { + fn next(&mut self) -> Option { + loop { + match self.0.back_mut().and_then(|node_it| node_it.next_back()) { + Some(State::Elem(elem)) => return Some(elem), + Some(State::Node(node)) => self.0.push_back(node.iter_mut()), + None => if let None = self.0.pop_back() { return None }, + } } } } ``` -A very subtle but interesting detail in this design is that it *relies on -privacy to be sound*. Borrowck works on some very simple rules. One of those rules -is that if we have a live &mut Foo and Foo contains an &mut Bar, then that &mut -Bar is *also* live. Since IterMut is always live when `next` can be called, if -`ring` were public then we could mutate `ring` while outstanding mutable borrows -to it exist! +All of these are completely safe and work on stable Rust! This ultimately +falls out of the simple struct case we saw before: Rust understands that you +can safely split a mutable reference into subfields. We can then encode +permanently consuming a reference via Options (or in the case of slices, +replacing with an empty slice). From 8c7111da07f20422a6bd5243b56d302f0f02c3a5 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sun, 26 Jul 2015 18:19:50 -0700 Subject: [PATCH 094/104] fixup atomics --- src/doc/tarpl/atomics.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/tarpl/atomics.md b/src/doc/tarpl/atomics.md index 8395b22c8d8e..87378da7c523 100644 --- a/src/doc/tarpl/atomics.md +++ b/src/doc/tarpl/atomics.md @@ -85,12 +85,12 @@ x = 1; y *= 2; Ideally this program has 2 possible final states: -* `y = 3`: (thread 2 did the check before thread 1 completed) y = 6`: (thread 2 -* `did the check after thread 1 completed) +* `y = 3`: (thread 2 did the check before thread 1 completed) +* `y = 6`: (thread 2 did the check after thread 1 completed) However there's a third potential state that the hardware enables: -* `y = 2`: (thread 2 saw `x = 2`, but not `y = 3`, and then overwrote `y = 3`) +* `y = 2`: (thread 2 saw `x = 1`, but not `y = 3`, and then overwrote `y = 3`) It's worth noting that different kinds of CPU provide different guarantees. It is common to separate hardware into two categories: strongly-ordered and weakly- From b53406f8241edb45eb962795da99cb2cf73d8c1a Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 27 Jul 2015 14:40:54 -0700 Subject: [PATCH 095/104] fixups for aturon --- src/doc/tarpl/lifetimes.md | 4 +-- src/doc/tarpl/references.md | 62 ++++++++++++++++++++++++------------- src/doc/tarpl/subtyping.md | 2 +- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/doc/tarpl/lifetimes.md b/src/doc/tarpl/lifetimes.md index 350a4ead1309..f4475b738509 100644 --- a/src/doc/tarpl/lifetimes.md +++ b/src/doc/tarpl/lifetimes.md @@ -19,7 +19,7 @@ our toes with lifetimes, we're going to pretend that we're actually allowed to label scopes with lifetimes, and desugar the examples from the start of this chapter. -Our examples made use of *aggressive* sugar -- high fructose corn syrup even -- +Originally, our examples made use of *aggressive* sugar -- high fructose corn syrup even -- around scopes and lifetimes, because writing everything out explicitly is *extremely noisy*. All Rust code relies on aggressive inference and elision of "obvious" things. @@ -166,7 +166,7 @@ our implementation *just a bit*.) -# Example 2: aliasing a mutable reference +# Example: aliasing a mutable reference How about the other example: diff --git a/src/doc/tarpl/references.md b/src/doc/tarpl/references.md index a109bf5d012f..da70dd529078 100644 --- a/src/doc/tarpl/references.md +++ b/src/doc/tarpl/references.md @@ -1,5 +1,12 @@ % References +This section gives a high-level view of the memory model that *all* Rust +programs must satisfy to be correct. Safe code is statically verified +to obey this model by the borrow checker. Unsafe code may go above +and beyond the borrow checker while still satisfying this model. The borrow +checker may also be extended to allow more programs to compile, as long as +this more fundamental model is satisfied. + There are two kinds of reference: * Shared reference: `&` @@ -7,53 +14,63 @@ There are two kinds of reference: Which obey the following rules: -* A reference cannot outlive its referent A mutable reference cannot be aliased +* A reference cannot outlive its referent +* A mutable reference cannot be aliased -To define aliasing, we must define the notion of *paths* and *liveness*. +That's it. That's the whole model. Of course, we should probably define +what *aliased* means. To define aliasing, we must define the notion of +*paths* and *liveness*. # Paths -If all Rust had were values, then every value would be uniquely owned by a -variable or composite structure. From this we naturally derive a *tree* of -ownership. The stack itself is the root of the tree, with every variable as its -direct children. Each variable's direct children would be their fields (if any), -and so on. +If all Rust had were values (no pointers), then every value would be uniquely +owned by a variable or composite structure. From this we naturally derive a +*tree* of ownership. The stack itself is the root of the tree, with every +variable as its direct children. Each variable's direct children would be their +fields (if any), and so on. From this view, every value in Rust has a unique *path* in the tree of -ownership. References to a value can subsequently be interpreted as a path in -this tree. Of particular interest are *ancestors* and *descendants*: if `x` owns -`y`, then `x` is an *ancestor* of `y`, and `y` is a *descendant* of `x`. Note +ownership. Of particular interest are *ancestors* and *descendants*: if `x` owns +`y`, then `x` is an ancestor of `y`, and `y` is a descendant of `x`. Note that this is an inclusive relationship: `x` is a descendant and ancestor of itself. +We can then define references as simply *names* for paths. When you create a +reference, you're declaring that an ownership path exists to this address +of memory. + Tragically, plenty of data doesn't reside on the stack, and we must also accommodate this. Globals and thread-locals are simple enough to model as residing at the bottom of the stack (though we must be careful with mutable globals). Data on the heap poses a different problem. If all Rust had on the heap was data uniquely owned by a pointer on the stack, -then we can just treat that pointer as a struct that owns the value on the heap. -Box, Vec, String, and HashMap, are examples of types which uniquely own data on -the heap. +then we could just treat such a pointer as a struct that owns the value on the +heap. Box, Vec, String, and HashMap, are examples of types which uniquely +own data on the heap. Unfortunately, data on the heap is not *always* uniquely owned. Rc for instance -introduces a notion of *shared* ownership. Shared ownership means there is no -unique path. A value with no unique path limits what we can do with it. In -general, only shared references can be created to these values. However +introduces a notion of *shared* ownership. Shared ownership of a value means +there is no unique path to it. A value with no unique path limits what we can do +with it. + +In general, only shared references can be created to non-unique paths. However mechanisms which ensure mutual exclusion may establish One True Owner -temporarily, establishing a unique path to that value (and therefore all its -children). +temporarily, establishing a unique path to that value (and therefore all +its children). If this is done, the value may be mutated. In particular, a +mutable reference can be taken. The most common way to establish such a path is through *interior mutability*, in contrast to the *inherited mutability* that everything in Rust normally uses. Cell, RefCell, Mutex, and RWLock are all examples of interior mutability types. -These types provide exclusive access through runtime restrictions. However it is -also possible to establish unique ownership without interior mutability. For -instance, if an Rc has refcount 1, then it is safe to mutate or move its -internals. +These types provide exclusive access through runtime restrictions. + +An interesting case of this effect is Rc itself: if an Rc has refcount 1, +then it is safe to mutate or even move its internals. Note however that the +refcount itself uses interior mutability. In order to correctly communicate to the type system that a variable or field of a struct can have interior mutability, it must be wrapped in an UnsafeCell. This @@ -62,6 +79,7 @@ that value. You still must yourself ensure that mutual exclusion is upheld. + # Liveness Note: Liveness is not the same thing as a *lifetime*, which will be explained diff --git a/src/doc/tarpl/subtyping.md b/src/doc/tarpl/subtyping.md index 1b33c9abaa1b..8c5ac9cca6b3 100644 --- a/src/doc/tarpl/subtyping.md +++ b/src/doc/tarpl/subtyping.md @@ -100,7 +100,7 @@ subsequently be dropped, and `forever_str` would point to freed memory when we print it! Therefore `&mut` should be invariant. This is the general theme of variance vs invariance: if variance would allow you -to *store* a short-lived value over a longer-lived slot, then you must be +to store a short-lived value into a longer-lived slot, then you must be invariant. However it *is* sound for `&'a mut T` to be variant over `'a`. The key difference From fd13bdf626a50b5b21afbbe87806dc346f8ea9d7 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 27 Jul 2015 15:03:38 -0700 Subject: [PATCH 096/104] vec fixes for huonw --- src/doc/tarpl/vec-alloc.md | 11 +++++------ src/doc/tarpl/vec-drain.md | 3 ++- src/doc/tarpl/vec-layout.md | 7 +++++-- src/doc/tarpl/vec-raw.md | 8 ++++---- src/doc/tarpl/vec.md | 2 +- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/doc/tarpl/vec-alloc.md b/src/doc/tarpl/vec-alloc.md index 6f98220ebc97..93efbbbdf89a 100644 --- a/src/doc/tarpl/vec-alloc.md +++ b/src/doc/tarpl/vec-alloc.md @@ -61,9 +61,7 @@ like the standard library as much as possible, so we'll just kill the whole program. We said we don't want to use intrinsics, so doing *exactly* what `std` does is -out. `std::rt::util::abort` actually exists, but it takes a message to print, -which will probably allocate. Also it's still unstable. Instead, we'll call -`std::process::exit` with some random number. +out. Instead, we'll call `std::process::exit` with some random number. ```rust fn oom() { @@ -78,7 +76,7 @@ if cap == 0: allocate() cap = 1 else: - reallocate + reallocate() cap *= 2 ``` @@ -109,7 +107,7 @@ the same location in memory, the operations need to be done to the same value, and they can't just be merged afterwards. When you use GEP inbounds, you are specifically telling LLVM that the offsets -you're about to do are within the bounds of a single allocated entity. The +you're about to do are within the bounds of a single "allocated" entity. The ultimate payoff being that LLVM can assume that if two pointers are known to point to two disjoint objects, all the offsets of those pointers are *also* known to not alias (because you won't just end up in some random place in @@ -162,7 +160,8 @@ elements. This is a runtime no-op because every element takes up no space, and it's fine to pretend that there's infinite zero-sized types allocated at `0x01`. No allocator will ever allocate that address, because they won't allocate `0x00` and they generally allocate to some minimal alignment higher -than a byte. +than a byte. Also generally the whole first page of memory is +protected from being allocated anyway (a whole 4k, on many platforms). However what about for positive-sized types? That one's a bit trickier. In principle, you can argue that offsetting by 0 gives LLVM no information: either diff --git a/src/doc/tarpl/vec-drain.md b/src/doc/tarpl/vec-drain.md index 23671978369a..3be295f1adc2 100644 --- a/src/doc/tarpl/vec-drain.md +++ b/src/doc/tarpl/vec-drain.md @@ -83,6 +83,7 @@ impl Vec { pub fn into_iter(self) -> IntoIter { unsafe { let iter = RawValIter::new(&self); + let buf = ptr::read(&self.buf); mem::forget(self); @@ -112,7 +113,7 @@ pub struct Drain<'a, T: 'a> { impl<'a, T> Iterator for Drain<'a, T> { type Item = T; - fn next(&mut self) -> Option { self.iter.next_back() } + fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } diff --git a/src/doc/tarpl/vec-layout.md b/src/doc/tarpl/vec-layout.md index bce9a2f22f4d..325399d622b6 100644 --- a/src/doc/tarpl/vec-layout.md +++ b/src/doc/tarpl/vec-layout.md @@ -1,7 +1,10 @@ % Layout -First off, we need to come up with the struct layout. Naively we want this -design: +First off, we need to come up with the struct layout. A Vec has three parts: +a pointer to the allocation, the size of the allocation, and the number of +elements that have been initialized. + +Naively, this means we just want this design: ```rust pub struct Vec { diff --git a/src/doc/tarpl/vec-raw.md b/src/doc/tarpl/vec-raw.md index 40de0196f29a..8f78462cf402 100644 --- a/src/doc/tarpl/vec-raw.md +++ b/src/doc/tarpl/vec-raw.md @@ -1,9 +1,9 @@ % RawVec We've actually reached an interesting situation here: we've duplicated the logic -for specifying a buffer and freeing its memory. Now that we've implemented it -and identified *actual* logic duplication, this is a good time to perform some -logic compression. +for specifying a buffer and freeing its memory in Vec and IntoIter. Now that +we've implemented it and identified *actual* logic duplication, this is a good +time to perform some logic compression. We're going to abstract out the `(ptr, cap)` pair and give them the logic for allocating, growing, and freeing: @@ -64,7 +64,7 @@ impl Drop for RawVec { } ``` -And change vec as follows: +And change Vec as follows: ```rust,ignore pub struct Vec { diff --git a/src/doc/tarpl/vec.md b/src/doc/tarpl/vec.md index 39d9686ccac7..63f83788c4ba 100644 --- a/src/doc/tarpl/vec.md +++ b/src/doc/tarpl/vec.md @@ -12,7 +12,7 @@ bit nicer or efficient because intrinsics are permanently unstable. Although many intrinsics *do* become stabilized elsewhere (`std::ptr` and `str::mem` consist of many intrinsics). -Ultimately this means out implementation may not take advantage of all +Ultimately this means our implementation may not take advantage of all possible optimizations, though it will be by no means *naive*. We will definitely get into the weeds over nitty-gritty details, even when the problem doesn't *really* merit it. From 05bb1dbc43a620fbbd65ae830bb53ba9768ac185 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 27 Jul 2015 16:01:22 -0700 Subject: [PATCH 097/104] OBRM for aturon --- src/doc/tarpl/SUMMARY.md | 2 +- src/doc/tarpl/destructors.md | 6 ++++-- src/doc/tarpl/leaking.md | 40 ++++++++++++++++++++++++++++-------- src/doc/tarpl/obrm.md | 14 +++++++++++++ src/doc/tarpl/raii.md | 14 ------------- 5 files changed, 50 insertions(+), 26 deletions(-) create mode 100644 src/doc/tarpl/obrm.md delete mode 100644 src/doc/tarpl/raii.md diff --git a/src/doc/tarpl/SUMMARY.md b/src/doc/tarpl/SUMMARY.md index d8b348760765..a7014d7f0207 100644 --- a/src/doc/tarpl/SUMMARY.md +++ b/src/doc/tarpl/SUMMARY.md @@ -27,7 +27,7 @@ * [Checked](checked-uninit.md) * [Drop Flags](drop-flags.md) * [Unchecked](unchecked-uninit.md) -* [Ownership-Oriented Resource Management](raii.md) +* [Ownership Based Resource Management](obrm.md) * [Constructors](constructors.md) * [Destructors](destructors.md) * [Leaking](leaking.md) diff --git a/src/doc/tarpl/destructors.md b/src/doc/tarpl/destructors.md index e146ae4a1dac..34c8b2b8624d 100644 --- a/src/doc/tarpl/destructors.md +++ b/src/doc/tarpl/destructors.md @@ -45,8 +45,8 @@ impl Drop for Box { ``` and this works fine because when Rust goes to drop the `ptr` field it just sees -a *mut that has no actual `Drop` implementation. Similarly nothing can use- -after-free the `ptr` because the Box is immediately marked as uninitialized. +a [Unique][] that has no actual `Drop` implementation. Similarly nothing can +use-after-free the `ptr` because when drop exits, it becomes inacessible. However this wouldn't work: @@ -174,3 +174,5 @@ arbitrarily invalid state in there. On balance this is an ok choice. Certainly what you should reach for by default. However, in the future we expect there to be a first-class way to announce that a field shouldn't be automatically dropped. + +[Unique]: phantom-data.html diff --git a/src/doc/tarpl/leaking.md b/src/doc/tarpl/leaking.md index bb6f7bb4bda0..dcb03b1c8b6a 100644 --- a/src/doc/tarpl/leaking.md +++ b/src/doc/tarpl/leaking.md @@ -8,14 +8,17 @@ is perfect and all of our problems are solved. Everything is terrible and we have new and exotic problems to try to solve. -Many people like to believe that Rust eliminates resource leaks, but this is -absolutely not the case, no matter how you look at it. In the strictest sense, -"leaking" is so abstract as to be unpreventable. It's quite trivial to -initialize a collection at the start of a program, fill it with tons of objects -with destructors, and then enter an infinite event loop that never refers to it. -The collection will sit around uselessly, holding on to its precious resources -until the program terminates (at which point all those resources would have been -reclaimed by the OS anyway). +Many people like to believe that Rust eliminates resource leaks. In practice, +this is basically true. You would be surprised to see a Safe Rust program +leak resources in an uncontrolled way. + +However from a theoretical perspective this is absolutely not the case, no +matter how you look at it. In the strictest sense, "leaking" is so abstract as +to be unpreventable. It's quite trivial to initialize a collection at the start +of a program, fill it with tons of objects with destructors, and then enter an +infinite event loop that never refers to it. The collection will sit around +uselessly, holding on to its precious resources until the program terminates (at +which point all those resources would have been reclaimed by the OS anyway). We may consider a more restricted form of leak: failing to drop a value that is unreachable. Rust also doesn't prevent this. In fact Rust has a *function for @@ -181,7 +184,26 @@ in memory. ## thread::scoped::JoinGuard The thread::scoped API intends to allow threads to be spawned that reference -data on the stack without any synchronization over that data. Usage looked like: +data on their parent's stack without any synchronization over that data by +ensuring the parent joins the thread before any of the shared data goes out +of scope. + +```rust +pub fn scoped<'a, F>(f: F) -> JoinGuard<'a> + where F: FnOnce() + Send + 'a +``` + +Here `f` is some closure for the other thread to execute. Saying that +`F: Send +'a` is saying that it closes over data that lives for `'a`, and it +either owns that data or the data was Sync (implying `&data` is Send). + +Because JoinGuard has a lifetime, it keeps all the data it closes over +borrowed in the parent thread. This means the JoinGuard can't outlive +the data that the other thread is working on. When the JoinGuard *does* get +dropped it blocks the parent thread, ensuring the child terminates before any +of the closed-over data goes out of scope in the parent. + +Usage looked like: ```rust,ignore let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; diff --git a/src/doc/tarpl/obrm.md b/src/doc/tarpl/obrm.md new file mode 100644 index 000000000000..2c495240c127 --- /dev/null +++ b/src/doc/tarpl/obrm.md @@ -0,0 +1,14 @@ +% The Perils Of Ownership Based Resource Management (OBRM) + +OBRM (AKA RAII: Resource Acquisition Is Initialization) is something you'll +interact with a lot in Rust. Especially if you use the standard library. + +Roughly speaking the pattern is as follows: to acquire a resource, you create an +object that manages it. To release the resource, you simply destroy the object, +and it cleans up the resource for you. The most common "resource" this pattern +manages is simply *memory*. `Box`, `Rc`, and basically everything in +`std::collections` is a convenience to enable correctly managing memory. This is +particularly important in Rust because we have no pervasive GC to rely on for +memory management. Which is the point, really: Rust is about control. However we +are not limited to just memory. Pretty much every other system resource like a +thread, file, or socket is exposed through this kind of API. diff --git a/src/doc/tarpl/raii.md b/src/doc/tarpl/raii.md deleted file mode 100644 index e9b92c69ccd2..000000000000 --- a/src/doc/tarpl/raii.md +++ /dev/null @@ -1,14 +0,0 @@ -% The Perils Of RAII - -Ownership Based Resource Management (AKA RAII: Resource Acquisition Is Initialization) is -something you'll interact with a lot in Rust. Especially if you use the standard library. - -Roughly speaking the pattern is as follows: to acquire a resource, you create an object that -manages it. To release the resource, you simply destroy the object, and it cleans up the -resource for you. The most common "resource" -this pattern manages is simply *memory*. `Box`, `Rc`, and basically everything in -`std::collections` is a convenience to enable correctly managing memory. This is particularly -important in Rust because we have no pervasive GC to rely on for memory management. Which is the -point, really: Rust is about control. However we are not limited to just memory. -Pretty much every other system resource like a thread, file, or socket is exposed through -this kind of API. From 57891067374a4cf3fff8c2be4bd0804cb4ef7fbe Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 28 Jul 2015 13:20:36 -0700 Subject: [PATCH 098/104] many many pnkfelix fixes --- src/doc/tarpl/exotic-sizes.md | 73 ++++++++++++++--------- src/doc/tarpl/meet-safe-and-unsafe.md | 36 ++++++------ src/doc/tarpl/other-reprs.md | 19 +++--- src/doc/tarpl/ownership.md | 15 ++--- src/doc/tarpl/repr-rust.md | 84 +++++++++++++++++---------- src/doc/tarpl/safe-unsafe-meaning.md | 56 ++++++++++++------ src/doc/tarpl/working-with-unsafe.md | 37 +++++++----- 7 files changed, 197 insertions(+), 123 deletions(-) diff --git a/src/doc/tarpl/exotic-sizes.md b/src/doc/tarpl/exotic-sizes.md index 68ce061d8c8b..d75d12e716e3 100644 --- a/src/doc/tarpl/exotic-sizes.md +++ b/src/doc/tarpl/exotic-sizes.md @@ -9,19 +9,24 @@ is not always the case, however. # Dynamically Sized Types (DSTs) -Rust also supports types without a statically known size. On the surface, this -is a bit nonsensical: Rust *must* know the size of something in order to work -with it! DSTs are generally produced as views, or through type-erasure of types -that *do* have a known size. Due to their lack of a statically known size, these -types can only exist *behind* some kind of pointer. They consequently produce a -*fat* pointer consisting of the pointer and the information that *completes* -them. +Rust in fact supports Dynamically Sized Types (DSTs): types without a statically +known size or alignment. On the surface, this is a bit nonsensical: Rust *must* +know the size and alignment of something in order to correctly work with it! In +this regard, DSTs are not normal types. Due to their lack of a statically known +size, these types can only exist behind some kind of pointer. Any pointer to a +DST consequently becomes a *fat* pointer consisting of the pointer and the +information that "completes" them (more on this below). -For instance, the slice type, `[T]`, is some statically unknown number of -elements stored contiguously. `&[T]` consequently consists of a `(&T, usize)` -pair that specifies where the slice starts, and how many elements it contains. -Similarly, Trait Objects support interface-oriented type erasure through a -`(data_ptr, vtable_ptr)` pair. +There are two major DSTs exposed by the language: trait objects, and slices. + +A trait object represents some type that implements the traits it specifies. +The exact original type is *erased* in favour of runtime reflection +with a vtable containing all the information necessary to use the type. +This is the information that completes a trait object: a pointer to its vtable. + +A slice is simply a view into some contiguous storage -- typically an array or +`Vec`. The information that completes a slice is just the number of elements +it points to. Structs can actually store a single DST directly as their last field, but this makes them a DST as well: @@ -34,8 +39,8 @@ struct Foo { } ``` -**NOTE: As of Rust 1.0 struct DSTs are broken if the last field has -a variable position based on its alignment.** +**NOTE: [As of Rust 1.0 struct DSTs are broken if the last field has +a variable position based on its alignment][dst-issue].** @@ -56,22 +61,32 @@ struct Baz { } ``` -On their own, ZSTs are, for obvious reasons, pretty useless. However as with -many curious layout choices in Rust, their potential is realized in a generic -context. +On their own, Zero Sized Types (ZSTs) are, for obvious reasons, pretty useless. +However as with many curious layout choices in Rust, their potential is realized +in a generic context: Rust largely understands that any operation that produces +or stores a ZST can be reduced to a no-op. First off, storing it doesn't even +make sense -- it doesn't occupy any space. Also there's only one value of that +type, so anything that loads it can just produce it from the aether -- which is +also a no-op since it doesn't occupy any space. -Rust largely understands that any operation that produces or stores a ZST can be -reduced to a no-op. For instance, a `HashSet` can be effeciently implemented -as a thin wrapper around `HashMap` because all the operations `HashMap` -normally does to store and retrieve values will be completely stripped in -monomorphization. +One of the most extreme example's of this is Sets and Maps. Given a +`Map`, it is common to implement a `Set` as just a thin wrapper +around `Map`. In many languages, this would necessitate +allocating space for UselessJunk and doing work to store and load UselessJunk +only to discard it. Proving this unnecessary would be a difficult analysis for +the compiler. -Similarly `Result<(), ()>` and `Option<()>` are effectively just fancy `bool`s. +However in Rust, we can just say that `Set = Map`. Now Rust +statically knows that every load and store is useless, and no allocation has any +size. The result is that the monomorphized code is basically a custom +implementation of a HashSet with none of the overhead that HashMap would have to +support values. Safe code need not worry about ZSTs, but *unsafe* code must be careful about the consequence of types with no size. In particular, pointer offsets are no-ops, -and standard allocators (including jemalloc, the one used by Rust) generally -consider passing in `0` as Undefined Behaviour. +and standard allocators (including jemalloc, the one used by default in Rust) +generally consider passing in `0` for the size of an allocation as Undefined +Behaviour. @@ -93,11 +108,12 @@ return a Result in general, but a specific case actually is infallible. It's actually possible to communicate this at the type level by returning a `Result`. Consumers of the API can confidently unwrap such a Result knowing that it's *statically impossible* for this value to be an `Err`, as -this would require providing a value of type Void. +this would require providing a value of type `Void`. In principle, Rust can do some interesting analyses and optimizations based on this fact. For instance, `Result` could be represented as just `T`, -because the Err case doesn't actually exist. The following *could* also compile: +because the `Err` case doesn't actually exist. The following *could* also +compile: ```rust,ignore enum Void {} @@ -116,3 +132,6 @@ actually valid to construct, but dereferencing them is Undefined Behaviour because that doesn't actually make sense. That is, you could model C's `void *` type with `*const Void`, but this doesn't necessarily gain anything over using e.g. `*const ()`, which *is* safe to randomly dereference. + + +[dst-issue]: https://github.com/rust-lang/rust/issues/26403 diff --git a/src/doc/tarpl/meet-safe-and-unsafe.md b/src/doc/tarpl/meet-safe-and-unsafe.md index 5ff000f2bbce..a5e3136c54ac 100644 --- a/src/doc/tarpl/meet-safe-and-unsafe.md +++ b/src/doc/tarpl/meet-safe-and-unsafe.md @@ -2,7 +2,7 @@ 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 some *really* poor +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 @@ -12,21 +12,22 @@ 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 +Regardless of why you're doing it, as soon as your program starts talking to C it stops being safe. With that said, Rust is *totally* a safe programming language. Well, Rust *has* a safe programming language. Let's step back a bit. -Rust can be thought of as being composed of two -programming languages: *Safe* and *Unsafe*. Safe is For Reals Totally Safe. -Unsafe, unsurprisingly, is *not* For Reals Totally Safe. In fact, Unsafe lets -you do some really crazy unsafe things. +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 crazy unsafe things. -Safe is *the* 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 Behaviour nonsense. +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 Behaviour +nonsense. *That's totally awesome*. @@ -69,17 +70,16 @@ language cares about is preventing the following things: * A non-utf8 `str` * Unwinding into another language * Causing a [data race][race] -* Double-dropping a value -That's it. That's all the Undefined Behaviour baked into Rust. Of course, unsafe -functions and traits are free to declare arbitrary other constraints that a -program must maintain to avoid Undefined Behaviour. However these are generally -just things that will 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. +That's it. That's all the causes of Undefined Behaviour baked into Rust. Of +course, unsafe functions and traits are free to declare arbitrary other +constraints that a program must maintain to avoid Undefined Behaviour. 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: +Rust is otherwise quite permissive with respect to other dubious operations. +Rust considers it "safe" to: * Deadlock * Have a [race condition][race] diff --git a/src/doc/tarpl/other-reprs.md b/src/doc/tarpl/other-reprs.md index 26e0192a536d..93ef2c13cdf8 100644 --- a/src/doc/tarpl/other-reprs.md +++ b/src/doc/tarpl/other-reprs.md @@ -12,21 +12,21 @@ The order, size, and alignment of fields is exactly what you would expect from C or C++. Any type you expect to pass through an FFI boundary should have `repr(C)`, as C is the lingua-franca of the programming world. This is also necessary to soundly do more elaborate tricks with data layout such as -reintepretting values as a different type. +reinterpreting values as a different type. However, the interaction with Rust's more exotic data layout features must be kept in mind. Due to its dual purpose as "for FFI" and "for layout control", `repr(C)` can be applied to types that will be nonsensical or problematic if passed through the FFI boundary. -* ZSTs are still zero-sized, even though this is not a standard behaviour in +* ZSTs are still zero-sized, even though this is not a standard behaviour in C, and is explicitly contrary to the behaviour of an empty type in C++, which still consumes a byte of space. * DSTs, tuples, and tagged unions are not a concept in C and as such are never FFI safe. -* **The [drop flag][] will still be added** +* **If the type would have any [drop flags][], they will still be added** * This is equivalent to one of `repr(u*)` (see the next section) for enums. The chosen size is the default enum size for the target platform's C ABI. Note that @@ -39,10 +39,10 @@ compiled with certain flags. # repr(u8), repr(u16), repr(u32), repr(u64) These specify the size to make a C-like enum. If the discriminant overflows the -integer it has to fit in, it will be an error. You can manually ask Rust to -allow this by setting the overflowing element to explicitly be 0. However Rust -will not allow you to create an enum where two variants have the same -discriminant. +integer it has to fit in, it will produce a compile-time error. You can manually +ask Rust to allow this by setting the overflowing element to explicitly be 0. +However Rust will not allow you to create an enum where two variants have the +same discriminant. On non-C-like enums, this will inhibit certain optimizations like the null- pointer optimization. @@ -65,9 +65,12 @@ compiler might be able to paper over alignment issues with shifts and masks. However if you take a reference to a packed field, it's unlikely that the compiler will be able to emit code to avoid an unaligned load. +**[As of Rust 1.0 this can cause undefined behaviour.][ub loads]** + `repr(packed)` is not to be used lightly. Unless you have extreme requirements, this should not be used. This repr is a modifier on `repr(C)` and `repr(rust)`. -[drop flag]: drop-flags.html +[drop flags]: drop-flags.html +[ub loads]: https://github.com/rust-lang/rust/issues/27060 diff --git a/src/doc/tarpl/ownership.md b/src/doc/tarpl/ownership.md index 200337a2256e..f79cd92479f0 100644 --- a/src/doc/tarpl/ownership.md +++ b/src/doc/tarpl/ownership.md @@ -5,16 +5,17 @@ memory-safe and efficient, while avoiding garbage collection. Before getting into the ownership system in detail, we will consider the motivation of this design. -We will assume that you accept that garbage collection is not always an optimal -solution, and that it is desirable to manually manage memory to some extent. -If you do not accept this, might I interest you in a different language? +We will assume that you accept that garbage collection (GC) is not always an +optimal solution, and that it is desirable to manually manage memory in some +contexts. If you do not accept this, might I interest you in a different +language? Regardless of your feelings on GC, it is pretty clearly a *massive* boon to making code safe. You never have to worry about things going away *too soon* (although whether you still *wanted* to be pointing at that thing is a different -issue...). This is a pervasive problem that C and C++ need to deal with. -Consider this simple mistake that all of us who have used a non-GC'd language -have made at one point: +issue...). This is a pervasive problem that C and C++ programs need to deal +with. Consider this simple mistake that all of us who have used a non-GC'd +language have made at one point: ```rust,ignore fn as_str(data: &u32) -> &str { @@ -40,7 +41,7 @@ be forced to accept your program on the assumption that it is correct. This will never happen to Rust. It's up to the programmer to prove to the compiler that everything is sound. -Of course, rust's story around ownership is much more complicated than just +Of course, Rust's story around ownership is much more complicated than just verifying that references don't escape the scope of their referent. That's because ensuring pointers are always valid is much more complicated than this. For instance in this code, diff --git a/src/doc/tarpl/repr-rust.md b/src/doc/tarpl/repr-rust.md index f7ed15f1e870..639d64adc18b 100644 --- a/src/doc/tarpl/repr-rust.md +++ b/src/doc/tarpl/repr-rust.md @@ -1,5 +1,19 @@ % repr(Rust) +First and foremost, all types have an alignment specified in bytes. The +alignment of a type specifies what addresses are valid to store the value at. A +value of alignment `n` must only be stored at an address that is a multiple of +`n`. So alignment 2 means you must be stored at an even address, and 1 means +that you can be stored anywhere. Alignment is at least 1, and always a power of +2. Most primitives are generally aligned to their size, although this is +platform-specific behaviour. In particular, on x86 `u64` and `f64` may be only +aligned to 32 bits. + +A type's size must always be a multiple of its alignment. This ensures that an +array of that type may always be indexed by offsetting by a multiple of its +size. Note that the size and alignment of a type may not be known +statically in the case of [dynamically sized types][dst]. + Rust gives you the following ways to lay out composite data: * structs (named product types) @@ -9,17 +23,10 @@ Rust gives you the following ways to lay out composite data: An enum is said to be *C-like* if none of its variants have associated data. -For all these, individual fields are aligned to their preferred alignment. For -primitives this is usually equal to their size. For instance, a u32 will be -aligned to a multiple of 32 bits, and a u16 will be aligned to a multiple of 16 -bits. Note that some primitives may be emulated on different platforms, and as -such may have strange alignment. For instance, a u64 on x86 may actually be -emulated as a pair of u32s, and thus only have 32-bit alignment. - -Composite structures will have a preferred alignment equal to the maximum -of their fields' preferred alignment, and a size equal to a multiple of their -preferred alignment. This ensures that arrays of T can be correctly iterated -by offsetting by their size. So for instance, +Composite structures will have an alignment equal to the maximum +of their fields' alignment. Rust will consequently insert padding where +necessary to ensure that all fields are properly aligned and that the overall +type's size is a multiple of its alignment. For instance: ```rust struct A { @@ -29,12 +36,24 @@ struct A { } ``` -will have a size that is a multiple of 32-bits, and 32-bit alignment. +will be 32-bit aligned assuming these primitives are aligned to their size. +It will therefore have a size that is a multiple of 32-bits. It will potentially +*really* become: -There is *no indirection* for these types; all data is stored contiguously as you would -expect in C. However with the exception of arrays (which are densely packed and -in-order), the layout of data is not by default specified in Rust. Given the two -following struct definitions: +```rust +struct A { + a: u8, + _pad1: [u8; 3], // to align `b` + b: u32, + c: u16, + _pad2: [u8; 2], // to make overall size multiple of 4 +} +``` + +There is *no indirection* for these types; all data is stored contiguously as +you would expect in C. However with the exception of arrays (which are densely +packed and in-order), the layout of data is not by default specified in Rust. +Given the two following struct definitions: ```rust struct A { @@ -48,13 +67,15 @@ struct B { } ``` -Rust *does* guarantee that two instances of A have their data laid out in exactly -the same way. However Rust *does not* guarantee that an instance of A has the same -field ordering or padding as an instance of B (in practice there's no *particular* -reason why they wouldn't, other than that its not currently guaranteed). +Rust *does* guarantee that two instances of A have their data laid out in +exactly the same way. However Rust *does not* guarantee that an instance of A +has the same field ordering or padding as an instance of B (in practice there's +no *particular* reason why they wouldn't, other than that its not currently +guaranteed). -With A and B as written, this is basically nonsensical, but several other features -of Rust make it desirable for the language to play with data layout in complex ways. +With A and B as written, this is basically nonsensical, but several other +features of Rust make it desirable for the language to play with data layout in +complex ways. For instance, consider this struct: @@ -66,10 +87,10 @@ struct Foo { } ``` -Now consider the monomorphizations of `Foo` and `Foo`. If Rust lays out the -fields in the order specified, we expect it to *pad* the values in the struct to satisfy -their *alignment* requirements. So if Rust didn't reorder fields, we would expect Rust to -produce the following: +Now consider the monomorphizations of `Foo` and `Foo`. If +Rust lays out the fields in the order specified, we expect it to *pad* the +values in the struct to satisfy their *alignment* requirements. So if Rust +didn't reorder fields, we would expect Rust to produce the following: ```rust,ignore struct Foo { @@ -87,10 +108,11 @@ struct Foo { } ``` -The latter case quite simply wastes space. An optimal use of space therefore requires -different monomorphizations to have *different field orderings*. +The latter case quite simply wastes space. An optimal use of space therefore +requires different monomorphizations to have *different field orderings*. -**Note: this is a hypothetical optimization that is not yet implemented in Rust 1.0** +**Note: this is a hypothetical optimization that is not yet implemented in Rust +**1.0 Enums make this consideration even more complicated. Naively, an enum such as: @@ -121,8 +143,10 @@ by using null as a special value. The net result is that There are many types in Rust that are, or contain, "not null" pointers such as `Box`, `Vec`, `String`, `&T`, and `&mut T`. Similarly, one can imagine -nested enums pooling their tags into a single descriminant, as they are by +nested enums pooling their tags into a single discriminant, as they are by definition known to have a limited range of valid values. In principle enums can use fairly elaborate algorithms to cache bits throughout nested types with special constrained representations. As such it is *especially* desirable that we leave enum layout unspecified today. + +[dst]: exotic-sizes.html#dynamically-sized-types-(dsts) diff --git a/src/doc/tarpl/safe-unsafe-meaning.md b/src/doc/tarpl/safe-unsafe-meaning.md index 2a593ffc5a7a..c7210f8e2cf9 100644 --- a/src/doc/tarpl/safe-unsafe-meaning.md +++ b/src/doc/tarpl/safe-unsafe-meaning.md @@ -1,29 +1,30 @@ % How Safe and Unsafe Interact -So what's the relationship between Safe and Unsafe? How do they interact? +So what's the relationship between Safe and Unsafe Rust? How do they interact? -Rust models the seperation between Safe and Unsafe with the `unsafe` keyword, which -can be thought as a sort of *foreign function interface* (FFI) between Safe and Unsafe. -This is the magic behind why we can say Safe is a safe language: all the scary unsafe -bits are relagated *exclusively* to FFI *just like every other safe language*. +Rust models the separation between Safe and Unsafe Rust with the `unsafe` +keyword, which can be thought as a sort of *foreign function interface* (FFI) +between Safe and Unsafe Rust. This is the magic behind why we can say Safe Rust +is a safe language: all the scary unsafe bits are relegated *exclusively* to FFI +*just like every other safe language*. However because one language is a subset of the other, the two can be cleanly -intermixed as long as the boundary between Safe and Unsafe is denoted with the -`unsafe` keyword. No need to write headers, initialize runtimes, or any of that -other FFI boiler-plate. +intermixed as long as the boundary between Safe and Unsafe Rust is denoted with +the `unsafe` keyword. No need to write headers, initialize runtimes, or any of +that other FFI boiler-plate. There are several places `unsafe` can appear in Rust today, which can largely be grouped into two categories: * There are unchecked contracts here. To declare you understand this, I require you to write `unsafe` elsewhere: - * On functions, `unsafe` is declaring the function to be unsafe to call. Users - of the function must check the documentation to determine what this means, - and then have to write `unsafe` somewhere to identify that they're aware of - the danger. + * On functions, `unsafe` is declaring the function to be unsafe to call. + Users of the function must check the documentation to determine what this + means, and then have to write `unsafe` somewhere to identify that they're + aware of the danger. * On trait declarations, `unsafe` is declaring that *implementing* the trait - is an unsafe operation, as it has contracts that other unsafe code is free to - trust blindly. (More on this below.) + is an unsafe operation, as it has contracts that other unsafe code is free + to trust blindly. (More on this below.) * I am declaring that I have, to the best of my knowledge, adhered to the unchecked contracts: @@ -64,9 +65,9 @@ This means that Unsafe, **the royal vanguard of Undefined Behaviour**, has to be *super paranoid* about generic safe code. Unsafe is free to trust *specific* safe code (or else you would degenerate into infinite spirals of paranoid despair). It is generally regarded as ok to trust the standard library to be correct, as -std is effectively an extension of the language (and you *really* just have to trust -the language). If `std` fails to uphold the guarantees it declares, then it's -basically a language bug. +`std` is effectively an extension of the language (and you *really* just have +to trust the language). If `std` fails to uphold the guarantees it declares, +then it's basically a language bug. That said, it would be best to minimize *needlessly* relying on properties of concrete safe code. Bugs happen! Of course, I must reinforce that this is only @@ -89,7 +90,7 @@ Ord for a type, but don't actually provide a proper total ordering, BTreeMap wil get *really confused* and start making a total mess of itself. Data that is inserted may be impossible to find! -But that's ok. BTreeMap is safe, so it guarantees that even if you give it a +But that's okay. BTreeMap is safe, so it guarantees that even if you give it a *completely* garbage Ord implementation, it will still do something *safe*. You won't start reading uninitialized memory or unallocated memory. In fact, BTreeMap manages to not actually lose any of your data. When the map is dropped, all the @@ -104,7 +105,24 @@ Safe's responsibility to uphold. But wouldn't it be grand if there was some way for Unsafe to trust *some* trait contracts *somewhere*? This is the problem that unsafe traits tackle: by marking *the trait itself* as unsafe *to implement*, Unsafe can trust the implementation -to be correct. +to uphold the trait's contract. Although the trait implementation may be +incorrect in arbitrary other ways. + +For instance, given a hypothetical UnsafeOrd trait, this is technically a valid +implementation: + +```rust +# use std::cmp::Ordering; +# struct MyType; +# pub unsafe trait UnsafeOrd { fn cmp(&self, other: &Self) -> Ordering; } +unsafe impl UnsafeOrd for MyType { + fn cmp(&self, other: &Self) -> Ordering { + Ordering::Equal + } +} +``` + +But it's probably not the implementation you want. Rust has traditionally avoided making traits unsafe because it makes Unsafe pervasive, which is not desirable. Send and Sync are unsafe is because diff --git a/src/doc/tarpl/working-with-unsafe.md b/src/doc/tarpl/working-with-unsafe.md index 0aeb2c0dc258..b20dff72e1c6 100644 --- a/src/doc/tarpl/working-with-unsafe.md +++ b/src/doc/tarpl/working-with-unsafe.md @@ -1,8 +1,8 @@ % Working with Unsafe -Rust generally only gives us the tools to talk about Unsafe in a scoped and -binary manner. Unfortunately, reality is significantly more complicated than that. -For instance, consider the following toy function: +Rust generally only gives us the tools to talk about Unsafe Rust in a scoped and +binary manner. Unfortunately, reality is significantly more complicated than +that. For instance, consider the following toy function: ```rust fn index(idx: usize, arr: &[u8]) -> Option { @@ -35,10 +35,15 @@ fn index(idx: usize, arr: &[u8]) -> Option { This program is now unsound, and yet *we only modified safe code*. This is the fundamental problem of safety: it's non-local. The soundness of our unsafe -operations necessarily depends on the state established by "safe" operations. -Although safety *is* modular (we *still* don't need to worry about about -unrelated safety issues like uninitialized memory), it quickly contaminates the -surrounding code. +operations necessarily depends on the state established by otherwise +"safe" operations. + +Safety is modular in the sense that opting into unsafety doesn't require you +to consider arbitrary other kinds of badness. For instance, doing an unchecked +index into a slice doesn't mean you suddenly need to worry about the slice being +null or containing uninitialized memory. Nothing fundamentally changes. However +safety *isn't* modular in the sense that programs are inherently stateful and +your unsafe operations may depend on arbitrary other state. Trickier than that is when we get into actual statefulness. Consider a simple implementation of `Vec`: @@ -84,10 +89,10 @@ fn make_room(&mut self) { } ``` -This code is safe, but it is also completely unsound. Changing the capacity -violates the invariants of Vec (that `cap` reflects the allocated space in the -Vec). This is not something the rest of Vec can guard against. It *has* to -trust the capacity field because there's no way to verify it. +This code is 100% Safe Rust but it is also completely unsound. Changing the +capacity violates the invariants of Vec (that `cap` reflects the allocated space +in the Vec). This is not something the rest of Vec can guard against. It *has* +to trust the capacity field because there's no way to verify it. `unsafe` does more than pollute a whole function: it pollutes a whole *module*. Generally, the only bullet-proof way to limit the scope of unsafe code is at the @@ -102,9 +107,13 @@ as Vec. It is therefore possible for us to write a completely safe abstraction that relies on complex invariants. This is *critical* to the relationship between Safe Rust and Unsafe Rust. We have already seen that Unsafe code must trust -*some* Safe code, but can't trust *arbitrary* Safe code. However if Unsafe -couldn't prevent client Safe code from messing with its state in arbitrary ways, -safety would be a lost cause. +*some* Safe code, but can't trust *generic* Safe code. It can't trust an +arbitrary implementor of a trait or any function that was passed to it to be +well-behaved in a way that safe code doesn't care about. + +However if unsafe code couldn't prevent client safe code from messing with its +state in arbitrary ways, safety would be a lost cause. Thankfully, it *can* +prevent arbitrary code from messing with critical state due to privacy. Safety lives! From 0d37e7897766129715a2be960cb87a717a48390d Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 28 Jul 2015 15:13:54 -0700 Subject: [PATCH 099/104] lots more felix fixes --- src/doc/tarpl/casts.md | 18 +++++++++------ src/doc/tarpl/checked-uninit.md | 13 +++++++++-- src/doc/tarpl/coercions.md | 2 +- src/doc/tarpl/drop-flags.md | 34 ++++++++++++++++++++-------- src/doc/tarpl/dropck.md | 12 +++++----- src/doc/tarpl/exception-safety.md | 2 +- src/doc/tarpl/hrtb.md | 23 ++++++++++--------- src/doc/tarpl/lifetime-splitting.md | 13 ++++++----- src/doc/tarpl/lifetimes.md | 17 +++++++------- src/doc/tarpl/safe-unsafe-meaning.md | 14 ++++++------ src/doc/tarpl/subtyping.md | 14 +++++++----- src/doc/tarpl/unchecked-uninit.md | 16 ++++++------- 12 files changed, 104 insertions(+), 74 deletions(-) diff --git a/src/doc/tarpl/casts.md b/src/doc/tarpl/casts.md index a5527b250755..cb12ffe8d214 100644 --- a/src/doc/tarpl/casts.md +++ b/src/doc/tarpl/casts.md @@ -41,8 +41,7 @@ Note that lengths are not adjusted when casting raw slices - half of the original memory. Casting is not transitive, that is, even if `e as U1 as U2` is a valid -expression, `e as U2` is not necessarily so (in fact it will only be valid if -`U1` coerces to `U2`). +expression, `e as U2` is not necessarily so. For numeric casts, there are quite a few cases to consider: @@ -53,15 +52,20 @@ For numeric casts, there are quite a few cases to consider: * zero-extend if the source is unsigned * sign-extend if the source is signed * casting from a float to an integer will round the float towards zero - * **NOTE: currently this will cause Undefined Behaviour if the rounded - value cannot be represented by the target integer type**. This includes - Inf and NaN. This is a bug and will be fixed. + * **[NOTE: currently this will cause Undefined Behaviour if the rounded + value cannot be represented by the target integer type][float-int]**. + This includes Inf and NaN. This is a bug and will be fixed. * casting from an integer to float will produce the floating point representation of the integer, rounded if necessary (rounding strategy unspecified) * casting from an f32 to an f64 is perfect and lossless * casting from an f64 to an f32 will produce the closest possible value (rounding strategy unspecified) - * **NOTE: currently this will cause Undefined Behaviour if the value + * **[NOTE: currently this will cause Undefined Behaviour if the value is finite but larger or smaller than the largest or smallest finite - value representable by f32**. This is a bug and will be fixed. + value representable by f32][float-float]**. This is a bug and will + be fixed. + + +[float-int]: https://github.com/rust-lang/rust/issues/10184 +[float-float]: https://github.com/rust-lang/rust/issues/15536 diff --git a/src/doc/tarpl/checked-uninit.md b/src/doc/tarpl/checked-uninit.md index 8b03cd497b74..706016a480c6 100644 --- a/src/doc/tarpl/checked-uninit.md +++ b/src/doc/tarpl/checked-uninit.md @@ -104,5 +104,14 @@ fn main() { ``` However reassigning `y` in this example *would* require `y` to be marked as -mutable, as a Safe Rust program could observe that the value of `y` changed. -Otherwise the variable is exactly like new. +mutable, as a Safe Rust program could observe that the value of `y` changed: + +```rust +fn main() { + let mut y = Box::new(0); + let z = y; // y is now logically uninitialized because Box isn't Copy + y = Box::new(1); // reinitialize y +} +``` + +Otherwise it's like `y` is a brand new variable. diff --git a/src/doc/tarpl/coercions.md b/src/doc/tarpl/coercions.md index 8bb82843ba0d..2e33a6729d1c 100644 --- a/src/doc/tarpl/coercions.md +++ b/src/doc/tarpl/coercions.md @@ -27,7 +27,7 @@ only implemented automatically, and enables the following transformations: * `Foo<..., T, ...>` => `Foo<..., U, ...>` where: * `T: Unsize` * `Foo` is a struct - * Only the last field has type `T` + * Only the last field of `Foo` has type `T` * `T` is not part of the type of any other fields Coercions occur at a *coercion site*. Any location that is explicitly typed diff --git a/src/doc/tarpl/drop-flags.md b/src/doc/tarpl/drop-flags.md index e8c331cd0565..f95ccc00329e 100644 --- a/src/doc/tarpl/drop-flags.md +++ b/src/doc/tarpl/drop-flags.md @@ -2,12 +2,25 @@ The examples in the previous section introduce an interesting problem for Rust. We have seen that's possible to conditionally initialize, deinitialize, and -*reinitialize* locations of memory totally safely. For Copy types, this isn't +reinitialize locations of memory totally safely. For Copy types, this isn't particularly notable since they're just a random pile of bits. However types with destructors are a different story: Rust needs to know whether to call a destructor whenever a variable is assigned to, or a variable goes out of scope. How can it do this with conditional initialization? +Note that this is not a problem that all assignments need worry about. In +particular, assigning through a dereference unconditionally drops, and assigning +in a `let` unconditionally *doesn't* drop: + +``` +let mut x = Box::new(0); // let makes a fresh variable, so never need to drop +let y = &mut x; +*y = Box::new(1); // Deref assumes the referent is initialized, so always drops +``` + +This is only a problem when overwriting a previously initialized variable or +one of its subfields. + It turns out that Rust actually tracks whether a type should be dropped or not *at runtime*. As a variable becomes initialized and uninitialized, a *drop flag* for that variable is toggled. When a variable *might* need to be dropped, this @@ -15,7 +28,7 @@ flag is evaluated to determine if it *should* be dropped. Of course, it is *often* the case that a value's initialization state can be *statically* known at every point in the program. If this is the case, then the -compiler can theoretically generate more effecient code! For instance, straight- +compiler can theoretically generate more efficient code! For instance, straight- line code has such *static drop semantics*: ```rust @@ -23,8 +36,8 @@ let mut x = Box::new(0); // x was uninit; just overwrite. let mut y = x; // y was uninit; just overwrite and make x uninit. x = Box::new(0); // x was uninit; just overwrite. y = x; // y was init; Drop y, overwrite it, and make x uninit! - // y was init; Drop y! - // x was uninit; do nothing. + // y goes out of scope; y was init; Drop y! + // x goes out of scope; x was uninit; do nothing. ``` And even branched code where all branches have the same behaviour with respect @@ -40,7 +53,7 @@ if condition { drop(x) // x gets moved out; make x uninit. } x = Box::new(0); // x was uninit; just overwrite. - // x was init; Drop x! + // x goes out of scope; x was init; Drop x! ``` However code like this *requires* runtime information to correctly Drop: @@ -52,7 +65,8 @@ if condition { x = Box::new(0); // x was uninit; just overwrite. println!("{}", x); } - // x *might* be uninit; check the flag! + // x goes out of scope; x *might* be uninit; + // check the flag! ``` Of course, in this case it's trivial to retrieve static drop semantics: @@ -66,10 +80,10 @@ if condition { ``` As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden -field of any type that implements Drop. Rust sets the drop flag by -overwriting the *entire* value with a particular byte. This is pretty obviously -Not The Fastest and causes a bunch of trouble with optimizing code. It's legacy -from a time when you could do much more complex conditional initialization. +field of any type that implements Drop. Rust sets the drop flag by overwriting +the *entire* value with a particular bit pattern. This is pretty obviously Not +The Fastest and causes a bunch of trouble with optimizing code. It's legacy from +a time when you could do much more complex conditional initialization. As such work is currently under way to move the flags out onto the stack frame where they more reasonably belong. Unfortunately, this work will take some time diff --git a/src/doc/tarpl/dropck.md b/src/doc/tarpl/dropck.md index e1a25f513c7f..419c61281d9f 100644 --- a/src/doc/tarpl/dropck.md +++ b/src/doc/tarpl/dropck.md @@ -49,7 +49,7 @@ accidentally make dangling pointers. Consider the following simple program: struct Inspector<'a>(&'a u8); fn main() { - let (days, inspector); + let (inspector, days); days = Box::new(1); inspector = Inspector(&days); } @@ -71,7 +71,7 @@ impl<'a> Drop for Inspector<'a> { } fn main() { - let (days, inspector); + let (inspector, days); days = Box::new(1); inspector = Inspector(&days); // Let's say `days` happens to get dropped first. @@ -85,14 +85,14 @@ fn main() { ^~~~ :9:11: 15:2 note: reference must be valid for the block at 9:10... :9 fn main() { -:10 let (days, inspector); +:10 let (inspector, days); :11 days = Box::new(1); :12 inspector = Inspector(&days); :13 // Let's say `days` happens to get dropped first. :14 // Then when Inspector is dropped, it will try to read free'd memory! ... :10:27: 15:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 10:26 -:10 let (days, inspector); +:10 let (inspector, days); :11 days = Box::new(1); :12 inspector = Inspector(&days); :13 // Let's say `days` happens to get dropped first. @@ -112,8 +112,8 @@ of the finer details of how the drop checker validates types is totally up in the air. However The Big Rule is the subtlety that we have focused on this whole section: -**For a generic type to soundly implement drop, it must strictly outlive all of -its generic arguments.** +**For a generic type to soundly implement drop, its generics arguments must +strictly outlive it.** This rule is sufficient but not necessary to satisfy the drop checker. That is, if your type obeys this rule then it's *definitely* sound to drop. However diff --git a/src/doc/tarpl/exception-safety.md b/src/doc/tarpl/exception-safety.md index 9a3193409034..a43eec4f37ea 100644 --- a/src/doc/tarpl/exception-safety.md +++ b/src/doc/tarpl/exception-safety.md @@ -37,7 +37,7 @@ needs to be careful and consider exception safety. ## Vec::push_all `Vec::push_all` is a temporary hack to get extending a Vec by a slice reliably -effecient without specialization. Here's a simple implementation: +efficient without specialization. Here's a simple implementation: ```rust,ignore impl Vec { diff --git a/src/doc/tarpl/hrtb.md b/src/doc/tarpl/hrtb.md index 640742f9b149..3cc06f21df00 100644 --- a/src/doc/tarpl/hrtb.md +++ b/src/doc/tarpl/hrtb.md @@ -1,6 +1,6 @@ % Higher-Rank Trait Bounds (HRTBs) -Rust's Fn traits are a little bit magic. For instance, we can write the +Rust's `Fn` traits are a little bit magic. For instance, we can write the following code: ```rust @@ -52,21 +52,22 @@ fn main() { } ``` -How on earth are we supposed to express the lifetimes on F's trait bound? We need -to provide some lifetime there, but the lifetime we care about can't be named until -we enter the body of `call`! Also, that isn't some fixed lifetime; call works with -*any* lifetime `&self` happens to have at that point. +How on earth are we supposed to express the lifetimes on `F`'s trait bound? We +need to provide some lifetime there, but the lifetime we care about can't be +named until we enter the body of `call`! Also, that isn't some fixed lifetime; +call works with *any* lifetime `&self` happens to have at that point. -This job requires The Magic of Higher-Rank Trait Bounds. The way we desugar -this is as follows: +This job requires The Magic of Higher-Rank Trait Bounds (HRTBs). The way we +desugar this is as follows: ```rust,ignore where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, ``` -(Where `Fn(a, b, c) -> d` is itself just sugar for the unstable *real* Fn trait) +(Where `Fn(a, b, c) -> d` is itself just sugar for the unstable *real* `Fn` +trait) `for<'a>` can be read as "for all choices of `'a`", and basically produces an -*inifinite list* of trait bounds that F must satisfy. Intense. There aren't many -places outside of the Fn traits where we encounter HRTBs, and even for those we -have a nice magic sugar for the common cases. +*infinite list* of trait bounds that F must satisfy. Intense. There aren't many +places outside of the `Fn` traits where we encounter HRTBs, and even for +those we have a nice magic sugar for the common cases. diff --git a/src/doc/tarpl/lifetime-splitting.md b/src/doc/tarpl/lifetime-splitting.md index 9b6b769520fa..e320c5c7b6b6 100644 --- a/src/doc/tarpl/lifetime-splitting.md +++ b/src/doc/tarpl/lifetime-splitting.md @@ -52,16 +52,17 @@ In order to "teach" borrowck that what we're doing is ok, we need to drop down to unsafe code. For instance, mutable slices expose a `split_at_mut` function that consumes the slice and returns *two* mutable slices. One for everything to the left of the index, and one for everything to the right. Intuitively we know -this is safe because the slices don't alias. However the implementation requires -some unsafety: +this is safe because the slices don't overlap, and therefore alias. However +the implementation requires some unsafety: ```rust,ignore fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + let len = self.len(); + let ptr = self.as_mut_ptr(); + assert!(mid <= len); unsafe { - let self2: &mut [T] = mem::transmute_copy(&self); - - (ops::IndexMut::index_mut(self, ops::RangeTo { end: mid } ), - ops::IndexMut::index_mut(self2, ops::RangeFrom { start: mid } )) + (from_raw_parts_mut(ptr, mid), + from_raw_parts_mut(ptr.offset(mid as isize), len - mid)) } } ``` diff --git a/src/doc/tarpl/lifetimes.md b/src/doc/tarpl/lifetimes.md index f4475b738509..5d7b305982fb 100644 --- a/src/doc/tarpl/lifetimes.md +++ b/src/doc/tarpl/lifetimes.md @@ -7,11 +7,10 @@ the scope it's valid for. Within a function body, Rust generally doesn't let you explicitly name the lifetimes involved. This is because it's generally not really *necessary* -to talk about lifetimes in a local context; rust has all the information and -can work out everything. It's also a good thing because the scope of a borrow -is often significantly smaller than the scope its referent is *actually* valid -for. Rust will introduce *many* anonymous scopes and temporaries to make your -code *just work*. +to talk about lifetimes in a local context; Rust has all the information and +can work out everything as optimally as possible. Many anonymous scopes and +temporaries that you would otherwise have to write are often introduced to +make your code *just work*. However once you cross the function boundary, you need to start talking about lifetimes. Lifetimes are denoted with an apostrophe: `'a`, `'static`. To dip @@ -19,10 +18,10 @@ our toes with lifetimes, we're going to pretend that we're actually allowed to label scopes with lifetimes, and desugar the examples from the start of this chapter. -Originally, our examples made use of *aggressive* sugar -- high fructose corn syrup even -- -around scopes and lifetimes, because writing everything out explicitly is -*extremely noisy*. All Rust code relies on aggressive inference and elision of -"obvious" things. +Originally, our examples made use of *aggressive* sugar -- high fructose corn +syrup even -- around scopes and lifetimes, because writing everything out +explicitly is *extremely noisy*. All Rust code relies on aggressive inference +and elision of "obvious" things. One particularly interesting piece of sugar is that each `let` statement implicitly introduces a scope. For the most part, this doesn't really matter. However it diff --git a/src/doc/tarpl/safe-unsafe-meaning.md b/src/doc/tarpl/safe-unsafe-meaning.md index c7210f8e2cf9..1a4e5b8ffad1 100644 --- a/src/doc/tarpl/safe-unsafe-meaning.md +++ b/src/doc/tarpl/safe-unsafe-meaning.md @@ -125,13 +125,13 @@ unsafe impl UnsafeOrd for MyType { But it's probably not the implementation you want. Rust has traditionally avoided making traits unsafe because it makes Unsafe -pervasive, which is not desirable. Send and Sync are unsafe is because -thread safety is a *fundamental property* that Unsafe cannot possibly hope to -defend against in the same way it would defend against a bad Ord implementation. -The only way to possibly defend against thread-unsafety would be to *not use -threading at all*. Making every operation atomic isn't even sufficient, because -it's possible for complex invariants to exist between disjoint locations in -memory. For instance, the pointer and capacity of a Vec must be in sync. +pervasive, which is not desirable. Send and Sync are unsafe is because thread +safety is a *fundamental property* that Unsafe cannot possibly hope to defend +against in the same way it would defend against a bad Ord implementation. The +only way to possibly defend against thread-unsafety would be to *not use +threading at all*. Making every load and store atomic isn't even sufficient, +because it's possible for complex invariants to exist between disjoint locations +in memory. For instance, the pointer and capacity of a Vec must be in sync. Even concurrent paradigms that are traditionally regarded as Totally Safe like message passing implicitly rely on some notion of thread safety -- are you diff --git a/src/doc/tarpl/subtyping.md b/src/doc/tarpl/subtyping.md index 8c5ac9cca6b3..975d1c59c76d 100644 --- a/src/doc/tarpl/subtyping.md +++ b/src/doc/tarpl/subtyping.md @@ -33,7 +33,7 @@ Variance is where things get a bit complicated. Variance is a property that *type constructors* have with respect to their arguments. A type constructor in Rust is a generic type with unbound arguments. For instance `Vec` is a type constructor that takes a `T` and returns a -`Vec`. `&` and `&mut` are type constructors that take a two types: a +`Vec`. `&` and `&mut` are type constructors that take two inputs: a lifetime, and a type to point to. A type constructor's *variance* is how the subtyping of its inputs affects the @@ -54,7 +54,8 @@ Some important variances: * `&'a T` is variant over `'a` and `T` (as is `*const T` by metaphor) * `&'a mut T` is variant with over `'a` but invariant over `T` * `Fn(T) -> U` is invariant over `T`, but variant over `U` -* `Box`, `Vec`, and all other collections are variant over their contents +* `Box`, `Vec`, and all other collections are variant over the types of + their contents * `UnsafeCell`, `Cell`, `RefCell`, `Mutex` and all other interior mutability types are invariant over T (as is `*mut T` by metaphor) @@ -71,7 +72,7 @@ to be able to pass `&&'static str` where an `&&'a str` is expected. The additional level of indirection does not change the desire to be able to pass longer lived things where shorted lived things are expected. -However this logic *does not* apply to see why `&mut`. To see why &mut should +However this logic *does not* apply to `&mut`. To see why `&mut` should be invariant over T, consider the following code: ```rust,ignore @@ -117,8 +118,9 @@ in them *via a mutable reference*! The mutable reference makes the whole type invariant, and therefore prevents you from smuggling a short-lived type into them. -Being variant *does* allows them to be weakened when shared immutably. -So you can pass a `&Box<&'static str>` where a `&Box<&'a str>` is expected. +Being variant *does* allows `Box` and `Vec` to be weakened when shared +immutably. So you can pass a `&Box<&'static str>` where a `&Box<&'a str>` is +expected. However what should happen when passing *by-value* is less obvious. It turns out that, yes, you can use subtyping when passing by-value. That is, this works: @@ -178,7 +180,7 @@ fn foo(usize) -> &'static str; in its place. Therefore functions *are* variant over their return type. `*const` has the exact same semantics as `&`, so variance follows. `*mut` on the -other hand can dereference to an &mut whether shared or not, so it is marked +other hand can dereference to an `&mut` whether shared or not, so it is marked as invariant just like cells. This is all well and good for the types the standard library provides, but diff --git a/src/doc/tarpl/unchecked-uninit.md b/src/doc/tarpl/unchecked-uninit.md index 9ab97b9e2d2d..d0397c371908 100644 --- a/src/doc/tarpl/unchecked-uninit.md +++ b/src/doc/tarpl/unchecked-uninit.md @@ -26,7 +26,7 @@ returns a pointer to uninitialized memory. To handle this, we must use the `ptr` module. In particular, it provides three functions that allow us to assign bytes to a location in memory without -evaluating the old value: `write`, `copy`, and `copy_nonoverlapping`. +dropping the old value: `write`, `copy`, and `copy_nonoverlapping`. * `ptr::write(ptr, val)` takes a `val` and moves it into the address pointed to by `ptr`. @@ -35,7 +35,7 @@ evaluating the old value: `write`, `copy`, and `copy_nonoverlapping`. order is reversed!) * `ptr::copy_nonoverlapping(src, dest, count)` does what `copy` does, but a little faster on the assumption that the two ranges of memory don't overlap. - (this is equivalent to memcopy -- note that the argument order is reversed!) + (this is equivalent to memcpy -- note that the argument order is reversed!) It should go without saying that these functions, if misused, will cause serious havoc or just straight up Undefined Behaviour. The only things that these @@ -68,14 +68,14 @@ unsafe { println!("{:?}", x); ``` -It's worth noting that you don't need to worry about ptr::write-style -shenanigans with types which don't implement Drop or -contain Drop types, because Rust knows not to try to Drop them. Similarly you -should be able to assign to fields of partially initialized structs -directly if those fields don't contain any Drop types. +It's worth noting that you don't need to worry about `ptr::write`-style +shenanigans with types which don't implement `Drop` or contain `Drop` types, +because Rust knows not to try to drop them. Similarly you should be able to +assign to fields of partially initialized structs directly if those fields don't +contain any `Drop` types. However when working with uninitialized memory you need to be ever-vigilant for -Rust trying to Drop values you make like this before they're fully initialized. +Rust trying to drop values you make like this before they're fully initialized. Every control path through that variable's scope must initialize the value before it ends, if has a destructor. *[This includes code panicking](unwinding.html)*. From b93438f648233ccdc98d80bcba53d78f672522f9 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 28 Jul 2015 15:16:59 -0700 Subject: [PATCH 100/104] fix incorrect name --- src/doc/tarpl/lifetimes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/tarpl/lifetimes.md b/src/doc/tarpl/lifetimes.md index 5d7b305982fb..37d035733613 100644 --- a/src/doc/tarpl/lifetimes.md +++ b/src/doc/tarpl/lifetimes.md @@ -137,7 +137,7 @@ fn main() { // need to last for the whole scope x is valid for. The return // of as_str must find a str somewhere *before* this function // call. Obviously not happening. - println!("{}", as_str::<'d>(&'d temp)); + println!("{}", as_str::<'d>(&'d x)); } } } From 9123bb02ca3d71e16ce3e4a2ebb1fca49fcd93e2 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 28 Jul 2015 15:38:39 -0700 Subject: [PATCH 101/104] fix borrow-splitting --- src/doc/tarpl/SUMMARY.md | 2 +- .../{lifetime-splitting.md => borrow-splitting.md} | 7 +++---- src/doc/tarpl/unchecked-uninit.md | 10 +++++----- 3 files changed, 9 insertions(+), 10 deletions(-) rename src/doc/tarpl/{lifetime-splitting.md => borrow-splitting.md} (97%) diff --git a/src/doc/tarpl/SUMMARY.md b/src/doc/tarpl/SUMMARY.md index a7014d7f0207..aeab8fc72769 100644 --- a/src/doc/tarpl/SUMMARY.md +++ b/src/doc/tarpl/SUMMARY.md @@ -17,7 +17,7 @@ * [Subtyping and Variance](subtyping.md) * [Drop Check](dropck.md) * [PhantomData](phantom-data.md) - * [Splitting Lifetimes](lifetime-splitting.md) + * [Splitting Borrows](borrow-splitting.md) * [Type Conversions](conversions.md) * [Coercions](coercions.md) * [The Dot Operator](dot-operator.md) diff --git a/src/doc/tarpl/lifetime-splitting.md b/src/doc/tarpl/borrow-splitting.md similarity index 97% rename from src/doc/tarpl/lifetime-splitting.md rename to src/doc/tarpl/borrow-splitting.md index e320c5c7b6b6..fe5f2343dec5 100644 --- a/src/doc/tarpl/lifetime-splitting.md +++ b/src/doc/tarpl/borrow-splitting.md @@ -1,4 +1,4 @@ -% Splitting Lifetimes +% Splitting Borrows The mutual exclusion property of mutable references can be very limiting when working with a composite structure. The borrow checker understands some basic @@ -67,9 +67,8 @@ fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { } ``` -This is pretty plainly dangerous. We use transmute to duplicate the slice with -an *unbounded* lifetime, so that it can be treated as disjoint from the other -until we unify them when we return. +This is actually a bit subtle. So as to avoid ever making two `&mut`'s to the +same value, we explicitly construct brand-new slices through raw pointers. However more subtle is how iterators that yield mutable references work. The iterator trait is defined as follows: diff --git a/src/doc/tarpl/unchecked-uninit.md b/src/doc/tarpl/unchecked-uninit.md index d0397c371908..da9fb294a1ea 100644 --- a/src/doc/tarpl/unchecked-uninit.md +++ b/src/doc/tarpl/unchecked-uninit.md @@ -15,11 +15,11 @@ initialization. Unfortunately, this opens us up to all kinds of problems. Assignment has a different meaning to Rust based on whether it believes that a variable is -initialized or not. If it's uninitialized, then Rust will semantically just -memcopy the bits over the uninitialized ones, and do nothing else. However if Rust -believes a value to be initialized, it will try to `Drop` the old value! -Since we've tricked Rust into believing that the value is initialized, we -can no longer safely use normal assignment. +initialized or not. If it's believed uninitialized, then Rust will semantically +just memcopy the bits over the uninitialized ones, and do nothing else. However +if Rust believes a value to be initialized, it will try to `Drop` the old value! +Since we've tricked Rust into believing that the value is initialized, we can no +longer safely use normal assignment. This is also a problem if you're working with a raw system allocator, which returns a pointer to uninitialized memory. From b539906de1d12dc935a1c3db9e511518dddabb3d Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 28 Jul 2015 15:41:58 -0700 Subject: [PATCH 102/104] clarify subtyping --- src/doc/tarpl/subtyping.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/tarpl/subtyping.md b/src/doc/tarpl/subtyping.md index 975d1c59c76d..767a0aca542f 100644 --- a/src/doc/tarpl/subtyping.md +++ b/src/doc/tarpl/subtyping.md @@ -1,9 +1,9 @@ % Subtyping and Variance -Although Rust doesn't have any notion of inheritance, it *does* include -subtyping. In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes -are scopes, we can partially order them based on the *contains* (outlives) -relationship. We can even express this as a generic bound. +Although Rust doesn't have any notion of structural inheritance, it *does* +include subtyping. In Rust, subtyping derives entirely from *lifetimes*. Since +lifetimes are scopes, we can partially order them based on the *contains* +(outlives) relationship. We can even express this as a generic bound. Subtyping on lifetimes in terms of that relationship: if `'a: 'b` ("a contains b" or "a outlives b"), then `'a` is a subtype of `'b`. This is a large source of From 4c48ffa53e7b9aa008bed5ac92a8362c0574172e Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 29 Jul 2015 15:55:19 -0700 Subject: [PATCH 103/104] add warning about reference section --- src/doc/tarpl/references.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/doc/tarpl/references.md b/src/doc/tarpl/references.md index da70dd529078..3d7369eca0fe 100644 --- a/src/doc/tarpl/references.md +++ b/src/doc/tarpl/references.md @@ -22,6 +22,10 @@ what *aliased* means. To define aliasing, we must define the notion of *paths* and *liveness*. +**NOTE: The model that follows is generally agreed to be dubious and have +issues. It's ok-ish as an intuitive model, but fails to capture the desired +semantics. We leave this here to be able to use notions introduced here in later +sections. This will be significantly changed in the future. TODO: do that.** # Paths From ddb029034b734ec078589724c45e6eb8bf2e6645 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 29 Jul 2015 17:15:11 -0700 Subject: [PATCH 104/104] fix example code --- src/doc/tarpl/borrow-splitting.md | 4 +++- src/doc/tarpl/dropck.md | 6 +++--- src/doc/tarpl/leaking.md | 2 +- src/doc/tarpl/safe-unsafe-meaning.md | 2 +- src/doc/tarpl/vec-layout.md | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/doc/tarpl/borrow-splitting.md b/src/doc/tarpl/borrow-splitting.md index fe5f2343dec5..123e2baf8faf 100644 --- a/src/doc/tarpl/borrow-splitting.md +++ b/src/doc/tarpl/borrow-splitting.md @@ -137,6 +137,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { Here's a mutable slice: ```rust +# fn main() {} use std::mem; pub struct IterMut<'a, T: 'a>(&'a mut[T]); @@ -170,6 +171,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { And here's a binary tree: ```rust +# fn main() {} use std::collections::VecDeque; type Link = Option>>; @@ -262,7 +264,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { } impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { - fn next(&mut self) -> Option { + fn next_back(&mut self) -> Option { loop { match self.0.back_mut().and_then(|node_it| node_it.next_back()) { Some(State::Elem(elem)) => return Some(elem), diff --git a/src/doc/tarpl/dropck.md b/src/doc/tarpl/dropck.md index 419c61281d9f..c75bf8b11794 100644 --- a/src/doc/tarpl/dropck.md +++ b/src/doc/tarpl/dropck.md @@ -8,12 +8,12 @@ when we talked about `'a: 'b`, it was ok for `'a` to live *exactly* as long as gets dropped at the same time as another, right? This is why we used the following desugarring of `let` statements: -```rust +```rust,ignore let x; let y; ``` -```rust +```rust,ignore { let x; { @@ -25,7 +25,7 @@ let y; Each creates its own scope, clearly establishing that one drops before the other. However, what if we do the following? -```rust +```rust,ignore let (x, y) = (vec![], vec![]); ``` diff --git a/src/doc/tarpl/leaking.md b/src/doc/tarpl/leaking.md index dcb03b1c8b6a..343de99f08ad 100644 --- a/src/doc/tarpl/leaking.md +++ b/src/doc/tarpl/leaking.md @@ -188,7 +188,7 @@ data on their parent's stack without any synchronization over that data by ensuring the parent joins the thread before any of the shared data goes out of scope. -```rust +```rust,ignore pub fn scoped<'a, F>(f: F) -> JoinGuard<'a> where F: FnOnce() + Send + 'a ``` diff --git a/src/doc/tarpl/safe-unsafe-meaning.md b/src/doc/tarpl/safe-unsafe-meaning.md index 1a4e5b8ffad1..909308397d71 100644 --- a/src/doc/tarpl/safe-unsafe-meaning.md +++ b/src/doc/tarpl/safe-unsafe-meaning.md @@ -114,7 +114,7 @@ implementation: ```rust # use std::cmp::Ordering; # struct MyType; -# pub unsafe trait UnsafeOrd { fn cmp(&self, other: &Self) -> Ordering; } +# unsafe trait UnsafeOrd { fn cmp(&self, other: &Self) -> Ordering; } unsafe impl UnsafeOrd for MyType { fn cmp(&self, other: &Self) -> Ordering { Ordering::Equal diff --git a/src/doc/tarpl/vec-layout.md b/src/doc/tarpl/vec-layout.md index 325399d622b6..3df63d5249c5 100644 --- a/src/doc/tarpl/vec-layout.md +++ b/src/doc/tarpl/vec-layout.md @@ -12,7 +12,6 @@ pub struct Vec { cap: usize, len: usize, } - # fn main() {} ``` @@ -69,6 +68,7 @@ impl Deref for Unique { unsafe { mem::transmute(&self.ptr) } } } +# fn main() {} ``` Unfortunately the mechanism for stating that your value is non-zero is