diff --git a/FiraSans-Medium.woff b/FiraSans-Medium.woff new file mode 100644 index 000000000000..5627227744ae Binary files /dev/null and b/FiraSans-Medium.woff differ diff --git a/FiraSans-Regular.woff b/FiraSans-Regular.woff new file mode 100644 index 000000000000..9ff40445bf4a Binary files /dev/null and b/FiraSans-Regular.woff differ diff --git a/Heuristica-Italic.woff b/Heuristica-Italic.woff new file mode 100644 index 000000000000..b0cebf01de49 Binary files /dev/null and b/Heuristica-Italic.woff differ 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 000000000000..5576670903ae Binary files /dev/null and b/SourceCodePro-Regular.woff differ diff --git a/SourceCodePro-Semibold.woff b/SourceCodePro-Semibold.woff new file mode 100644 index 000000000000..ca972a11dc42 Binary files /dev/null and b/SourceCodePro-Semibold.woff differ diff --git a/SourceSerifPro-Bold.woff b/SourceSerifPro-Bold.woff new file mode 100644 index 000000000000..ac1b1b3a0bb7 Binary files /dev/null and b/SourceSerifPro-Bold.woff differ diff --git a/SourceSerifPro-Regular.woff b/SourceSerifPro-Regular.woff new file mode 100644 index 000000000000..e8c43b852e10 Binary files /dev/null and b/SourceSerifPro-Regular.woff differ diff --git a/intro.md b/intro.md deleted file mode 100644 index 939ba4fa2129..000000000000 --- a/intro.md +++ /dev/null @@ -1,267 +0,0 @@ -% 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). -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. - - - - -# Chapters - -* [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) -* [Example: Implementing Vec](vec.html) - - - - -# 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. - 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