├── .editorconfig ├── .gitignore ├── .travis.yml ├── Cargo.lock ├── Cargo.toml ├── Readme.md ├── build.sh ├── dist └── .gitignore ├── lib ├── epub.css ├── index.css ├── index_template.html ├── pandoc.css ├── template.html └── template.tex ├── nomicon ├── README.md ├── SUMMARY.md ├── arc-and-mutex.md ├── atomics.md ├── borrow-splitting.md ├── casts.md ├── checked-uninit.md ├── coercions.md ├── concurrency.md ├── constructors.md ├── conversions.md ├── data.md ├── destructors.md ├── dot-operator.md ├── drop-flags.md ├── dropck.md ├── exception-safety.md ├── exotic-sizes.md ├── hrtb.md ├── leaking.md ├── lifetime-elision.md ├── lifetime-mismatch.md ├── lifetimes.md ├── meet-safe-and-unsafe.md ├── obrm.md ├── other-reprs.md ├── ownership.md ├── phantom-data.md ├── poisoning.md ├── races.md ├── references.md ├── repr-rust.md ├── safe-unsafe-meaning.md ├── send-and-sync.md ├── subtyping.md ├── transmutes.md ├── unbounded-lifetimes.md ├── unchecked-uninit.md ├── uninitialized.md ├── unwinding.md ├── vec-alloc.md ├── vec-dealloc.md ├── vec-deref.md ├── vec-drain.md ├── vec-final.md ├── vec-insert-remove.md ├── vec-into-iter.md ├── vec-layout.md ├── vec-push-pop.md ├── vec-raw.md ├── vec-zsts.md ├── vec.md └── working-with-unsafe.md ├── nomicon_meta.yml ├── src ├── convert_book │ ├── index.rs │ ├── markdown.rs │ ├── mod.rs │ ├── options.rs │ └── pandoc.rs ├── helpers │ ├── adjust_header_level.rs │ ├── adjust_reference_names.rs │ ├── convert_checkmarks.rs │ ├── file.rs │ ├── line_breaks.rs │ ├── mod.rs │ ├── normalize.rs │ ├── normalize_code_blocks.rs │ ├── remove_emojis.rs │ ├── remove_file_title.rs │ └── shell_pipe.rs └── main.rs ├── trpl ├── README.md ├── SUMMARY.md ├── advanced-linking.md ├── associated-constants.md ├── associated-types.md ├── attributes.md ├── benchmark-tests.md ├── bibliography.md ├── borrow-and-asref.md ├── box-syntax-and-patterns.md ├── casting-between-types.md ├── choosing-your-guarantees.md ├── closures.md ├── comments.md ├── compiler-plugins.md ├── concurrency.md ├── conditional-compilation.md ├── const-and-static.md ├── crates-and-modules.md ├── custom-allocators.md ├── deref-coercions.md ├── documentation.md ├── drop.md ├── effective-rust.md ├── enums.md ├── error-handling.md ├── ffi.md ├── functions.md ├── generics.md ├── getting-started.md ├── glossary.md ├── guessing-game.md ├── if-let.md ├── if.md ├── inline-assembly.md ├── intrinsics.md ├── iterators.md ├── lang-items.md ├── lifetimes.md ├── loops.md ├── macros.md ├── match.md ├── method-syntax.md ├── mutability.md ├── nightly-rust.md ├── no-stdlib.md ├── operators-and-overloading.md ├── ownership.md ├── patterns.md ├── primitive-types.md ├── raw-pointers.md ├── references-and-borrowing.md ├── release-channels.md ├── slice-patterns.md ├── strings.md ├── structs.md ├── syntax-and-semantics.md ├── syntax-index.md ├── testing.md ├── the-stack-and-the-heap.md ├── trait-objects.md ├── traits.md ├── type-aliases.md ├── ufcs.md ├── unsafe.md ├── unsized-types.md ├── using-rust-without-the-standard-library.md ├── variable-bindings.md └── vectors.md └── trpl_meta.yml /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | indent_style = space 14 | indent_size = 4 15 | 16 | [*.rs] 17 | indent_style = space 18 | indent_size = 4 19 | 20 | [*.toml] 21 | indent_style = space 22 | indent_size = 4 23 | 24 | [*.md] 25 | trim_trailing_whitespace = false 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | log.json 3 | .DS_Store 4 | dist/ 5 | *.bk 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | notifications: 5 | email: 6 | on_success: never 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "compile-trpl" 3 | version = "0.1.1" 4 | authors = ["Pascal Hertleif "] 5 | 6 | [features] 7 | default = [] 8 | dev = ["clippy"] 9 | 10 | [dependencies] 11 | regex = "0.1.32" 12 | docopt = "0.6.69" 13 | rustc-serialize = "0.3" 14 | 15 | [dependencies.clippy] 16 | git = "https://github.com/Manishearth/rust-clippy.git" 17 | optional = true 18 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # 'The Rust Programming Language' as EBook 2 | 3 | This repository contains stuff to convert [this book](http://doc.rust-lang.org/book/) to HTML, EPUB and PDF. 4 | 5 | **[Download Links](http://killercup.github.io/trpl-ebook/)** 6 | 7 | [![Build Status](https://travis-ci.org/killercup/trpl-ebook.svg?branch=master)](https://travis-ci.org/killercup/trpl-ebook) 8 | 9 | ## DIY 10 | 11 | Install: 12 | 13 | - pandoc 14 | - Rust and cargo 15 | - XeLaTeX, up to date (`sudo tlmgr update -all`) and probably some additional packages (`sudo tlmgr install $pkg`) such as: 16 | + framed 17 | + hyphenat 18 | + quotchap 19 | + collection-fontsrecommended 20 | + mathspec 21 | + euenc 22 | + xltxtra 23 | + xecjk 24 | + fancyhdr 25 | - the DejaVu Sans Mono font: http://dejavu-fonts.org/ 26 | - the IPA font for Japanese Text: http://ipafont.ipa.go.jp/ipaexfont/download.html#en 27 | 28 | Then run: 29 | 30 | ```sh 31 | $ cargo run --release 32 | ``` 33 | 34 | Voilà! 35 | 36 | ## Build different books 37 | 38 | There are some CLI arguments that you can use to compile books other than the default (`trpl`). E.g., this repository also include the Rustonomicon. 39 | 40 | You can build it like this: 41 | 42 | ```sh 43 | $ cargo run --release -- --prefix=nomicon --source=nomicon --meta=nomicon_meta.yml 44 | ``` 45 | 46 | ## License 47 | 48 | The book content itself as well as any code I added as part of this repository is Copyright (c) 2015 The Rust Project Developers and licensed like Rust itself ([MIT](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT) and [Apache](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE)). 49 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | RUN="cargo run --release --" 4 | 5 | $RUN --prefix=trpl --source=trpl --meta=trpl_meta.yml && \ 6 | $RUN --prefix=nomicon --source=nomicon --meta=nomicon_meta.yml 7 | -------------------------------------------------------------------------------- /dist/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /lib/epub.css: -------------------------------------------------------------------------------- 1 | /* based on https://github.com/jgm/pandoc/blob/c9cb313a479f3d134d5df1cffe5e340034fb44b4/data/epub.css */ 2 | body { margin: 5%; text-align: justify; font-size: medium; } 3 | code { font-family: monospace; word-wrap: break-word } 4 | h1 { text-align: left; } 5 | h2 { text-align: left; } 6 | h3 { text-align: left; } 7 | h4 { text-align: left; } 8 | h5 { text-align: left; } 9 | h6 { text-align: left; } 10 | h1.title { } 11 | h2.author { } 12 | h3.date { } 13 | ol.toc { padding: 0; margin-left: 1em; } 14 | ol.toc li { list-style-type: none; margin: 0; padding: 0; } 15 | a.footnoteRef { vertical-align: super; } 16 | 17 | pre { text-align: left; white-space: pre-wrap; font-size: 0.6em; } 18 | -------------------------------------------------------------------------------- /lib/index.css: -------------------------------------------------------------------------------- 1 | body { max-width: 40em; margin: 6em auto 2em; font-size: 16px; font-family: sans-serif; line-height: 1.3; padding: 0.6em; } 2 | @media screen and (max-width:800px){ 3 | body { margin-top: 1em;} 4 | } 5 | article, header, footer, aside { display: block; } 6 | li { margin-bottom: 0.5em; } 7 | footer { text-align: center; margin-top: 4em; font-size: 0.8em; } 8 | aside { position: absolute; top: 0; right: 0; border: 0; } 9 | aside img { border: 0; } 10 | 11 | /* from https://codepo8.github.io/css-fork-on-github-ribbon/ */ 12 | #forkongithub a{background:#666;color:#fff;text-decoration:none;font-family:arial,sans-serif;text-align:center;font-weight:bold;padding:5px 40px;font-size:1rem;line-height:2rem;position:relative;transition:0.2s;} 13 | #forkongithub a:hover{background:#000;color:#fff;} 14 | #forkongithub a::before,#forkongithub a::after{content:"";width:100%;display:block;position:absolute;top:1px;left:0;height:1px;background:#fff;} 15 | #forkongithub a::after{bottom:1px;top:auto;} 16 | @media screen and (min-width:800px){ 17 | #forkongithub{position:absolute;display:block;top:0;right:0;width:200px;overflow:hidden;height:200px;z-index:9999;} 18 | #forkongithub a{width:200px;position:absolute;top:60px;right:-60px;transform:rotate(45deg);-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);-moz-transform:rotate(45deg);-o-transform:rotate(45deg);box-shadow:2px 2px 5px rgba(0,0,0,0.3);} 19 | } 20 | -------------------------------------------------------------------------------- /lib/index_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Download 'The Rust Programming Language' E-Books (PDF, EPUB, MOBI) 6 | 7 | 10 | 11 | 12 |
13 |
14 |

'The Rust Programming Language' E-Books

15 | Fork me on GitHub 16 |
17 | 26 | 29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /lib/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $for(author-meta)$ 8 | 9 | $endfor$ 10 | $if(date-meta)$ 11 | 12 | $endif$ 13 | $if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ 14 | 17 | $if(highlighting-css)$ 18 | 21 | $endif$ 22 | $for(css)$ 23 | 24 | $endfor$ 25 | $if(math)$ 26 | $math$ 27 | $endif$ 28 | $for(header-includes)$ 29 | $header-includes$ 30 | $endfor$ 31 | 32 | 33 | 34 | $for(include-before)$ 35 | $include-before$ 36 | $endfor$ 37 | 38 | $if(title)$ 39 |
40 |

$title$

41 | 42 | $if(subtitle)$ 43 |

$subtitle$

44 | $endif$ 45 | 46 | 56 |
57 | $endif$ 58 | 59 | $if(abstract)$ 60 | 63 | $endif$ 64 | 65 | $if(toc)$ 66 | 70 | $endif$ 71 | 72 |
73 | $body$ 74 |
75 | 76 | $for(include-after)$ 77 | $include-after$ 78 | $endfor$ 79 | 80 | 81 | -------------------------------------------------------------------------------- /nomicon/README.md: -------------------------------------------------------------------------------- 1 | % The Rustonomicon 2 | 3 | #### The Dark Arts of Advanced and Unsafe Rust Programming 4 | 5 | **NOTE: This is a draft document, and may contain serious errors** 6 | 7 | > Instead of the programs I had hoped for, there came only a shuddering blackness 8 | and ineffable loneliness; and I saw at last a fearful truth which no one had 9 | ever dared to breathe before — the unwhisperable secret of secrets — The fact 10 | that this language of stone and stridor is not a sentient perpetuation of Rust 11 | as London is of Old London and Paris of Old Paris, but that it is in fact 12 | quite unsafe, its sprawling body imperfectly embalmed and infested with queer 13 | animate things which have nothing to do with it as it was in compilation. 14 | 15 | This book digs into all the awful details that are necessary to understand in 16 | order to write correct Unsafe Rust programs. Due to the nature of this problem, 17 | it may lead to unleashing untold horrors that shatter your psyche into a billion 18 | infinitesimal fragments of despair. 19 | 20 | Should you wish a long and happy career of writing Rust programs, you should 21 | turn back now and forget you ever saw this book. It is not necessary. However 22 | if you intend to write unsafe code -- or just want to dig into the guts of the 23 | language -- this book contains invaluable information. 24 | 25 | Unlike [The Book][trpl] we will be assuming considerable prior knowledge. In 26 | particular, you should be comfortable with basic systems programming and Rust. 27 | If you don't feel comfortable with these topics, you should consider [reading 28 | The Book][trpl] first. Though we will not be assuming that you have, and will 29 | take care to occasionally give a refresher on the basics where appropriate. You 30 | can skip straight to this book if you want; just know that we won't be 31 | explaining everything from the ground up. 32 | 33 | To be clear, this book goes into deep detail. We're going to dig into 34 | exception-safety, pointer aliasing, memory models, and even some type-theory. 35 | We will also be spending a lot of time talking about the different kinds 36 | of safety and guarantees. 37 | 38 | [trpl]: ../book/ 39 | -------------------------------------------------------------------------------- /nomicon/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Meet Safe and Unsafe](meet-safe-and-unsafe.md) 4 | * [How Safe and Unsafe Interact](safe-unsafe-meaning.md) 5 | * [Working with Unsafe](working-with-unsafe.md) 6 | * [Data Layout](data.md) 7 | * [repr(Rust)](repr-rust.md) 8 | * [Exotically Sized Types](exotic-sizes.md) 9 | * [Other reprs](other-reprs.md) 10 | * [Ownership](ownership.md) 11 | * [References](references.md) 12 | * [Lifetimes](lifetimes.md) 13 | * [Limits of Lifetimes](lifetime-mismatch.md) 14 | * [Lifetime Elision](lifetime-elision.md) 15 | * [Unbounded Lifetimes](unbounded-lifetimes.md) 16 | * [Higher-Rank Trait Bounds](hrtb.md) 17 | * [Subtyping and Variance](subtyping.md) 18 | * [Drop Check](dropck.md) 19 | * [PhantomData](phantom-data.md) 20 | * [Splitting Borrows](borrow-splitting.md) 21 | * [Type Conversions](conversions.md) 22 | * [Coercions](coercions.md) 23 | * [The Dot Operator](dot-operator.md) 24 | * [Casts](casts.md) 25 | * [Transmutes](transmutes.md) 26 | * [Uninitialized Memory](uninitialized.md) 27 | * [Checked](checked-uninit.md) 28 | * [Drop Flags](drop-flags.md) 29 | * [Unchecked](unchecked-uninit.md) 30 | * [Ownership Based Resource Management](obrm.md) 31 | * [Constructors](constructors.md) 32 | * [Destructors](destructors.md) 33 | * [Leaking](leaking.md) 34 | * [Unwinding](unwinding.md) 35 | * [Exception Safety](exception-safety.md) 36 | * [Poisoning](poisoning.md) 37 | * [Concurrency](concurrency.md) 38 | * [Races](races.md) 39 | * [Send and Sync](send-and-sync.md) 40 | * [Atomics](atomics.md) 41 | * [Implementing Vec](vec.md) 42 | * [Layout](vec-layout.md) 43 | * [Allocating](vec-alloc.md) 44 | * [Push and Pop](vec-push-pop.md) 45 | * [Deallocating](vec-dealloc.md) 46 | * [Deref](vec-deref.md) 47 | * [Insert and Remove](vec-insert-remove.md) 48 | * [IntoIter](vec-into-iter.md) 49 | * [RawVec](vec-raw.md) 50 | * [Drain](vec-drain.md) 51 | * [Handling Zero-Sized Types](vec-zsts.md) 52 | * [Final Code](vec-final.md) 53 | * [Implementing Arc and Mutex](arc-and-mutex.md) 54 | -------------------------------------------------------------------------------- /nomicon/arc-and-mutex.md: -------------------------------------------------------------------------------- 1 | % Implementing Arc and Mutex 2 | 3 | Knowing the theory is all fine and good, but the *best* way to understand 4 | something is to use it. To better understand atomics and interior mutability, 5 | we'll be implementing versions of the standard library's Arc and Mutex types. 6 | 7 | TODO: ALL OF THIS OMG 8 | -------------------------------------------------------------------------------- /nomicon/casts.md: -------------------------------------------------------------------------------- 1 | % Casts 2 | 3 | Casts are a superset of coercions: every coercion can be explicitly 4 | invoked via a cast. However some conversions require a cast. 5 | While coercions are pervasive and largely harmless, these "true casts" 6 | are rare and potentially dangerous. As such, casts must be explicitly invoked 7 | using the `as` keyword: `expr as Type`. 8 | 9 | True casts generally revolve around raw pointers and the primitive numeric 10 | types. Even though they're dangerous, these casts are infallible at runtime. 11 | If a cast triggers some subtle corner case no indication will be given that 12 | this occurred. The cast will simply succeed. That said, casts must be valid 13 | at the type level, or else they will be prevented statically. For instance, 14 | `7u8 as bool` will not compile. 15 | 16 | That said, casts aren't `unsafe` because they generally can't violate memory 17 | safety *on their own*. For instance, converting an integer to a raw pointer can 18 | very easily lead to terrible things. However the act of creating the pointer 19 | itself is safe, because actually using a raw pointer is already marked as 20 | `unsafe`. 21 | 22 | Here's an exhaustive list of all the true casts. For brevity, we will use `*` 23 | to denote either a `*const` or `*mut`, and `integer` to denote any integral 24 | primitive: 25 | 26 | * `*T as *U` where `T, U: Sized` 27 | * `*T as *U` TODO: explain unsized situation 28 | * `*T as integer` 29 | * `integer as *T` 30 | * `number as number` 31 | * `C-like-enum as integer` 32 | * `bool as integer` 33 | * `char as integer` 34 | * `u8 as char` 35 | * `&[T; n] as *const T` 36 | * `fn as *T` where `T: Sized` 37 | * `fn as integer` 38 | 39 | Note that lengths are not adjusted when casting raw slices - 40 | `*const [u16] as *const [u8]` creates a slice that only includes 41 | half of the original memory. 42 | 43 | Casting is not transitive, that is, even if `e as U1 as U2` is a valid 44 | expression, `e as U2` is not necessarily so. 45 | 46 | For numeric casts, there are quite a few cases to consider: 47 | 48 | * casting between two integers of the same size (e.g. i32 -> u32) is a no-op 49 | * casting from a larger integer to a smaller integer (e.g. u32 -> u8) will 50 | truncate 51 | * casting from a smaller integer to a larger integer (e.g. u8 -> u32) will 52 | * zero-extend if the source is unsigned 53 | * sign-extend if the source is signed 54 | * casting from a float to an integer will round the float towards zero 55 | * **[NOTE: currently this will cause Undefined Behavior if the rounded 56 | value cannot be represented by the target integer type][float-int]**. 57 | This includes Inf and NaN. This is a bug and will be fixed. 58 | * casting from an integer to float will produce the floating point 59 | representation of the integer, rounded if necessary (rounding strategy 60 | unspecified) 61 | * casting from an f32 to an f64 is perfect and lossless 62 | * casting from an f64 to an f32 will produce the closest possible value 63 | (rounding strategy unspecified) 64 | * **[NOTE: currently this will cause Undefined Behavior if the value 65 | is finite but larger or smaller than the largest or smallest finite 66 | value representable by f32][float-float]**. This is a bug and will 67 | be fixed. 68 | 69 | 70 | [float-int]: https://github.com/rust-lang/rust/issues/10184 71 | [float-float]: https://github.com/rust-lang/rust/issues/15536 72 | -------------------------------------------------------------------------------- /nomicon/checked-uninit.md: -------------------------------------------------------------------------------- 1 | % Checked Uninitialized Memory 2 | 3 | Like C, all stack variables in Rust are uninitialized until a value is 4 | explicitly assigned to them. Unlike C, Rust statically prevents you from ever 5 | reading them until you do: 6 | 7 | ```rust,ignore 8 | fn main() { 9 | let x: i32; 10 | println!("{}", x); 11 | } 12 | ``` 13 | 14 | ```text 15 | src/main.rs:3:20: 3:21 error: use of possibly uninitialized variable: `x` 16 | src/main.rs:3 println!("{}", x); 17 | ^ 18 | ``` 19 | 20 | This is based off of a basic branch analysis: every branch must assign a value 21 | to `x` before it is first used. Interestingly, Rust doesn't require the variable 22 | to be mutable to perform a delayed initialization if every branch assigns 23 | exactly once. However the analysis does not take advantage of constant analysis 24 | or anything like that. So this compiles: 25 | 26 | ```rust 27 | fn main() { 28 | let x: i32; 29 | 30 | if true { 31 | x = 1; 32 | } else { 33 | x = 2; 34 | } 35 | 36 | println!("{}", x); 37 | } 38 | ``` 39 | 40 | but this doesn't: 41 | 42 | ```rust,ignore 43 | fn main() { 44 | let x: i32; 45 | if true { 46 | x = 1; 47 | } 48 | println!("{}", x); 49 | } 50 | ``` 51 | 52 | ```text 53 | src/main.rs:6:17: 6:18 error: use of possibly uninitialized variable: `x` 54 | src/main.rs:6 println!("{}", x); 55 | ``` 56 | 57 | while this does: 58 | 59 | ```rust 60 | fn main() { 61 | let x: i32; 62 | if true { 63 | x = 1; 64 | println!("{}", x); 65 | } 66 | // Don't care that there are branches where it's not initialized 67 | // since we don't use the value in those branches 68 | } 69 | ``` 70 | 71 | Of course, while the analysis doesn't consider actual values, it does 72 | have a relatively sophisticated understanding of dependencies and control 73 | flow. For instance, this works: 74 | 75 | ```rust 76 | let x: i32; 77 | 78 | loop { 79 | // Rust doesn't understand that this branch will be taken unconditionally, 80 | // because it relies on actual values. 81 | if true { 82 | // But it does understand that it will only be taken once because 83 | // we unconditionally break out of it. Therefore `x` doesn't 84 | // need to be marked as mutable. 85 | x = 0; 86 | break; 87 | } 88 | } 89 | // It also knows that it's impossible to get here without reaching the break. 90 | // And therefore that `x` must be initialized here! 91 | println!("{}", x); 92 | ``` 93 | 94 | If a value is moved out of a variable, that variable becomes logically 95 | uninitialized if the type of the value isn't Copy. That is: 96 | 97 | ```rust 98 | fn main() { 99 | let x = 0; 100 | let y = Box::new(0); 101 | let z1 = x; // x is still valid because i32 is Copy 102 | let z2 = y; // y is now logically uninitialized because Box isn't Copy 103 | } 104 | ``` 105 | 106 | However reassigning `y` in this example *would* require `y` to be marked as 107 | mutable, as a Safe Rust program could observe that the value of `y` changed: 108 | 109 | ```rust 110 | fn main() { 111 | let mut y = Box::new(0); 112 | let z = y; // y is now logically uninitialized because Box isn't Copy 113 | y = Box::new(1); // reinitialize y 114 | } 115 | ``` 116 | 117 | Otherwise it's like `y` is a brand new variable. 118 | -------------------------------------------------------------------------------- /nomicon/coercions.md: -------------------------------------------------------------------------------- 1 | % Coercions 2 | 3 | Types can implicitly be coerced to change in certain contexts. These changes are 4 | generally just *weakening* of types, largely focused around pointers and 5 | lifetimes. They mostly exist to make Rust "just work" in more cases, and are 6 | largely harmless. 7 | 8 | Here's all the kinds of coercion: 9 | 10 | Coercion is allowed between the following types: 11 | 12 | * Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to 13 | `T_3` 14 | * Pointer Weakening: 15 | * `&mut T` to `&T` 16 | * `*mut T` to `*const T` 17 | * `&T` to `*const T` 18 | * `&mut T` to `*mut T` 19 | * Unsizing: `T` to `U` if `T` implements `CoerceUnsized` 20 | 21 | `CoerceUnsized> for Pointer where T: Unsize` is implemented 22 | for all pointer types (including smart pointers like Box and Rc). Unsize is 23 | only implemented automatically, and enables the following transformations: 24 | 25 | * `[T; n]` => `[T]` 26 | * `T` => `Trait` where `T: Trait` 27 | * `Foo<..., T, ...>` => `Foo<..., U, ...>` where: 28 | * `T: Unsize` 29 | * `Foo` is a struct 30 | * Only the last field of `Foo` has type `T` 31 | * `T` is not part of the type of any other fields 32 | 33 | Coercions occur at a *coercion site*. Any location that is explicitly typed 34 | will cause a coercion to its type. If inference is necessary, the coercion will 35 | not be performed. Exhaustively, the coercion sites for an expression `e` to 36 | type `U` are: 37 | 38 | * let statements, statics, and consts: `let x: U = e` 39 | * Arguments to functions: `takes_a_U(e)` 40 | * Any expression that will be returned: `fn foo() -> U { e }` 41 | * Struct literals: `Foo { some_u: e }` 42 | * Array literals: `let x: [U; 10] = [e, ..]` 43 | * Tuple literals: `let x: (U, ..) = (e, ..)` 44 | * The last expression in a block: `let x: U = { ..; e }` 45 | 46 | Note that we do not perform coercions when matching traits (except for 47 | receivers, see below). If there is an impl for some type `U` and `T` coerces to 48 | `U`, that does not constitute an implementation for `T`. For example, the 49 | following will not type check, even though it is OK to coerce `t` to `&T` and 50 | there is an impl for `&T`: 51 | 52 | ```rust,ignore 53 | trait Trait {} 54 | 55 | fn foo(t: X) {} 56 | 57 | impl<'a> Trait for &'a i32 {} 58 | 59 | 60 | fn main() { 61 | let t: &mut i32 = &mut 0; 62 | foo(t); 63 | } 64 | ``` 65 | 66 | ```text 67 | :10:5: 10:8 error: the trait bound `&mut i32 : Trait` is not satisfied [E0277] 68 | :10 foo(t); 69 | ^~~ 70 | ``` 71 | -------------------------------------------------------------------------------- /nomicon/concurrency.md: -------------------------------------------------------------------------------- 1 | % Concurrency and Parallelism 2 | 3 | Rust as a language doesn't *really* have an opinion on how to do concurrency or 4 | parallelism. The standard library exposes OS threads and blocking sys-calls 5 | because everyone has those, and they're uniform enough that you can provide 6 | an abstraction over them in a relatively uncontroversial way. Message passing, 7 | green threads, and async APIs are all diverse enough that any abstraction over 8 | them tends to involve trade-offs that we weren't willing to commit to for 1.0. 9 | 10 | However the way Rust models concurrency makes it relatively easy to design your own 11 | concurrency paradigm as a library and have everyone else's code Just Work 12 | with yours. Just require the right lifetimes and Send and Sync where appropriate 13 | and you're off to the races. Or rather, off to the... not... having... races. 14 | -------------------------------------------------------------------------------- /nomicon/constructors.md: -------------------------------------------------------------------------------- 1 | % Constructors 2 | 3 | There is exactly one way to create an instance of a user-defined type: name it, 4 | and initialize all its fields at once: 5 | 6 | ```rust 7 | struct Foo { 8 | a: u8, 9 | b: u32, 10 | c: bool, 11 | } 12 | 13 | enum Bar { 14 | X(u32), 15 | Y(bool), 16 | } 17 | 18 | struct Unit; 19 | 20 | let foo = Foo { a: 0, b: 1, c: false }; 21 | let bar = Bar::X(0); 22 | let empty = Unit; 23 | ``` 24 | 25 | That's it. Every other way you make an instance of a type is just calling a 26 | totally vanilla function that does some stuff and eventually bottoms out to The 27 | One True Constructor. 28 | 29 | Unlike C++, Rust does not come with a slew of built-in kinds of constructor. 30 | There are no Copy, Default, Assignment, Move, or whatever constructors. The 31 | reasons for this are varied, but it largely boils down to Rust's philosophy of 32 | *being explicit*. 33 | 34 | Move constructors are meaningless in Rust because we don't enable types to 35 | "care" about their location in memory. Every type must be ready for it to be 36 | blindly memcopied to somewhere else in memory. This means pure on-the-stack-but- 37 | still-movable intrusive linked lists are simply not happening in Rust (safely). 38 | 39 | Assignment and copy constructors similarly don't exist because move semantics 40 | are the only semantics in Rust. At most `x = y` just moves the bits of y into 41 | the x variable. Rust does provide two facilities for providing C++'s copy- 42 | oriented semantics: `Copy` and `Clone`. Clone is our moral equivalent of a copy 43 | constructor, but it's never implicitly invoked. You have to explicitly call 44 | `clone` on an element you want to be cloned. Copy is a special case of Clone 45 | where the implementation is just "copy the bits". Copy types *are* implicitly 46 | cloned whenever they're moved, but because of the definition of Copy this just 47 | means not treating the old copy as uninitialized -- a no-op. 48 | 49 | While Rust provides a `Default` trait for specifying the moral equivalent of a 50 | default constructor, it's incredibly rare for this trait to be used. This is 51 | because variables [aren't implicitly initialized][uninit]. Default is basically 52 | only useful for generic programming. In concrete contexts, a type will provide a 53 | static `new` method for any kind of "default" constructor. This has no relation 54 | to `new` in other languages and has no special meaning. It's just a naming 55 | convention. 56 | 57 | TODO: talk about "placement new"? 58 | 59 | [uninit]: uninitialized.html 60 | -------------------------------------------------------------------------------- /nomicon/conversions.md: -------------------------------------------------------------------------------- 1 | % Type Conversions 2 | 3 | At the end of the day, everything is just a pile of bits somewhere, and type 4 | systems are just there to help us use those bits right. There are two common 5 | problems with typing bits: needing to reinterpret those exact bits as a 6 | different type, and needing to change the bits to have equivalent meaning for 7 | a different type. Because Rust encourages encoding important properties in the 8 | type system, these problems are incredibly pervasive. As such, Rust 9 | consequently gives you several ways to solve them. 10 | 11 | First we'll look at the ways that Safe Rust gives you to reinterpret values. 12 | The most trivial way to do this is to just destructure a value into its 13 | constituent parts and then build a new type out of them. e.g. 14 | 15 | ```rust 16 | struct Foo { 17 | x: u32, 18 | y: u16, 19 | } 20 | 21 | struct Bar { 22 | a: u32, 23 | b: u16, 24 | } 25 | 26 | fn reinterpret(foo: Foo) -> Bar { 27 | let Foo { x, y } = foo; 28 | Bar { a: x, b: y } 29 | } 30 | ``` 31 | 32 | But this is, at best, annoying. For common conversions, Rust provides 33 | more ergonomic alternatives. 34 | 35 | -------------------------------------------------------------------------------- /nomicon/data.md: -------------------------------------------------------------------------------- 1 | % Data Representation in Rust 2 | 3 | Low-level programming cares a lot about data layout. It's a big deal. It also 4 | pervasively influences the rest of the language, so we're going to start by 5 | digging into how data is represented in Rust. 6 | -------------------------------------------------------------------------------- /nomicon/dot-operator.md: -------------------------------------------------------------------------------- 1 | % The Dot Operator 2 | 3 | The dot operator will perform a lot of magic to convert types. It will perform 4 | auto-referencing, auto-dereferencing, and coercion until types match. 5 | 6 | TODO: steal information from http://stackoverflow.com/questions/28519997/what-are-rusts-exact-auto-dereferencing-rules/28552082#28552082 7 | -------------------------------------------------------------------------------- /nomicon/drop-flags.md: -------------------------------------------------------------------------------- 1 | % Drop Flags 2 | 3 | The examples in the previous section introduce an interesting problem for Rust. 4 | We have seen that it's possible to conditionally initialize, deinitialize, and 5 | reinitialize locations of memory totally safely. For Copy types, this isn't 6 | particularly notable since they're just a random pile of bits. However types 7 | with destructors are a different story: Rust needs to know whether to call a 8 | destructor whenever a variable is assigned to, or a variable goes out of scope. 9 | How can it do this with conditional initialization? 10 | 11 | Note that this is not a problem that all assignments need worry about. In 12 | particular, assigning through a dereference unconditionally drops, and assigning 13 | in a `let` unconditionally doesn't drop: 14 | 15 | ``` 16 | let mut x = Box::new(0); // let makes a fresh variable, so never need to drop 17 | let y = &mut x; 18 | *y = Box::new(1); // Deref assumes the referent is initialized, so always drops 19 | ``` 20 | 21 | This is only a problem when overwriting a previously initialized variable or 22 | one of its subfields. 23 | 24 | It turns out that Rust actually tracks whether a type should be dropped or not 25 | *at runtime*. As a variable becomes initialized and uninitialized, a *drop flag* 26 | for that variable is toggled. When a variable might need to be dropped, this 27 | flag is evaluated to determine if it should be dropped. 28 | 29 | Of course, it is often the case that a value's initialization state can be 30 | statically known at every point in the program. If this is the case, then the 31 | compiler can theoretically generate more efficient code! For instance, straight- 32 | line code has such *static drop semantics*: 33 | 34 | ```rust 35 | let mut x = Box::new(0); // x was uninit; just overwrite. 36 | let mut y = x; // y was uninit; just overwrite and make x uninit. 37 | x = Box::new(0); // x was uninit; just overwrite. 38 | y = x; // y was init; Drop y, overwrite it, and make x uninit! 39 | // y goes out of scope; y was init; Drop y! 40 | // x goes out of scope; x was uninit; do nothing. 41 | ``` 42 | 43 | Similarly, branched code where all branches have the same behavior with respect 44 | to initialization has static drop semantics: 45 | 46 | ```rust 47 | # let condition = true; 48 | let mut x = Box::new(0); // x was uninit; just overwrite. 49 | if condition { 50 | drop(x) // x gets moved out; make x uninit. 51 | } else { 52 | println!("{}", x); 53 | drop(x) // x gets moved out; make x uninit. 54 | } 55 | x = Box::new(0); // x was uninit; just overwrite. 56 | // x goes out of scope; x was init; Drop x! 57 | ``` 58 | 59 | However code like this *requires* runtime information to correctly Drop: 60 | 61 | ```rust 62 | # let condition = true; 63 | let x; 64 | if condition { 65 | x = Box::new(0); // x was uninit; just overwrite. 66 | println!("{}", x); 67 | } 68 | // x goes out of scope; x might be uninit; 69 | // check the flag! 70 | ``` 71 | 72 | Of course, in this case it's trivial to retrieve static drop semantics: 73 | 74 | ```rust 75 | # let condition = true; 76 | if condition { 77 | let x = Box::new(0); 78 | println!("{}", x); 79 | } 80 | ``` 81 | 82 | As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden 83 | field of any type that implements Drop. Rust sets the drop flag by overwriting 84 | the entire value with a particular bit pattern. This is pretty obviously Not 85 | The Fastest and causes a bunch of trouble with optimizing code. It's legacy from 86 | a time when you could do much more complex conditional initialization. 87 | 88 | As such work is currently under way to move the flags out onto the stack frame 89 | where they more reasonably belong. Unfortunately, this work will take some time 90 | as it requires fairly substantial changes to the compiler. 91 | 92 | Regardless, Rust programs don't need to worry about uninitialized values on 93 | the stack for correctness. Although they might care for performance. Thankfully, 94 | Rust makes it easy to take control here! Uninitialized values are there, and 95 | you can work with them in Safe Rust, but you're never in danger. 96 | -------------------------------------------------------------------------------- /nomicon/hrtb.md: -------------------------------------------------------------------------------- 1 | % Higher-Rank Trait Bounds (HRTBs) 2 | 3 | Rust's `Fn` traits are a little bit magic. For instance, we can write the 4 | following code: 5 | 6 | ```rust 7 | struct Closure { 8 | data: (u8, u16), 9 | func: F, 10 | } 11 | 12 | impl Closure 13 | where F: Fn(&(u8, u16)) -> &u8, 14 | { 15 | fn call(&self) -> &u8 { 16 | (self.func)(&self.data) 17 | } 18 | } 19 | 20 | fn do_it(data: &(u8, u16)) -> &u8 { &data.0 } 21 | 22 | fn main() { 23 | let clo = Closure { data: (0, 1), func: do_it }; 24 | println!("{}", clo.call()); 25 | } 26 | ``` 27 | 28 | If we try to naively desugar this code in the same way that we did in the 29 | lifetimes section, we run into some trouble: 30 | 31 | ```rust,ignore 32 | struct Closure { 33 | data: (u8, u16), 34 | func: F, 35 | } 36 | 37 | impl Closure 38 | // where F: Fn(&'??? (u8, u16)) -> &'??? u8, 39 | { 40 | fn call<'a>(&'a self) -> &'a u8 { 41 | (self.func)(&self.data) 42 | } 43 | } 44 | 45 | fn do_it<'b>(data: &'b (u8, u16)) -> &'b u8 { &'b data.0 } 46 | 47 | fn main() { 48 | 'x: { 49 | let clo = Closure { data: (0, 1), func: do_it }; 50 | println!("{}", clo.call()); 51 | } 52 | } 53 | ``` 54 | 55 | How on earth are we supposed to express the lifetimes on `F`'s trait bound? We 56 | need to provide some lifetime there, but the lifetime we care about can't be 57 | named until we enter the body of `call`! Also, that isn't some fixed lifetime; 58 | `call` works with *any* lifetime `&self` happens to have at that point. 59 | 60 | This job requires The Magic of Higher-Rank Trait Bounds (HRTBs). The way we 61 | desugar this is as follows: 62 | 63 | ```rust,ignore 64 | where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, 65 | ``` 66 | 67 | (Where `Fn(a, b, c) -> d` is itself just sugar for the unstable *real* `Fn` 68 | trait) 69 | 70 | `for<'a>` can be read as "for all choices of `'a`", and basically produces an 71 | *infinite list* of trait bounds that F must satisfy. Intense. There aren't many 72 | places outside of the `Fn` traits where we encounter HRTBs, and even for 73 | those we have a nice magic sugar for the common cases. 74 | -------------------------------------------------------------------------------- /nomicon/lifetime-elision.md: -------------------------------------------------------------------------------- 1 | % Lifetime Elision 2 | 3 | In order to make common patterns more ergonomic, Rust allows lifetimes to be 4 | *elided* in function signatures. 5 | 6 | A *lifetime position* is anywhere you can write a lifetime in a type: 7 | 8 | ```rust,ignore 9 | &'a T 10 | &'a mut T 11 | T<'a> 12 | ``` 13 | 14 | Lifetime positions can appear as either "input" or "output": 15 | 16 | * For `fn` definitions, input refers to the types of the formal arguments 17 | in the `fn` definition, while output refers to 18 | result types. So `fn foo(s: &str) -> (&str, &str)` has elided one lifetime in 19 | input position and two lifetimes in output position. 20 | Note that the input positions of a `fn` method definition do not 21 | include the lifetimes that occur in the method's `impl` header 22 | (nor lifetimes that occur in the trait header, for a default method). 23 | 24 | * In the future, it should be possible to elide `impl` headers in the same manner. 25 | 26 | Elision rules are as follows: 27 | 28 | * Each elided lifetime in input position becomes a distinct lifetime 29 | parameter. 30 | 31 | * If there is exactly one input lifetime position (elided or not), that lifetime 32 | is assigned to *all* elided output lifetimes. 33 | 34 | * If there are multiple input lifetime positions, but one of them is `&self` or 35 | `&mut self`, the lifetime of `self` is assigned to *all* elided output lifetimes. 36 | 37 | * Otherwise, it is an error to elide an output lifetime. 38 | 39 | Examples: 40 | 41 | ```rust,ignore 42 | fn print(s: &str); // elided 43 | fn print<'a>(s: &'a str); // expanded 44 | 45 | fn debug(lvl: uint, s: &str); // elided 46 | fn debug<'a>(lvl: uint, s: &'a str); // expanded 47 | 48 | fn substr(s: &str, until: uint) -> &str; // elided 49 | fn substr<'a>(s: &'a str, until: uint) -> &'a str; // expanded 50 | 51 | fn get_str() -> &str; // ILLEGAL 52 | 53 | fn frob(s: &str, t: &str) -> &str; // ILLEGAL 54 | 55 | fn get_mut(&mut self) -> &mut T; // elided 56 | fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded 57 | 58 | fn args(&mut self, args: &[T]) -> &mut Command // elided 59 | fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded 60 | 61 | fn new(buf: &mut [u8]) -> BufWriter; // elided 62 | fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded 63 | 64 | ``` 65 | -------------------------------------------------------------------------------- /nomicon/lifetime-mismatch.md: -------------------------------------------------------------------------------- 1 | % Limits of Lifetimes 2 | 3 | Given the following code: 4 | 5 | ```rust,ignore 6 | struct Foo; 7 | 8 | impl Foo { 9 | fn mutate_and_share(&mut self) -> &Self { &*self } 10 | fn share(&self) {} 11 | } 12 | 13 | fn main() { 14 | let mut foo = Foo; 15 | let loan = foo.mutate_and_share(); 16 | foo.share(); 17 | } 18 | ``` 19 | 20 | One might expect it to compile. We call `mutate_and_share`, which mutably borrows 21 | `foo` temporarily, but then returns only a shared reference. Therefore we 22 | would expect `foo.share()` to succeed as `foo` shouldn't be mutably borrowed. 23 | 24 | However when we try to compile it: 25 | 26 | ```text 27 | :11:5: 11:8 error: cannot borrow `foo` as immutable because it is also borrowed as mutable 28 | :11 foo.share(); 29 | ^~~ 30 | :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 31 | :10 let loan = foo.mutate_and_share(); 32 | ^~~ 33 | :12:2: 12:2 note: previous borrow ends here 34 | :8 fn main() { 35 | :9 let mut foo = Foo; 36 | :10 let loan = foo.mutate_and_share(); 37 | :11 foo.share(); 38 | :12 } 39 | ^ 40 | ``` 41 | 42 | What happened? Well, we got the exact same reasoning as we did for 43 | [Example 2 in the previous section][ex2]. We desugar the program and we get 44 | the following: 45 | 46 | ```rust,ignore 47 | struct Foo; 48 | 49 | impl Foo { 50 | fn mutate_and_share<'a>(&'a mut self) -> &'a Self { &'a *self } 51 | fn share<'a>(&'a self) {} 52 | } 53 | 54 | fn main() { 55 | 'b: { 56 | let mut foo: Foo = Foo; 57 | 'c: { 58 | let loan: &'c Foo = Foo::mutate_and_share::<'c>(&'c mut foo); 59 | 'd: { 60 | Foo::share::<'d>(&'d foo); 61 | } 62 | } 63 | } 64 | } 65 | ``` 66 | 67 | The lifetime system is forced to extend the `&mut foo` to have lifetime `'c`, 68 | due to the lifetime of `loan` and mutate_and_share's signature. Then when we 69 | try to call `share`, and it sees we're trying to alias that `&'c mut foo` and 70 | blows up in our face! 71 | 72 | This program is clearly correct according to the reference semantics we actually 73 | care about, but the lifetime system is too coarse-grained to handle that. 74 | 75 | 76 | TODO: other common problems? SEME regions stuff, mostly? 77 | 78 | 79 | 80 | 81 | [ex2]: lifetimes.html#example-aliasing-a-mutable-reference 82 | -------------------------------------------------------------------------------- /nomicon/meet-safe-and-unsafe.md: -------------------------------------------------------------------------------- 1 | % Meet Safe and Unsafe 2 | 3 | Programmers in safe "high-level" languages face a fundamental dilemma. On one 4 | hand, it would be *really* great to just say what you want and not worry about 5 | how it's done. On the other hand, that can lead to unacceptably poor 6 | performance. It may be necessary to drop down to less clear or idiomatic 7 | practices to get the performance characteristics you want. Or maybe you just 8 | throw up your hands in disgust and decide to shell out to an implementation in 9 | a less sugary-wonderful *unsafe* language. 10 | 11 | Worse, when you want to talk directly to the operating system, you *have* to 12 | talk to an unsafe language: *C*. C is ever-present and unavoidable. It's the 13 | lingua-franca of the programming world. 14 | Even other safe languages generally expose C interfaces for the world at large! 15 | Regardless of why you're doing it, as soon as your program starts talking to 16 | C it stops being safe. 17 | 18 | With that said, Rust is *totally* a safe programming language. 19 | 20 | Well, Rust *has* a safe programming language. Let's step back a bit. 21 | 22 | Rust can be thought of as being composed of two programming languages: *Safe 23 | Rust* and *Unsafe Rust*. Safe Rust is For Reals Totally Safe. Unsafe Rust, 24 | unsurprisingly, is *not* For Reals Totally Safe. In fact, Unsafe Rust lets you 25 | do some really crazy unsafe things. 26 | 27 | Safe Rust is the *true* Rust programming language. If all you do is write Safe 28 | Rust, you will never have to worry about type-safety or memory-safety. You will 29 | never endure a null or dangling pointer, or any of that Undefined Behavior 30 | nonsense. 31 | 32 | *That's totally awesome.* 33 | 34 | The standard library also gives you enough utilities out-of-the-box that you'll 35 | be able to write awesome high-performance applications and libraries in pure 36 | idiomatic Safe Rust. 37 | 38 | But maybe you want to talk to another language. Maybe you're writing a 39 | low-level abstraction not exposed by the standard library. Maybe you're 40 | *writing* the standard library (which is written entirely in Rust). Maybe you 41 | need to do something the type-system doesn't understand and just *frob some dang 42 | bits*. Maybe you need Unsafe Rust. 43 | 44 | Unsafe Rust is exactly like Safe Rust with all the same rules and semantics. 45 | However Unsafe Rust lets you do some *extra* things that are Definitely Not Safe. 46 | 47 | The only things that are different in Unsafe Rust are that you can: 48 | 49 | * Dereference raw pointers 50 | * Call `unsafe` functions (including C functions, intrinsics, and the raw allocator) 51 | * Implement `unsafe` traits 52 | * Mutate statics 53 | 54 | That's it. The reason these operations are relegated to Unsafe is that misusing 55 | any of these things will cause the ever dreaded Undefined Behavior. Invoking 56 | Undefined Behavior gives the compiler full rights to do arbitrarily bad things 57 | to your program. You definitely *should not* invoke Undefined Behavior. 58 | 59 | Unlike C, Undefined Behavior is pretty limited in scope in Rust. All the core 60 | language cares about is preventing the following things: 61 | 62 | * Dereferencing null or dangling pointers 63 | * Reading [uninitialized memory] 64 | * Breaking the [pointer aliasing rules] 65 | * Producing invalid primitive values: 66 | * dangling/null references 67 | * a `bool` that isn't 0 or 1 68 | * an undefined `enum` discriminant 69 | * a `char` outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF] 70 | * A non-utf8 `str` 71 | * Unwinding into another language 72 | * Causing a [data race][race] 73 | 74 | That's it. That's all the causes of Undefined Behavior baked into Rust. Of 75 | course, unsafe functions and traits are free to declare arbitrary other 76 | constraints that a program must maintain to avoid Undefined Behavior. However, 77 | generally violations of these constraints will just transitively lead to one of 78 | the above problems. Some additional constraints may also derive from compiler 79 | intrinsics that make special assumptions about how code can be optimized. 80 | 81 | Rust is otherwise quite permissive with respect to other dubious operations. 82 | Rust considers it "safe" to: 83 | 84 | * Deadlock 85 | * Have a [race condition][race] 86 | * Leak memory 87 | * Fail to call destructors 88 | * Overflow integers 89 | * Abort the program 90 | * Delete the production database 91 | 92 | However any program that actually manages to do such a thing is *probably* 93 | incorrect. Rust provides lots of tools to make these things rare, but 94 | these problems are considered impractical to categorically prevent. 95 | 96 | [pointer aliasing rules]: references.html 97 | [uninitialized memory]: uninitialized.html 98 | [race]: races.html 99 | -------------------------------------------------------------------------------- /nomicon/obrm.md: -------------------------------------------------------------------------------- 1 | % The Perils Of Ownership Based Resource Management (OBRM) 2 | 3 | OBRM (AKA RAII: Resource Acquisition Is Initialization) is something you'll 4 | interact with a lot in Rust. Especially if you use the standard library. 5 | 6 | Roughly speaking the pattern is as follows: to acquire a resource, you create an 7 | object that manages it. To release the resource, you simply destroy the object, 8 | and it cleans up the resource for you. The most common "resource" this pattern 9 | manages is simply *memory*. `Box`, `Rc`, and basically everything in 10 | `std::collections` is a convenience to enable correctly managing memory. This is 11 | particularly important in Rust because we have no pervasive GC to rely on for 12 | memory management. Which is the point, really: Rust is about control. However we 13 | are not limited to just memory. Pretty much every other system resource like a 14 | thread, file, or socket is exposed through this kind of API. 15 | -------------------------------------------------------------------------------- /nomicon/other-reprs.md: -------------------------------------------------------------------------------- 1 | % Alternative representations 2 | 3 | Rust allows you to specify alternative data layout strategies from the default. 4 | 5 | 6 | 7 | 8 | # repr(C) 9 | 10 | This is the most important `repr`. It has fairly simple intent: do what C does. 11 | The order, size, and alignment of fields is exactly what you would expect from C 12 | or C++. Any type you expect to pass through an FFI boundary should have 13 | `repr(C)`, as C is the lingua-franca of the programming world. This is also 14 | necessary to soundly do more elaborate tricks with data layout such as 15 | reinterpreting values as a different type. 16 | 17 | However, the interaction with Rust's more exotic data layout features must be 18 | kept in mind. Due to its dual purpose as "for FFI" and "for layout control", 19 | `repr(C)` can be applied to types that will be nonsensical or problematic if 20 | passed through the FFI boundary. 21 | 22 | * ZSTs are still zero-sized, even though this is not a standard behavior in 23 | C, and is explicitly contrary to the behavior of an empty type in C++, which 24 | still consumes a byte of space. 25 | 26 | * DSTs, tuples, and tagged unions are not a concept in C and as such are never 27 | FFI safe. 28 | 29 | * Tuple structs are like structs with regards to `repr(C)`, as the only 30 | difference from a struct is that the fields aren’t named. 31 | 32 | * **If the type would have any [drop flags], they will still be added** 33 | 34 | * This is equivalent to one of `repr(u*)` (see the next section) for enums. The 35 | chosen size is the default enum size for the target platform's C ABI. Note that 36 | enum representation in C is implementation defined, so this is really a "best 37 | guess". In particular, this may be incorrect when the C code of interest is 38 | compiled with certain flags. 39 | 40 | 41 | 42 | # repr(u8), repr(u16), repr(u32), repr(u64) 43 | 44 | These specify the size to make a C-like enum. If the discriminant overflows the 45 | integer it has to fit in, it will produce a compile-time error. You can manually 46 | ask Rust to allow this by setting the overflowing element to explicitly be 0. 47 | However Rust will not allow you to create an enum where two variants have the 48 | same discriminant. 49 | 50 | On non-C-like enums, this will inhibit certain optimizations like the null- 51 | pointer optimization. 52 | 53 | These reprs have no effect on a struct. 54 | 55 | 56 | 57 | 58 | # repr(packed) 59 | 60 | `repr(packed)` forces Rust to strip any padding, and only align the type to a 61 | byte. This may improve the memory footprint, but will likely have other negative 62 | side-effects. 63 | 64 | In particular, most architectures *strongly* prefer values to be aligned. This 65 | may mean the unaligned loads are penalized (x86), or even fault (some ARM 66 | chips). For simple cases like directly loading or storing a packed field, the 67 | compiler might be able to paper over alignment issues with shifts and masks. 68 | However if you take a reference to a packed field, it's unlikely that the 69 | compiler will be able to emit code to avoid an unaligned load. 70 | 71 | **[As of Rust 1.0 this can cause undefined behavior.][ub loads]** 72 | 73 | `repr(packed)` is not to be used lightly. Unless you have extreme requirements, 74 | this should not be used. 75 | 76 | This repr is a modifier on `repr(C)` and `repr(rust)`. 77 | 78 | [drop flags]: drop-flags.html 79 | [ub loads]: https://github.com/rust-lang/rust/issues/27060 80 | -------------------------------------------------------------------------------- /nomicon/ownership.md: -------------------------------------------------------------------------------- 1 | % Ownership and Lifetimes 2 | 3 | Ownership is the breakout feature of Rust. It allows Rust to be completely 4 | memory-safe and efficient, while avoiding garbage collection. Before getting 5 | into the ownership system in detail, we will consider the motivation of this 6 | design. 7 | 8 | We will assume that you accept that garbage collection (GC) is not always an 9 | optimal solution, and that it is desirable to manually manage memory in some 10 | contexts. If you do not accept this, might I interest you in a different 11 | language? 12 | 13 | Regardless of your feelings on GC, it is pretty clearly a *massive* boon to 14 | making code safe. You never have to worry about things going away *too soon* 15 | (although whether you still wanted to be pointing at that thing is a different 16 | issue...). This is a pervasive problem that C and C++ programs need to deal 17 | with. Consider this simple mistake that all of us who have used a non-GC'd 18 | language have made at one point: 19 | 20 | ```rust,ignore 21 | fn as_str(data: &u32) -> &str { 22 | // compute the string 23 | let s = format!("{}", data); 24 | 25 | // OH NO! We returned a reference to something that 26 | // exists only in this function! 27 | // Dangling pointer! Use after free! Alas! 28 | // (this does not compile in Rust) 29 | &s 30 | } 31 | ``` 32 | 33 | This is exactly what Rust's ownership system was built to solve. 34 | Rust knows the scope in which the `&s` lives, and as such can prevent it from 35 | escaping. However this is a simple case that even a C compiler could plausibly 36 | catch. Things get more complicated as code gets bigger and pointers get fed through 37 | various functions. Eventually, a C compiler will fall down and won't be able to 38 | perform sufficient escape analysis to prove your code unsound. It will consequently 39 | be forced to accept your program on the assumption that it is correct. 40 | 41 | This will never happen to Rust. It's up to the programmer to prove to the 42 | compiler that everything is sound. 43 | 44 | Of course, Rust's story around ownership is much more complicated than just 45 | verifying that references don't escape the scope of their referent. That's 46 | because ensuring pointers are always valid is much more complicated than this. 47 | For instance in this code, 48 | 49 | ```rust,ignore 50 | let mut data = vec![1, 2, 3]; 51 | // get an internal reference 52 | let x = &data[0]; 53 | 54 | // OH NO! `push` causes the backing storage of `data` to be reallocated. 55 | // Dangling pointer! User after free! Alas! 56 | // (this does not compile in Rust) 57 | data.push(4); 58 | 59 | println!("{}", x); 60 | ``` 61 | 62 | naive scope analysis would be insufficient to prevent this bug, because `data` 63 | does in fact live as long as we needed. However it was *changed* while we had 64 | a reference into it. This is why Rust requires any references to freeze the 65 | referent and its owners. 66 | 67 | -------------------------------------------------------------------------------- /nomicon/phantom-data.md: -------------------------------------------------------------------------------- 1 | % PhantomData 2 | 3 | When working with unsafe code, we can often end up in a situation where 4 | types or lifetimes are logically associated with a struct, but not actually 5 | part of a field. This most commonly occurs with lifetimes. For instance, the 6 | `Iter` for `&'a [T]` is (approximately) defined as follows: 7 | 8 | ```rust,ignore 9 | struct Iter<'a, T: 'a> { 10 | ptr: *const T, 11 | end: *const T, 12 | } 13 | ``` 14 | 15 | However because `'a` is unused within the struct's body, it's *unbounded*. 16 | Because of the troubles this has historically caused, unbounded lifetimes and 17 | types are *forbidden* in struct definitions. Therefore we must somehow refer 18 | to these types in the body. Correctly doing this is necessary to have 19 | correct variance and drop checking. 20 | 21 | We do this using `PhantomData`, which is a special marker type. `PhantomData` 22 | consumes no space, but simulates a field of the given type for the purpose of 23 | static analysis. This was deemed to be less error-prone than explicitly telling 24 | the type-system the kind of variance that you want, while also providing other 25 | useful such as the information needed by drop check. 26 | 27 | Iter logically contains a bunch of `&'a T`s, so this is exactly what we tell 28 | the PhantomData to simulate: 29 | 30 | ``` 31 | use std::marker; 32 | 33 | struct Iter<'a, T: 'a> { 34 | ptr: *const T, 35 | end: *const T, 36 | _marker: marker::PhantomData<&'a T>, 37 | } 38 | ``` 39 | 40 | and that's it. The lifetime will be bounded, and your iterator will be variant 41 | over `'a` and `T`. Everything Just Works. 42 | 43 | Another important example is Vec, which is (approximately) defined as follows: 44 | 45 | ``` 46 | struct Vec { 47 | data: *const T, // *const for variance! 48 | len: usize, 49 | cap: usize, 50 | } 51 | ``` 52 | 53 | Unlike the previous example it *appears* that everything is exactly as we 54 | want. Every generic argument to Vec shows up in the at least one field. 55 | Good to go! 56 | 57 | Nope. 58 | 59 | The drop checker will generously determine that Vec does not own any values 60 | of type T. This will in turn make it conclude that it doesn't need to worry 61 | about Vec dropping any T's in its destructor for determining drop check 62 | soundness. This will in turn allow people to create unsoundness using 63 | Vec's destructor. 64 | 65 | In order to tell dropck that we *do* own values of type T, and therefore may 66 | drop some T's when *we* drop, we must add an extra PhantomData saying exactly 67 | that: 68 | 69 | ``` 70 | use std::marker; 71 | 72 | struct Vec { 73 | data: *const T, // *const for covariance! 74 | len: usize, 75 | cap: usize, 76 | _marker: marker::PhantomData, 77 | } 78 | ``` 79 | 80 | Raw pointers that own an allocation is such a pervasive pattern that the 81 | standard library made a utility for itself called `Unique` which: 82 | 83 | * wraps a `*const T` for variance 84 | * includes a `PhantomData`, 85 | * auto-derives Send/Sync as if T was contained 86 | * marks the pointer as NonZero for the null-pointer optimization 87 | 88 | -------------------------------------------------------------------------------- /nomicon/poisoning.md: -------------------------------------------------------------------------------- 1 | % Poisoning 2 | 3 | Although all unsafe code *must* ensure it has minimal exception safety, not all 4 | types ensure *maximal* exception safety. Even if the type does, your code may 5 | ascribe additional meaning to it. For instance, an integer is certainly 6 | exception-safe, but has no semantics on its own. It's possible that code that 7 | panics could fail to correctly update the integer, producing an inconsistent 8 | program state. 9 | 10 | This is *usually* fine, because anything that witnesses an exception is about 11 | to get destroyed. For instance, if you send a Vec to another thread and that 12 | thread panics, it doesn't matter if the Vec is in a weird state. It will be 13 | dropped and go away forever. However some types are especially good at smuggling 14 | values across the panic boundary. 15 | 16 | These types may choose to explicitly *poison* themselves if they witness a panic. 17 | Poisoning doesn't entail anything in particular. Generally it just means 18 | preventing normal usage from proceeding. The most notable example of this is the 19 | standard library's Mutex type. A Mutex will poison itself if one of its 20 | MutexGuards (the thing it returns when a lock is obtained) is dropped during a 21 | panic. Any future attempts to lock the Mutex will return an `Err` or panic. 22 | 23 | Mutex poisons not for true safety in the sense that Rust normally cares about. It 24 | poisons as a safety-guard against blindly using the data that comes out of a Mutex 25 | that has witnessed a panic while locked. The data in such a Mutex was likely in the 26 | middle of being modified, and as such may be in an inconsistent or incomplete state. 27 | It is important to note that one cannot violate memory safety with such a type 28 | if it is correctly written. After all, it must be minimally exception-safe! 29 | 30 | However if the Mutex contained, say, a BinaryHeap that does not actually have the 31 | heap property, it's unlikely that any code that uses it will do 32 | what the author intended. As such, the program should not proceed normally. 33 | Still, if you're double-plus-sure that you can do *something* with the value, 34 | the Mutex exposes a method to get the lock anyway. It *is* safe, after all. 35 | Just maybe nonsense. 36 | -------------------------------------------------------------------------------- /nomicon/races.md: -------------------------------------------------------------------------------- 1 | % Data Races and Race Conditions 2 | 3 | Safe Rust guarantees an absence of data races, which are defined as: 4 | 5 | * two or more threads concurrently accessing a location of memory 6 | * one of them is a write 7 | * one of them is unsynchronized 8 | 9 | A data race has Undefined Behavior, and is therefore impossible to perform 10 | in Safe Rust. Data races are *mostly* prevented through rust's ownership system: 11 | it's impossible to alias a mutable reference, so it's impossible to perform a 12 | data race. Interior mutability makes this more complicated, which is largely why 13 | we have the Send and Sync traits (see below). 14 | 15 | **However Rust does not prevent general race conditions.** 16 | 17 | This is pretty fundamentally impossible, and probably honestly undesirable. Your 18 | hardware is racy, your OS is racy, the other programs on your computer are racy, 19 | and the world this all runs in is racy. Any system that could genuinely claim to 20 | prevent *all* race conditions would be pretty awful to use, if not just 21 | incorrect. 22 | 23 | So it's perfectly "fine" for a Safe Rust program to get deadlocked or do 24 | something incredibly stupid with incorrect synchronization. Obviously such a 25 | program isn't very good, but Rust can only hold your hand so far. Still, a 26 | race condition can't violate memory safety in a Rust program on 27 | its own. Only in conjunction with some other unsafe code can a race condition 28 | actually violate memory safety. For instance: 29 | 30 | ```rust,no_run 31 | use std::thread; 32 | use std::sync::atomic::{AtomicUsize, Ordering}; 33 | use std::sync::Arc; 34 | 35 | let data = vec![1, 2, 3, 4]; 36 | // Arc so that the memory the AtomicUsize is stored in still exists for 37 | // the other thread to increment, even if we completely finish executing 38 | // before it. Rust won't compile the program without it, because of the 39 | // lifetime requirements of thread::spawn! 40 | let idx = Arc::new(AtomicUsize::new(0)); 41 | let other_idx = idx.clone(); 42 | 43 | // `move` captures other_idx by-value, moving it into this thread 44 | thread::spawn(move || { 45 | // It's ok to mutate idx because this value 46 | // is an atomic, so it can't cause a Data Race. 47 | other_idx.fetch_add(10, Ordering::SeqCst); 48 | }); 49 | 50 | // Index with the value loaded from the atomic. This is safe because we 51 | // read the atomic memory only once, and then pass a copy of that value 52 | // to the Vec's indexing implementation. This indexing will be correctly 53 | // bounds checked, and there's no chance of the value getting changed 54 | // in the middle. However our program may panic if the thread we spawned 55 | // managed to increment before this ran. A race condition because correct 56 | // program execution (panicking is rarely correct) depends on order of 57 | // thread execution. 58 | println!("{}", data[idx.load(Ordering::SeqCst)]); 59 | ``` 60 | 61 | ```rust,no_run 62 | use std::thread; 63 | use std::sync::atomic::{AtomicUsize, Ordering}; 64 | use std::sync::Arc; 65 | 66 | let data = vec![1, 2, 3, 4]; 67 | 68 | let idx = Arc::new(AtomicUsize::new(0)); 69 | let other_idx = idx.clone(); 70 | 71 | // `move` captures other_idx by-value, moving it into this thread 72 | thread::spawn(move || { 73 | // It's ok to mutate idx because this value 74 | // is an atomic, so it can't cause a Data Race. 75 | other_idx.fetch_add(10, Ordering::SeqCst); 76 | }); 77 | 78 | if idx.load(Ordering::SeqCst) < data.len() { 79 | unsafe { 80 | // Incorrectly loading the idx after we did the bounds check. 81 | // It could have changed. This is a race condition, *and dangerous* 82 | // because we decided to do `get_unchecked`, which is `unsafe`. 83 | println!("{}", data.get_unchecked(idx.load(Ordering::SeqCst))); 84 | } 85 | } 86 | ``` 87 | -------------------------------------------------------------------------------- /nomicon/send-and-sync.md: -------------------------------------------------------------------------------- 1 | % Send and Sync 2 | 3 | Not everything obeys inherited mutability, though. Some types allow you to 4 | multiply alias a location in memory while mutating it. Unless these types use 5 | synchronization to manage this access, they are absolutely not thread safe. Rust 6 | captures this through the `Send` and `Sync` traits. 7 | 8 | * A type is Send if it is safe to send it to another thread. 9 | * A type is Sync if it is safe to share between threads (`&T` is Send). 10 | 11 | Send and Sync are fundamental to Rust's concurrency story. As such, a 12 | substantial amount of special tooling exists to make them work right. First and 13 | foremost, they're [unsafe traits]. This means that they are unsafe to 14 | implement, and other unsafe code can assume that they are correctly 15 | implemented. Since they're *marker traits* (they have no associated items like 16 | methods), correctly implemented simply means that they have the intrinsic 17 | properties an implementor should have. Incorrectly implementing Send or Sync can 18 | cause Undefined Behavior. 19 | 20 | Send and Sync are also automatically derived traits. This means that, unlike 21 | every other trait, if a type is composed entirely of Send or Sync types, then it 22 | is Send or Sync. Almost all primitives are Send and Sync, and as a consequence 23 | pretty much all types you'll ever interact with are Send and Sync. 24 | 25 | Major exceptions include: 26 | 27 | * raw pointers are neither Send nor Sync (because they have no safety guards). 28 | * `UnsafeCell` isn't Sync (and therefore `Cell` and `RefCell` aren't). 29 | * `Rc` isn't Send or Sync (because the refcount is shared and unsynchronized). 30 | 31 | `Rc` and `UnsafeCell` are very fundamentally not thread-safe: they enable 32 | unsynchronized shared mutable state. However raw pointers are, strictly 33 | speaking, marked as thread-unsafe as more of a *lint*. Doing anything useful 34 | with a raw pointer requires dereferencing it, which is already unsafe. In that 35 | sense, one could argue that it would be "fine" for them to be marked as thread 36 | safe. 37 | 38 | However it's important that they aren't thread safe to prevent types that 39 | contain them from being automatically marked as thread safe. These types have 40 | non-trivial untracked ownership, and it's unlikely that their author was 41 | necessarily thinking hard about thread safety. In the case of Rc, we have a nice 42 | example of a type that contains a `*mut` that is definitely not thread safe. 43 | 44 | Types that aren't automatically derived can simply implement them if desired: 45 | 46 | ```rust 47 | struct MyBox(*mut u8); 48 | 49 | unsafe impl Send for MyBox {} 50 | unsafe impl Sync for MyBox {} 51 | ``` 52 | 53 | In the *incredibly rare* case that a type is inappropriately automatically 54 | derived to be Send or Sync, then one can also unimplement Send and Sync: 55 | 56 | ```rust 57 | #![feature(optin_builtin_traits)] 58 | 59 | // I have some magic semantics for some synchronization primitive! 60 | struct SpecialThreadToken(u8); 61 | 62 | impl !Send for SpecialThreadToken {} 63 | impl !Sync for SpecialThreadToken {} 64 | ``` 65 | 66 | Note that *in and of itself* it is impossible to incorrectly derive Send and 67 | Sync. Only types that are ascribed special meaning by other unsafe code can 68 | possible cause trouble by being incorrectly Send or Sync. 69 | 70 | Most uses of raw pointers should be encapsulated behind a sufficient abstraction 71 | that Send and Sync can be derived. For instance all of Rust's standard 72 | collections are Send and Sync (when they contain Send and Sync types) in spite 73 | of their pervasive use of raw pointers to manage allocations and complex ownership. 74 | Similarly, most iterators into these collections are Send and Sync because they 75 | largely behave like an `&` or `&mut` into the collection. 76 | 77 | TODO: better explain what can or can't be Send or Sync. Sufficient to appeal 78 | only to data races? 79 | 80 | [unsafe traits]: safe-unsafe-meaning.html 81 | -------------------------------------------------------------------------------- /nomicon/transmutes.md: -------------------------------------------------------------------------------- 1 | % Transmutes 2 | 3 | Get out of our way type system! We're going to reinterpret these bits or die 4 | trying! Even though this book is all about doing things that are unsafe, I 5 | really can't emphasize that you should deeply think about finding Another Way 6 | than the operations covered in this section. This is really, truly, the most 7 | horribly unsafe thing you can do in Rust. The railguards here are dental floss. 8 | 9 | `mem::transmute` takes a value of type `T` and reinterprets it to have 10 | type `U`. The only restriction is that the `T` and `U` are verified to have the 11 | same size. The ways to cause Undefined Behavior with this are mind boggling. 12 | 13 | * First and foremost, creating an instance of *any* type with an invalid state 14 | is going to cause arbitrary chaos that can't really be predicted. 15 | * Transmute has an overloaded return type. If you do not specify the return type 16 | it may produce a surprising type to satisfy inference. 17 | * Making a primitive with an invalid value is UB 18 | * Transmuting between non-repr(C) types is UB 19 | * Transmuting an & to &mut is UB 20 | * Transmuting an & to &mut is *always* UB 21 | * No you can't do it 22 | * No you're not special 23 | * Transmuting to a reference without an explicitly provided lifetime 24 | produces an [unbounded lifetime] 25 | 26 | `mem::transmute_copy` somehow manages to be *even more* wildly unsafe than 27 | this. It copies `size_of` bytes out of an `&T` and interprets them as a `U`. 28 | The size check that `mem::transmute` has is gone (as it may be valid to copy 29 | out a prefix), though it is Undefined Behavior for `U` to be larger than `T`. 30 | 31 | Also of course you can get most of the functionality of these functions using 32 | pointer casts. 33 | 34 | 35 | [unbounded lifetime]: unbounded-lifetimes.html 36 | -------------------------------------------------------------------------------- /nomicon/unbounded-lifetimes.md: -------------------------------------------------------------------------------- 1 | % Unbounded Lifetimes 2 | 3 | Unsafe code can often end up producing references or lifetimes out of thin air. 4 | Such lifetimes come into the world as *unbounded*. The most common source of this 5 | is dereferencing a raw pointer, which produces a reference with an unbounded lifetime. 6 | Such a lifetime becomes as big as context demands. This is in fact more powerful 7 | than simply becoming `'static`, because for instance `&'static &'a T` 8 | will fail to typecheck, but the unbound lifetime will perfectly mold into 9 | `&'a &'a T` as needed. However for most intents and purposes, such an unbounded 10 | lifetime can be regarded as `'static`. 11 | 12 | Almost no reference is `'static`, so this is probably wrong. `transmute` and 13 | `transmute_copy` are the two other primary offenders. One should endeavor to 14 | bound an unbounded lifetime as quick as possible, especially across function 15 | boundaries. 16 | 17 | Given a function, any output lifetimes that don't derive from inputs are 18 | unbounded. For instance: 19 | 20 | ```rust,ignore 21 | fn get_str<'a>() -> &'a str; 22 | ``` 23 | 24 | will produce an `&str` with an unbounded lifetime. The easiest way to avoid 25 | unbounded lifetimes is to use lifetime elision at the function boundary. 26 | If an output lifetime is elided, then it *must* be bounded by an input lifetime. 27 | Of course it might be bounded by the *wrong* lifetime, but this will usually 28 | just cause a compiler error, rather than allow memory safety to be trivially 29 | violated. 30 | 31 | Within a function, bounding lifetimes is more error-prone. The safest and easiest 32 | way to bound a lifetime is to return it from a function with a bound lifetime. 33 | However if this is unacceptable, the reference can be placed in a location with 34 | a specific lifetime. Unfortunately it's impossible to name all lifetimes involved 35 | in a function. 36 | 37 | -------------------------------------------------------------------------------- /nomicon/unchecked-uninit.md: -------------------------------------------------------------------------------- 1 | % Unchecked Uninitialized Memory 2 | 3 | One interesting exception to this rule is working with arrays. Safe Rust doesn't 4 | permit you to partially initialize an array. When you initialize an array, you 5 | can either set every value to the same thing with `let x = [val; N]`, or you can 6 | specify each member individually with `let x = [val1, val2, val3]`. 7 | Unfortunately this is pretty rigid, especially if you need to initialize your 8 | array in a more incremental or dynamic way. 9 | 10 | Unsafe Rust gives us a powerful tool to handle this problem: 11 | `mem::uninitialized`. This function pretends to return a value when really 12 | it does nothing at all. Using it, we can convince Rust that we have initialized 13 | a variable, allowing us to do trickier things with conditional and incremental 14 | initialization. 15 | 16 | Unfortunately, this opens us up to all kinds of problems. Assignment has a 17 | different meaning to Rust based on whether it believes that a variable is 18 | initialized or not. If it's believed uninitialized, then Rust will semantically 19 | just memcopy the bits over the uninitialized ones, and do nothing else. However 20 | if Rust believes a value to be initialized, it will try to `Drop` the old value! 21 | Since we've tricked Rust into believing that the value is initialized, we can no 22 | longer safely use normal assignment. 23 | 24 | This is also a problem if you're working with a raw system allocator, which 25 | returns a pointer to uninitialized memory. 26 | 27 | To handle this, we must use the `ptr` module. In particular, it provides 28 | three functions that allow us to assign bytes to a location in memory without 29 | dropping the old value: `write`, `copy`, and `copy_nonoverlapping`. 30 | 31 | * `ptr::write(ptr, val)` takes a `val` and moves it into the address pointed 32 | to by `ptr`. 33 | * `ptr::copy(src, dest, count)` copies the bits that `count` T's would occupy 34 | from src to dest. (this is equivalent to memmove -- note that the argument 35 | order is reversed!) 36 | * `ptr::copy_nonoverlapping(src, dest, count)` does what `copy` does, but a 37 | little faster on the assumption that the two ranges of memory don't overlap. 38 | (this is equivalent to memcpy -- note that the argument order is reversed!) 39 | 40 | It should go without saying that these functions, if misused, will cause serious 41 | havoc or just straight up Undefined Behavior. The only things that these 42 | functions *themselves* require is that the locations you want to read and write 43 | are allocated. However the ways writing arbitrary bits to arbitrary 44 | locations of memory can break things are basically uncountable! 45 | 46 | Putting this all together, we get the following: 47 | 48 | ```rust 49 | use std::mem; 50 | use std::ptr; 51 | 52 | // size of the array is hard-coded but easy to change. This means we can't 53 | // use [a, b, c] syntax to initialize the array, though! 54 | const SIZE: usize = 10; 55 | 56 | let mut x: [Box; SIZE]; 57 | 58 | unsafe { 59 | // convince Rust that x is Totally Initialized 60 | x = mem::uninitialized(); 61 | for i in 0..SIZE { 62 | // very carefully overwrite each index without reading it 63 | // NOTE: exception safety is not a concern; Box can't panic 64 | ptr::write(&mut x[i], Box::new(i as u32)); 65 | } 66 | } 67 | 68 | println!("{:?}", x); 69 | ``` 70 | 71 | It's worth noting that you don't need to worry about `ptr::write`-style 72 | shenanigans with types which don't implement `Drop` or contain `Drop` types, 73 | because Rust knows not to try to drop them. Similarly you should be able to 74 | assign to fields of partially initialized structs directly if those fields don't 75 | contain any `Drop` types. 76 | 77 | However when working with uninitialized memory you need to be ever-vigilant for 78 | Rust trying to drop values you make like this before they're fully initialized. 79 | Every control path through that variable's scope must initialize the value 80 | before it ends, if it has a destructor. 81 | *[This includes code panicking](unwinding.html)*. 82 | 83 | And that's about it for working with uninitialized memory! Basically nothing 84 | anywhere expects to be handed uninitialized memory, so if you're going to pass 85 | it around at all, be sure to be *really* careful. 86 | -------------------------------------------------------------------------------- /nomicon/uninitialized.md: -------------------------------------------------------------------------------- 1 | % Working With Uninitialized Memory 2 | 3 | All runtime-allocated memory in a Rust program begins its life as 4 | *uninitialized*. In this state the value of the memory is an indeterminate pile 5 | of bits that may or may not even reflect a valid state for the type that is 6 | supposed to inhabit that location of memory. Attempting to interpret this memory 7 | as a value of *any* type will cause Undefined Behavior. Do Not Do This. 8 | 9 | Rust provides mechanisms to work with uninitialized memory in checked (safe) and 10 | unchecked (unsafe) ways. 11 | -------------------------------------------------------------------------------- /nomicon/unwinding.md: -------------------------------------------------------------------------------- 1 | % Unwinding 2 | 3 | Rust has a *tiered* error-handling scheme: 4 | 5 | * If something might reasonably be absent, Option is used. 6 | * If something goes wrong and can reasonably be handled, Result is used. 7 | * If something goes wrong and cannot reasonably be handled, the thread panics. 8 | * If something catastrophic happens, the program aborts. 9 | 10 | Option and Result are overwhelmingly preferred in most situations, especially 11 | since they can be promoted into a panic or abort at the API user's discretion. 12 | Panics cause the thread to halt normal execution and unwind its stack, calling 13 | destructors as if every function instantly returned. 14 | 15 | As of 1.0, Rust is of two minds when it comes to panics. In the long-long-ago, 16 | Rust was much more like Erlang. Like Erlang, Rust had lightweight tasks, 17 | and tasks were intended to kill themselves with a panic when they reached an 18 | untenable state. Unlike an exception in Java or C++, a panic could not be 19 | caught at any time. Panics could only be caught by the owner of the task, at which 20 | point they had to be handled or *that* task would itself panic. 21 | 22 | Unwinding was important to this story because if a task's 23 | destructors weren't called, it would cause memory and other system resources to 24 | leak. Since tasks were expected to die during normal execution, this would make 25 | Rust very poor for long-running systems! 26 | 27 | As the Rust we know today came to be, this style of programming grew out of 28 | fashion in the push for less-and-less abstraction. Light-weight tasks were 29 | killed in the name of heavy-weight OS threads. Still, on stable Rust as of 1.0 30 | panics can only be caught by the parent thread. This means catching a panic 31 | requires spinning up an entire OS thread! This unfortunately stands in conflict 32 | to Rust's philosophy of zero-cost abstractions. 33 | 34 | There is an unstable API called `catch_panic` that enables catching a panic 35 | without spawning a thread. Still, we would encourage you to only do this 36 | sparingly. In particular, Rust's current unwinding implementation is heavily 37 | optimized for the "doesn't unwind" case. If a program doesn't unwind, there 38 | should be no runtime cost for the program being *ready* to unwind. As a 39 | consequence, actually unwinding will be more expensive than in e.g. Java. 40 | Don't build your programs to unwind under normal circumstances. Ideally, you 41 | should only panic for programming errors or *extreme* problems. 42 | 43 | Rust's unwinding strategy is not specified to be fundamentally compatible 44 | with any other language's unwinding. As such, unwinding into Rust from another 45 | language, or unwinding into another language from Rust is Undefined Behavior. 46 | You must *absolutely* catch any panics at the FFI boundary! What you do at that 47 | point is up to you, but *something* must be done. If you fail to do this, 48 | at best, your application will crash and burn. At worst, your application *won't* 49 | crash and burn, and will proceed with completely clobbered state. 50 | -------------------------------------------------------------------------------- /nomicon/vec-dealloc.md: -------------------------------------------------------------------------------- 1 | % Deallocating 2 | 3 | Next we should implement Drop so that we don't massively leak tons of resources. 4 | The easiest way is to just call `pop` until it yields None, and then deallocate 5 | our buffer. Note that calling `pop` is unneeded if `T: !Drop`. In theory we can 6 | ask Rust if `T` `needs_drop` and omit the calls to `pop`. However in practice 7 | LLVM is *really* good at removing simple side-effect free code like this, so I 8 | wouldn't bother unless you notice it's not being stripped (in this case it is). 9 | 10 | We must not call `heap::deallocate` when `self.cap == 0`, as in this case we 11 | haven't actually allocated any memory. 12 | 13 | 14 | ```rust,ignore 15 | impl Drop for Vec { 16 | fn drop(&mut self) { 17 | if self.cap != 0 { 18 | while let Some(_) = self.pop() { } 19 | 20 | let align = mem::align_of::(); 21 | let elem_size = mem::size_of::(); 22 | let num_bytes = elem_size * self.cap; 23 | unsafe { 24 | heap::deallocate(*self.ptr as *mut _, num_bytes, align); 25 | } 26 | } 27 | } 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /nomicon/vec-deref.md: -------------------------------------------------------------------------------- 1 | % Deref 2 | 3 | Alright! We've got a decent minimal stack implemented. We can push, we can 4 | pop, and we can clean up after ourselves. However there's a whole mess of 5 | functionality we'd reasonably want. In particular, we have a proper array, but 6 | none of the slice functionality. That's actually pretty easy to solve: we can 7 | implement `Deref`. This will magically make our Vec coerce to, and 8 | behave like, a slice in all sorts of conditions. 9 | 10 | All we need is `slice::from_raw_parts`. It will correctly handle empty slices 11 | for us. Later once we set up zero-sized type support it will also Just Work 12 | for those too. 13 | 14 | ```rust,ignore 15 | use std::ops::Deref; 16 | 17 | impl Deref for Vec { 18 | type Target = [T]; 19 | fn deref(&self) -> &[T] { 20 | unsafe { 21 | ::std::slice::from_raw_parts(*self.ptr, self.len) 22 | } 23 | } 24 | } 25 | ``` 26 | 27 | And let's do DerefMut too: 28 | 29 | ```rust,ignore 30 | use std::ops::DerefMut; 31 | 32 | impl DerefMut for Vec { 33 | fn deref_mut(&mut self) -> &mut [T] { 34 | unsafe { 35 | ::std::slice::from_raw_parts_mut(*self.ptr, self.len) 36 | } 37 | } 38 | } 39 | ``` 40 | 41 | Now we have `len`, `first`, `last`, indexing, slicing, sorting, `iter`, 42 | `iter_mut`, and all other sorts of bells and whistles provided by slice. Sweet! 43 | -------------------------------------------------------------------------------- /nomicon/vec-drain.md: -------------------------------------------------------------------------------- 1 | % Drain 2 | 3 | Let's move on to Drain. Drain is largely the same as IntoIter, except that 4 | instead of consuming the Vec, it borrows the Vec and leaves its allocation 5 | untouched. For now we'll only implement the "basic" full-range version. 6 | 7 | ```rust,ignore 8 | use std::marker::PhantomData; 9 | 10 | struct Drain<'a, T: 'a> { 11 | // Need to bound the lifetime here, so we do it with `&'a mut Vec` 12 | // because that's semantically what we contain. We're "just" calling 13 | // `pop()` and `remove(0)`. 14 | vec: PhantomData<&'a mut Vec> 15 | start: *const T, 16 | end: *const T, 17 | } 18 | 19 | impl<'a, T> Iterator for Drain<'a, T> { 20 | type Item = T; 21 | fn next(&mut self) -> Option { 22 | if self.start == self.end { 23 | None 24 | ``` 25 | 26 | -- wait, this is seeming familiar. Let's do some more compression. Both 27 | IntoIter and Drain have the exact same structure, let's just factor it out. 28 | 29 | ```rust 30 | struct RawValIter { 31 | start: *const T, 32 | end: *const T, 33 | } 34 | 35 | impl RawValIter { 36 | // unsafe to construct because it has no associated lifetimes. 37 | // This is necessary to store a RawValIter in the same struct as 38 | // its actual allocation. OK since it's a private implementation 39 | // detail. 40 | unsafe fn new(slice: &[T]) -> Self { 41 | RawValIter { 42 | start: slice.as_ptr(), 43 | end: if slice.len() == 0 { 44 | // if `len = 0`, then this is not actually allocated memory. 45 | // Need to avoid offsetting because that will give wrong 46 | // information to LLVM via GEP. 47 | slice.as_ptr() 48 | } else { 49 | slice.as_ptr().offset(slice.len() as isize) 50 | } 51 | } 52 | } 53 | } 54 | 55 | // Iterator and DoubleEndedIterator impls identical to IntoIter. 56 | ``` 57 | 58 | And IntoIter becomes the following: 59 | 60 | ```rust,ignore 61 | pub struct IntoIter { 62 | _buf: RawVec, // we don't actually care about this. Just need it to live. 63 | iter: RawValIter, 64 | } 65 | 66 | impl Iterator for IntoIter { 67 | type Item = T; 68 | fn next(&mut self) -> Option { self.iter.next() } 69 | fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } 70 | } 71 | 72 | impl DoubleEndedIterator for IntoIter { 73 | fn next_back(&mut self) -> Option { self.iter.next_back() } 74 | } 75 | 76 | impl Drop for IntoIter { 77 | fn drop(&mut self) { 78 | for _ in &mut self.iter {} 79 | } 80 | } 81 | 82 | impl Vec { 83 | pub fn into_iter(self) -> IntoIter { 84 | unsafe { 85 | let iter = RawValIter::new(&self); 86 | 87 | let buf = ptr::read(&self.buf); 88 | mem::forget(self); 89 | 90 | IntoIter { 91 | iter: iter, 92 | _buf: buf, 93 | } 94 | } 95 | } 96 | } 97 | ``` 98 | 99 | Note that I've left a few quirks in this design to make upgrading Drain to work 100 | with arbitrary subranges a bit easier. In particular we *could* have RawValIter 101 | drain itself on drop, but that won't work right for a more complex Drain. 102 | We also take a slice to simplify Drain initialization. 103 | 104 | Alright, now Drain is really easy: 105 | 106 | ```rust,ignore 107 | use std::marker::PhantomData; 108 | 109 | pub struct Drain<'a, T: 'a> { 110 | vec: PhantomData<&'a mut Vec>, 111 | iter: RawValIter, 112 | } 113 | 114 | impl<'a, T> Iterator for Drain<'a, T> { 115 | type Item = T; 116 | fn next(&mut self) -> Option { self.iter.next() } 117 | fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } 118 | } 119 | 120 | impl<'a, T> DoubleEndedIterator for Drain<'a, T> { 121 | fn next_back(&mut self) -> Option { self.iter.next_back() } 122 | } 123 | 124 | impl<'a, T> Drop for Drain<'a, T> { 125 | fn drop(&mut self) { 126 | for _ in &mut self.iter {} 127 | } 128 | } 129 | 130 | impl Vec { 131 | pub fn drain(&mut self) -> Drain { 132 | unsafe { 133 | let iter = RawValIter::new(&self); 134 | 135 | // this is a mem::forget safety thing. If Drain is forgotten, we just 136 | // leak the whole Vec's contents. Also we need to do this *eventually* 137 | // anyway, so why not do it now? 138 | self.len = 0; 139 | 140 | Drain { 141 | iter: iter, 142 | vec: PhantomData, 143 | } 144 | } 145 | } 146 | } 147 | ``` 148 | 149 | For more details on the `mem::forget` problem, see the 150 | [section on leaks][leaks]. 151 | 152 | [leaks]: leaking.html 153 | -------------------------------------------------------------------------------- /nomicon/vec-insert-remove.md: -------------------------------------------------------------------------------- 1 | % Insert and Remove 2 | 3 | Something *not* provided by slice is `insert` and `remove`, so let's do those 4 | next. 5 | 6 | Insert needs to shift all the elements at the target index to the right by one. 7 | To do this we need to use `ptr::copy`, which is our version of C's `memmove`. 8 | This copies some chunk of memory from one location to another, correctly 9 | handling the case where the source and destination overlap (which will 10 | definitely happen here). 11 | 12 | If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]` 13 | using the old len. 14 | 15 | ```rust,ignore 16 | pub fn insert(&mut self, index: usize, elem: T) { 17 | // Note: `<=` because it's valid to insert after everything 18 | // which would be equivalent to push. 19 | assert!(index <= self.len, "index out of bounds"); 20 | if self.cap == self.len { self.grow(); } 21 | 22 | unsafe { 23 | if index < self.len { 24 | // ptr::copy(src, dest, len): "copy from source to dest len elems" 25 | ptr::copy(self.ptr.offset(index as isize), 26 | self.ptr.offset(index as isize + 1), 27 | self.len - index); 28 | } 29 | ptr::write(self.ptr.offset(index as isize), elem); 30 | self.len += 1; 31 | } 32 | } 33 | ``` 34 | 35 | Remove behaves in the opposite manner. We need to shift all the elements from 36 | `[i+1 .. len + 1]` to `[i .. len]` using the *new* len. 37 | 38 | ```rust,ignore 39 | pub fn remove(&mut self, index: usize) -> T { 40 | // Note: `<` because it's *not* valid to remove after everything 41 | assert!(index < self.len, "index out of bounds"); 42 | unsafe { 43 | self.len -= 1; 44 | let result = ptr::read(self.ptr.offset(index as isize)); 45 | ptr::copy(self.ptr.offset(index as isize + 1), 46 | self.ptr.offset(index as isize), 47 | self.len - index); 48 | result 49 | } 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /nomicon/vec-layout.md: -------------------------------------------------------------------------------- 1 | % Layout 2 | 3 | First off, we need to come up with the struct layout. A Vec has three parts: 4 | a pointer to the allocation, the size of the allocation, and the number of 5 | elements that have been initialized. 6 | 7 | Naively, this means we just want this design: 8 | 9 | ```rust 10 | pub struct Vec { 11 | ptr: *mut T, 12 | cap: usize, 13 | len: usize, 14 | } 15 | # fn main() {} 16 | ``` 17 | 18 | And indeed this would compile. Unfortunately, it would be incorrect. First, the 19 | compiler will give us too strict variance. So a `&Vec<&'static str>` 20 | couldn't be used where an `&Vec<&'a str>` was expected. More importantly, it 21 | will give incorrect ownership information to the drop checker, as it will 22 | conservatively assume we don't own any values of type `T`. See [the chapter 23 | on ownership and lifetimes][ownership] for all the details on variance and 24 | drop check. 25 | 26 | As we saw in the ownership chapter, we should use `Unique` in place of 27 | `*mut T` when we have a raw pointer to an allocation we own. Unique is unstable, 28 | so we'd like to not use it if possible, though. 29 | 30 | As a recap, Unique is a wrapper around a raw pointer that declares that: 31 | 32 | * We are variant over `T` 33 | * We may own a value of type `T` (for drop check) 34 | * We are Send/Sync if `T` is Send/Sync 35 | * We deref to `*mut T` (so it largely acts like a `*mut` in our code) 36 | * Our pointer is never null (so `Option>` is null-pointer-optimized) 37 | 38 | We can implement all of the above requirements except for the last 39 | one in stable Rust: 40 | 41 | ```rust 42 | use std::marker::PhantomData; 43 | use std::ops::Deref; 44 | use std::mem; 45 | 46 | struct Unique { 47 | ptr: *const T, // *const for variance 48 | _marker: PhantomData, // For the drop checker 49 | } 50 | 51 | // Deriving Send and Sync is safe because we are the Unique owners 52 | // of this data. It's like Unique is "just" T. 53 | unsafe impl Send for Unique {} 54 | unsafe impl Sync for Unique {} 55 | 56 | impl Unique { 57 | pub fn new(ptr: *mut T) -> Self { 58 | Unique { ptr: ptr, _marker: PhantomData } 59 | } 60 | } 61 | 62 | impl Deref for Unique { 63 | type Target = *mut T; 64 | fn deref(&self) -> &*mut T { 65 | // There's no way to cast the *const to a *mut 66 | // while also taking a reference. So we just 67 | // transmute it since it's all "just pointers". 68 | unsafe { mem::transmute(&self.ptr) } 69 | } 70 | } 71 | # fn main() {} 72 | ``` 73 | 74 | Unfortunately the mechanism for stating that your value is non-zero is 75 | unstable and unlikely to be stabilized soon. As such we're just going to 76 | take the hit and use std's Unique: 77 | 78 | 79 | ```rust 80 | #![feature(unique)] 81 | 82 | use std::ptr::{Unique, self}; 83 | 84 | pub struct Vec { 85 | ptr: Unique, 86 | cap: usize, 87 | len: usize, 88 | } 89 | 90 | # fn main() {} 91 | ``` 92 | 93 | If you don't care about the null-pointer optimization, then you can use the 94 | stable code. However we will be designing the rest of the code around enabling 95 | the optimization. In particular, `Unique::new` is unsafe to call, because 96 | putting `null` inside of it is Undefined Behavior. Our stable Unique doesn't 97 | need `new` to be unsafe because it doesn't make any interesting guarantees about 98 | its contents. 99 | 100 | [ownership]: ownership.html 101 | -------------------------------------------------------------------------------- /nomicon/vec-push-pop.md: -------------------------------------------------------------------------------- 1 | % Push and Pop 2 | 3 | Alright. We can initialize. We can allocate. Let's actually implement some 4 | functionality! Let's start with `push`. All it needs to do is check if we're 5 | full to grow, unconditionally write to the next index, and then increment our 6 | length. 7 | 8 | To do the write we have to be careful not to evaluate the memory we want to write 9 | to. At worst, it's truly uninitialized memory from the allocator. At best it's the 10 | bits of some old value we popped off. Either way, we can't just index to the memory 11 | and dereference it, because that will evaluate the memory as a valid instance of 12 | T. Worse, `foo[idx] = x` will try to call `drop` on the old value of `foo[idx]`! 13 | 14 | The correct way to do this is with `ptr::write`, which just blindly overwrites the 15 | target address with the bits of the value we provide. No evaluation involved. 16 | 17 | For `push`, if the old len (before push was called) is 0, then we want to write 18 | to the 0th index. So we should offset by the old len. 19 | 20 | ```rust,ignore 21 | pub fn push(&mut self, elem: T) { 22 | if self.len == self.cap { self.grow(); } 23 | 24 | unsafe { 25 | ptr::write(self.ptr.offset(self.len as isize), elem); 26 | } 27 | 28 | // Can't fail, we'll OOM first. 29 | self.len += 1; 30 | } 31 | ``` 32 | 33 | Easy! How about `pop`? Although this time the index we want to access is 34 | initialized, Rust won't just let us dereference the location of memory to move 35 | the value out, because that would leave the memory uninitialized! For this we 36 | need `ptr::read`, which just copies out the bits from the target address and 37 | interprets it as a value of type T. This will leave the memory at this address 38 | logically uninitialized, even though there is in fact a perfectly good instance 39 | of T there. 40 | 41 | For `pop`, if the old len is 1, we want to read out of the 0th index. So we 42 | should offset by the new len. 43 | 44 | ```rust,ignore 45 | pub fn pop(&mut self) -> Option { 46 | if self.len == 0 { 47 | None 48 | } else { 49 | self.len -= 1; 50 | unsafe { 51 | Some(ptr::read(self.ptr.offset(self.len as isize))) 52 | } 53 | } 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /nomicon/vec-raw.md: -------------------------------------------------------------------------------- 1 | % RawVec 2 | 3 | We've actually reached an interesting situation here: we've duplicated the logic 4 | for specifying a buffer and freeing its memory in Vec and IntoIter. Now that 5 | we've implemented it and identified *actual* logic duplication, this is a good 6 | time to perform some logic compression. 7 | 8 | We're going to abstract out the `(ptr, cap)` pair and give them the logic for 9 | allocating, growing, and freeing: 10 | 11 | ```rust,ignore 12 | struct RawVec { 13 | ptr: Unique, 14 | cap: usize, 15 | } 16 | 17 | impl RawVec { 18 | fn new() -> Self { 19 | assert!(mem::size_of::() != 0, "TODO: implement ZST support"); 20 | unsafe { 21 | RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: 0 } 22 | } 23 | } 24 | 25 | // unchanged from Vec 26 | fn grow(&mut self) { 27 | unsafe { 28 | let align = mem::align_of::(); 29 | let elem_size = mem::size_of::(); 30 | 31 | let (new_cap, ptr) = if self.cap == 0 { 32 | let ptr = heap::allocate(elem_size, align); 33 | (1, ptr) 34 | } else { 35 | let new_cap = 2 * self.cap; 36 | let ptr = heap::reallocate(*self.ptr as *mut _, 37 | self.cap * elem_size, 38 | new_cap * elem_size, 39 | align); 40 | (new_cap, ptr) 41 | }; 42 | 43 | // If allocate or reallocate fail, we'll get `null` back 44 | if ptr.is_null() { oom() } 45 | 46 | self.ptr = Unique::new(ptr as *mut _); 47 | self.cap = new_cap; 48 | } 49 | } 50 | } 51 | 52 | 53 | impl Drop for RawVec { 54 | fn drop(&mut self) { 55 | if self.cap != 0 { 56 | let align = mem::align_of::(); 57 | let elem_size = mem::size_of::(); 58 | let num_bytes = elem_size * self.cap; 59 | unsafe { 60 | heap::deallocate(*self.ptr as *mut _, num_bytes, align); 61 | } 62 | } 63 | } 64 | } 65 | ``` 66 | 67 | And change Vec as follows: 68 | 69 | ```rust,ignore 70 | pub struct Vec { 71 | buf: RawVec, 72 | len: usize, 73 | } 74 | 75 | impl Vec { 76 | fn ptr(&self) -> *mut T { *self.buf.ptr } 77 | 78 | fn cap(&self) -> usize { self.buf.cap } 79 | 80 | pub fn new() -> Self { 81 | Vec { buf: RawVec::new(), len: 0 } 82 | } 83 | 84 | // push/pop/insert/remove largely unchanged: 85 | // * `self.ptr -> self.ptr()` 86 | // * `self.cap -> self.cap()` 87 | // * `self.grow -> self.buf.grow()` 88 | } 89 | 90 | impl Drop for Vec { 91 | fn drop(&mut self) { 92 | while let Some(_) = self.pop() {} 93 | // deallocation is handled by RawVec 94 | } 95 | } 96 | ``` 97 | 98 | And finally we can really simplify IntoIter: 99 | 100 | ```rust,ignore 101 | struct IntoIter { 102 | _buf: RawVec, // we don't actually care about this. Just need it to live. 103 | start: *const T, 104 | end: *const T, 105 | } 106 | 107 | // next and next_back literally unchanged since they never referred to the buf 108 | 109 | impl Drop for IntoIter { 110 | fn drop(&mut self) { 111 | // only need to ensure all our elements are read; 112 | // buffer will clean itself up afterwards. 113 | for _ in &mut *self {} 114 | } 115 | } 116 | 117 | impl Vec { 118 | pub fn into_iter(self) -> IntoIter { 119 | unsafe { 120 | // need to use ptr::read to unsafely move the buf out since it's 121 | // not Copy, and Vec implements Drop (so we can't destructure it). 122 | let buf = ptr::read(&self.buf); 123 | let len = self.len; 124 | mem::forget(self); 125 | 126 | IntoIter { 127 | start: *buf.ptr, 128 | end: buf.ptr.offset(len as isize), 129 | _buf: buf, 130 | } 131 | } 132 | } 133 | } 134 | ``` 135 | 136 | Much better. 137 | -------------------------------------------------------------------------------- /nomicon/vec.md: -------------------------------------------------------------------------------- 1 | % Example: Implementing Vec 2 | 3 | To bring everything together, we're going to write `std::Vec` from scratch. 4 | Because all the best tools for writing unsafe code are unstable, this 5 | project will only work on nightly (as of Rust 1.9.0). With the exception of the 6 | allocator API, much of the unstable code we'll use is expected to be stabilized 7 | in a similar form as it is today. 8 | 9 | However we will generally try to avoid unstable code where possible. In 10 | particular we won't use any intrinsics that could make a code a little 11 | bit nicer or efficient because intrinsics are permanently unstable. Although 12 | many intrinsics *do* become stabilized elsewhere (`std::ptr` and `str::mem` 13 | consist of many intrinsics). 14 | 15 | Ultimately this means our implementation may not take advantage of all 16 | possible optimizations, though it will be by no means *naive*. We will 17 | definitely get into the weeds over nitty-gritty details, even 18 | when the problem doesn't *really* merit it. 19 | 20 | You wanted advanced. We're gonna go advanced. 21 | -------------------------------------------------------------------------------- /nomicon/working-with-unsafe.md: -------------------------------------------------------------------------------- 1 | % Working with Unsafe 2 | 3 | Rust generally only gives us the tools to talk about Unsafe Rust in a scoped and 4 | binary manner. Unfortunately, reality is significantly more complicated than 5 | that. For instance, consider the following toy function: 6 | 7 | ```rust 8 | fn index(idx: usize, arr: &[u8]) -> Option { 9 | if idx < arr.len() { 10 | unsafe { 11 | Some(*arr.get_unchecked(idx)) 12 | } 13 | } else { 14 | None 15 | } 16 | } 17 | ``` 18 | 19 | Clearly, this function is safe. We check that the index is in bounds, and if it 20 | is, index into the array in an unchecked manner. But even in such a trivial 21 | function, the scope of the unsafe block is questionable. Consider changing the 22 | `<` to a `<=`: 23 | 24 | ```rust 25 | fn index(idx: usize, arr: &[u8]) -> Option { 26 | if idx <= arr.len() { 27 | unsafe { 28 | Some(*arr.get_unchecked(idx)) 29 | } 30 | } else { 31 | None 32 | } 33 | } 34 | ``` 35 | 36 | This program is now unsound, and yet *we only modified safe code*. This is the 37 | fundamental problem of safety: it's non-local. The soundness of our unsafe 38 | operations necessarily depends on the state established by otherwise 39 | "safe" operations. 40 | 41 | Safety is modular in the sense that opting into unsafety doesn't require you 42 | to consider arbitrary other kinds of badness. For instance, doing an unchecked 43 | index into a slice doesn't mean you suddenly need to worry about the slice being 44 | null or containing uninitialized memory. Nothing fundamentally changes. However 45 | safety *isn't* modular in the sense that programs are inherently stateful and 46 | your unsafe operations may depend on arbitrary other state. 47 | 48 | Trickier than that is when we get into actual statefulness. Consider a simple 49 | implementation of `Vec`: 50 | 51 | ```rust 52 | use std::ptr; 53 | 54 | // Note this definition is insufficient. See the section on implementing Vec. 55 | pub struct Vec { 56 | ptr: *mut T, 57 | len: usize, 58 | cap: usize, 59 | } 60 | 61 | // Note this implementation does not correctly handle zero-sized types. 62 | // We currently live in a nice imaginary world of only positive fixed-size 63 | // types. 64 | impl Vec { 65 | pub fn push(&mut self, elem: T) { 66 | if self.len == self.cap { 67 | // not important for this example 68 | self.reallocate(); 69 | } 70 | unsafe { 71 | ptr::write(self.ptr.offset(self.len as isize), elem); 72 | self.len += 1; 73 | } 74 | } 75 | 76 | # fn reallocate(&mut self) { } 77 | } 78 | 79 | # fn main() {} 80 | ``` 81 | 82 | This code is simple enough to reasonably audit and verify. Now consider 83 | adding the following method: 84 | 85 | ```rust,ignore 86 | fn make_room(&mut self) { 87 | // grow the capacity 88 | self.cap += 1; 89 | } 90 | ``` 91 | 92 | This code is 100% Safe Rust but it is also completely unsound. Changing the 93 | capacity violates the invariants of Vec (that `cap` reflects the allocated space 94 | in the Vec). This is not something the rest of Vec can guard against. It *has* 95 | to trust the capacity field because there's no way to verify it. 96 | 97 | `unsafe` does more than pollute a whole function: it pollutes a whole *module*. 98 | Generally, the only bullet-proof way to limit the scope of unsafe code is at the 99 | module boundary with privacy. 100 | 101 | However this works *perfectly*. The existence of `make_room` is *not* a 102 | problem for the soundness of Vec because we didn't mark it as public. Only the 103 | module that defines this function can call it. Also, `make_room` directly 104 | accesses the private fields of Vec, so it can only be written in the same module 105 | as Vec. 106 | 107 | It is therefore possible for us to write a completely safe abstraction that 108 | relies on complex invariants. This is *critical* to the relationship between 109 | Safe Rust and Unsafe Rust. We have already seen that Unsafe code must trust 110 | *some* Safe code, but can't trust *generic* Safe code. It can't trust an 111 | arbitrary implementor of a trait or any function that was passed to it to be 112 | well-behaved in a way that safe code doesn't care about. 113 | 114 | However if unsafe code couldn't prevent client safe code from messing with its 115 | state in arbitrary ways, safety would be a lost cause. Thankfully, it *can* 116 | prevent arbitrary code from messing with critical state due to privacy. 117 | 118 | Safety lives! 119 | 120 | -------------------------------------------------------------------------------- /nomicon_meta.yml: -------------------------------------------------------------------------------- 1 | --- 2 | title: "The Rustonomicon" 3 | author: "The Rust Team" 4 | date: {release_date} 5 | description: "This book digs into all the awful details that are necessary to understand in order to write correct Unsafe Rust programs. Due to the nature of this problem, it may lead to unleashing untold horrors that shatter your psyche into a billion infinitesimal fragments of despair." 6 | language: en 7 | documentclass: book 8 | links-as-notes: true 9 | verbatim-in-note: true 10 | toc-depth: 2 11 | monofont: "DejaVu Sans Mono" 12 | ... 13 | -------------------------------------------------------------------------------- /src/convert_book/index.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::path::Path; 3 | use std::fs; 4 | use std::collections::BTreeMap; 5 | use std::ascii::AsciiExt; 6 | 7 | use regex::Regex; 8 | 9 | const FILENAME_PATTRN: &'static str = 10 | r"^(?P\w+)-(?P\d{4}-\d{2}-\d{2})\.(?P.+)$"; 11 | 12 | type FileListing = Vec<(String, String)>; 13 | 14 | fn list_file_groups(path: &str) -> Result> { 15 | let filename_pattern = Regex::new(FILENAME_PATTRN).unwrap(); 16 | 17 | let files = try!(fs::read_dir(&Path::new(path))) 18 | .filter(Result::is_ok) 19 | .map(|x| x.unwrap().path()) 20 | .filter_map(|x| { 21 | x.file_name() 22 | .and_then(|a| { a.to_str() }) 23 | .and_then(|b| -> Option { Some(b.into()) }) 24 | }) 25 | .flat_map(|name| -> Option<(String, String)> { 26 | // Extract the date from names like 'trpl-2015-05-13.a4.pdf'. 27 | // This also excludes the `index.html` file as it contains no date. 28 | if let Some(caps) = filename_pattern.captures(&name) { 29 | if let Some(version) = caps.name("date") { 30 | return Some((version.to_owned(), name.to_owned())); 31 | } 32 | } 33 | return None; 34 | }) 35 | .collect(); 36 | 37 | Ok(files) 38 | } 39 | 40 | pub fn render_index(path: &str) -> Result> { 41 | let filename_pattern = Regex::new(FILENAME_PATTRN).unwrap(); 42 | 43 | let files = try!(list_file_groups(path)); 44 | let mut versions: BTreeMap> = BTreeMap::new(); 45 | 46 | for &(ref version, ref filename) in &files { 47 | let file = versions.entry(version.clone()).or_insert(vec![]); 48 | file.push(filename.clone()); 49 | } 50 | 51 | let mut file_listing = String::new(); 52 | 53 | for (version, files) in versions.iter().rev() { 54 | file_listing.push_str("
  • \n

    "); 55 | file_listing.push_str(&version); 56 | file_listing.push_str("

    \n
      "); 57 | 58 | for file in files { 59 | file_listing.push_str(&format!( 60 | "
    • {file_title}
    • \n", 61 | file_name = file, 62 | file_title = filename_pattern 63 | .replace_all(file, "$prefix $ext") 64 | .to_ascii_uppercase() 65 | )); 66 | } 67 | 68 | file_listing.push_str("
    \n
  • "); 69 | } 70 | 71 | let output = format!(include_str!("../../lib/index_template.html"), 72 | css = include_str!("../../lib/index.css"), 73 | file_listing = file_listing); 74 | 75 | Ok(output) 76 | } 77 | -------------------------------------------------------------------------------- /src/convert_book/markdown.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | use std::error::Error; 3 | use regex::Regex; 4 | 5 | use helpers::*; 6 | 7 | /// Poor man's progress indicator 8 | macro_rules! put { 9 | ($e:expr) => ({ 10 | { 11 | use std::io; 12 | use std::io::Write; 13 | print!($e); 14 | io::stdout().flush().unwrap(); 15 | } 16 | }) 17 | } 18 | 19 | #[derive(Debug, Hash, PartialEq, Eq)] 20 | struct Chapter { 21 | file: String, 22 | headline: String, 23 | } 24 | 25 | fn get_chapters(toc: &str) -> Vec { 26 | let toc_pattern = Regex::new(r"(?x) 27 | (?P\s*?) 28 | \*\s 29 | \[ 30 | (?P.+?) 31 | \] 32 | \( 33 | (?P<filename>.+?) 34 | \) 35 | ").unwrap(); 36 | 37 | let filename_pattern = Regex::new(r"(?x) 38 | ^ 39 | (?P<path>(.*)/)? 40 | (?P<name>(.*?)) 41 | (?P<ext>\.(\w*))? 42 | $ 43 | ").unwrap(); 44 | 45 | toc.lines() 46 | .filter_map(|l| toc_pattern.captures(l)) 47 | .map(|link| { 48 | let level = if link.name("indent").unwrap().chars().count() == 0 { "#" } else { "##" }; 49 | let id = filename_pattern.captures( 50 | link.name("filename").unwrap() 51 | ).unwrap().name("name").unwrap(); 52 | 53 | let headline = format!( 54 | "{level} {name} {{#sec--{link}}}\n", 55 | level = level, name = link.name("title").unwrap(), link = id 56 | ); 57 | 58 | Chapter { 59 | file: link.name("filename").unwrap().into(), 60 | headline: headline, 61 | } 62 | }) 63 | .collect::<Vec<Chapter>>() 64 | } 65 | 66 | pub fn to_single_file(src_path: &Path, meta: &str) -> Result<String, Box<Error>> { 67 | put!("Reading book"); 68 | 69 | let toc = try!(file::get_file_content(&src_path.join("SUMMARY.md"))); 70 | put!("."); 71 | 72 | let mut book = String::new(); 73 | 74 | book.push_str(meta); 75 | book.push_str("\n"); 76 | 77 | { 78 | // Readme ~ "Getting Started" 79 | let file = try!(file::get_file_content(&src_path.join("README.md"))); 80 | let mut content = try!(adjust_header_level::adjust_header_level(&file, 1)); 81 | content = try!(remove_file_title::remove_file_title(&content)); 82 | content = try!(adjust_reference_names::adjust_reference_name(&content, "readme")); 83 | content = try!(normalize::normalize(&content)); 84 | 85 | put!("."); 86 | 87 | book.push_str("\n\n"); 88 | book.push_str("# Introduction"); 89 | book.push_str("\n\n"); 90 | book.push_str(&content); 91 | } 92 | 93 | for chapter in &get_chapters(&toc) { 94 | let file = try!(file::get_file_content(&src_path.join(&chapter.file))); 95 | 96 | let mut content = try!(adjust_header_level::adjust_header_level(&file, 3)); 97 | content = try!(remove_file_title::remove_file_title(&content)); 98 | content = try!(adjust_reference_names::adjust_reference_name(&content, &chapter.file)); 99 | content = try!(normalize::normalize(&content)); 100 | 101 | put!("."); 102 | 103 | book.push_str("\n\n"); 104 | book.push_str(&chapter.headline); 105 | book.push_str("\n"); 106 | book.push_str(&content); 107 | } 108 | 109 | put!(" done.\n"); 110 | 111 | Ok(book) 112 | } 113 | -------------------------------------------------------------------------------- /src/convert_book/mod.rs: -------------------------------------------------------------------------------- 1 | //! Tools to compile the book 2 | 3 | pub mod index; 4 | pub mod markdown; 5 | pub mod options; 6 | pub mod pandoc; 7 | 8 | use std::path::Path; 9 | use std::error::Error; 10 | use helpers; 11 | use convert_book::pandoc::save_as; 12 | 13 | /// Render book in different formats 14 | pub fn render_book(prefix: &str, src_path: &Path, meta_file: &str) -> Result<(), Box<Error>> { 15 | let meta_data = try!(helpers::file::get_file_content(meta_file)); 16 | 17 | let book = try!(markdown::to_single_file(src_path, 18 | &meta_data.replace("{release_date}", 19 | options::RELEASE_DATE))); 20 | 21 | try!(helpers::file::write_string_to_file(&book, 22 | &format!("dist/{}-{}.md", 23 | prefix, 24 | options::RELEASE_DATE))); 25 | println!("[✓] {}", "MD"); 26 | 27 | try!(save_as(&book, prefix, "html", options::HTML)); 28 | try!(save_as(&book, prefix, "epub", options::EPUB)); 29 | 30 | let cc_book = helpers::convert_checkmarks::convert_checkmarks(&book); 31 | try!(save_as(&cc_book, prefix, "tex", options::LATEX)); 32 | 33 | let plain_book = helpers::remove_emojis::remove_emojis(&cc_book); 34 | try!(save_as(&plain_book, 35 | prefix, 36 | "a4.pdf", 37 | &format!(r"{} --variable papersize=a4paper", options::LATEX))); 38 | try!(save_as(&plain_book, 39 | prefix, 40 | "letter.pdf", 41 | &format!(r"{} --variable papersize=letterpaper", 42 | options::LATEX))); 43 | 44 | Ok(()) 45 | } 46 | -------------------------------------------------------------------------------- /src/convert_book/options.rs: -------------------------------------------------------------------------------- 1 | pub const RELEASE_DATE: &'static str = "2016-10-01"; 2 | 3 | pub const MARKDOWN: &'static str = "markdown+grid_tables+pipe_tables-simple_tables+raw_html+implicit_figures+footnotes+intraword_underscores+auto_identifiers-inline_code_attributes"; 4 | 5 | pub const HTML: &'static str = "--smart --normalize --standalone --self-contained --highlight-style=tango --table-of-contents --section-divs --template=lib/template.html --css=lib/pandoc.css --to=html5"; 6 | 7 | pub const EPUB: &'static str = "--smart --normalize --standalone --self-contained --highlight-style=tango --epub-stylesheet=lib/epub.css --table-of-contents"; 8 | 9 | pub const LATEX: &'static str = "--smart --normalize --standalone --self-contained --highlight-style=tango --chapters --table-of-contents --template=lib/template.tex --latex-engine=xelatex --to=latex"; 10 | -------------------------------------------------------------------------------- /src/convert_book/pandoc.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::ascii::AsciiExt; 3 | 4 | use helpers::shell_pipe; 5 | use convert_book::options; 6 | 7 | pub fn run(args: &str, input: &str) -> Result<String, Box<Error>> { 8 | shell_pipe::run("pandoc", args, input) 9 | } 10 | 11 | pub fn save_as(book: &str, prefix: &str, format: &str, opts: &str) -> Result<(), Box<Error>> { 12 | let opts = format!("--from={markdown_opts} {opts} \ 13 | --output=dist/{prefix}-{release_date}.{format}", 14 | markdown_opts = options::MARKDOWN, 15 | opts = opts, 16 | prefix = prefix, 17 | release_date = options::RELEASE_DATE, 18 | format = format); 19 | 20 | try!(run(&opts, &book)); 21 | 22 | println!("[✓] {}", format.to_ascii_uppercase()); 23 | 24 | Ok(()) 25 | } 26 | 27 | #[test] 28 | #[ignore] 29 | fn dry_run() { 30 | let output = run("--from=markdown --base-header-level=2 --to=markdown --atx-headers", 31 | "# Hi there!\n") 32 | .unwrap(); 33 | 34 | assert_eq!(output, "## Hi there!\n"); 35 | } 36 | -------------------------------------------------------------------------------- /src/helpers/adjust_header_level.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::iter::repeat; 3 | use regex::Regex; 4 | 5 | const CODE_BLOCK_TOGGLE: &'static str = "```"; 6 | 7 | pub type HeaderLevel = i32; 8 | 9 | pub fn adjust_header_level(input: &str, base_level: HeaderLevel) -> Result<String, Box<Error>> { 10 | let headline_pattern = Regex::new(r"(?x) 11 | ^ 12 | (?P<level>[\x23]+) # A bunch of hash symbols 13 | \s 14 | (?P<title>.+) # Title, and maybe id 15 | $ 16 | ").unwrap(); 17 | 18 | let mut in_code_block = false; 19 | 20 | let output = input.lines() 21 | .fold(String::new(), |initial, line| { 22 | match (in_code_block, line.starts_with(CODE_BLOCK_TOGGLE)) { 23 | (true, false) => { 24 | // Code? I don't care about that stuff. 25 | return initial + line + "\n"; 26 | } 27 | (true, true ) => { in_code_block = false; } 28 | (false, true ) => { in_code_block = true; } 29 | _ => {} 30 | }; 31 | 32 | if let Some(headline) = headline_pattern.captures(line) { 33 | // level := number of '#'s. 34 | // '#' is always 1 byte, so .len() is save to use. 35 | let level = headline.name("level").unwrap().len() as i32; 36 | let new_level = calc_header_level(base_level, level); 37 | let new_headline = format!( 38 | "{level} {title}\n", 39 | level = repeat("#").take(new_level as usize).collect::<String>(), 40 | title = headline.name("title").unwrap() 41 | ); 42 | return initial + &new_headline; 43 | } 44 | 45 | initial + line + "\n" 46 | }); 47 | 48 | Ok(output) 49 | } 50 | 51 | fn calc_header_level(base_level: HeaderLevel, current_level: HeaderLevel) -> HeaderLevel { 52 | current_level + base_level - 1 53 | } 54 | 55 | #[test] 56 | fn header_level_calculation() { 57 | // base level | current level | new level 58 | assert_eq!(calc_header_level(1, 1), 1); 59 | assert_eq!(calc_header_level(1, 2), 2); 60 | assert_eq!(calc_header_level(2, 2), 3); 61 | assert_eq!(calc_header_level(2, 1), 2); 62 | } 63 | -------------------------------------------------------------------------------- /src/helpers/adjust_reference_names.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use regex::{Regex, Captures}; 3 | 4 | const CODE_BLOCK_TOGGLE: &'static str = "```"; 5 | 6 | pub fn adjust_reference_name(input: &str, prefix: &str) -> Result<String, Box<Error>> { 7 | let reference_link = Regex::new(r"(?x) 8 | \]\[ # This is a link to a reference 9 | (?P<id>.+?) # The reference name 10 | \] 11 | ").unwrap(); 12 | 13 | let footnote = Regex::new(r"(?x) 14 | \[ # This is a link to a reference 15 | \^ # Link to footnote begins with `^` 16 | (?P<id>.+?) # The reference name 17 | \] 18 | ").unwrap(); 19 | 20 | let reference_def = Regex::new(r"(?x) 21 | ^ 22 | \[ 23 | (?P<footnote>\^)? # Footnote definition begins with `^` 24 | (?P<id>.+) # The reference name 25 | \] 26 | :\s 27 | (?P<link>.+) # The link url (and maybe the title) 28 | $ 29 | ").unwrap(); 30 | 31 | let mut in_code_block = false; 32 | 33 | let output = input.lines() 34 | .fold(String::new(), |initial, line| { 35 | match (in_code_block, line.starts_with(CODE_BLOCK_TOGGLE)) { 36 | (true, false) => { 37 | // Code? I don't care about that stuff. 38 | return initial + line + "\n"; 39 | } 40 | (true, true ) => { in_code_block = false; } 41 | (false, true ) => { in_code_block = true; } 42 | _ => {} 43 | }; 44 | 45 | if reference_link.is_match(line) { 46 | let new_line = reference_link.replace_all(line, |matches: &Captures| { 47 | format!("][{prefix}--{id}]", 48 | prefix = prefix, 49 | id = matches.name("id").expect("no id in ref link") 50 | ) 51 | }); 52 | return initial + &new_line + "\n"; 53 | } 54 | 55 | if footnote.is_match(line) { 56 | let new_line = footnote.replace_all(line, |matches: &Captures| { 57 | format!("[^{prefix}--{id}]", 58 | prefix = prefix, 59 | id = matches.name("id").expect("no id in ref link") 60 | ) 61 | }); 62 | return initial + &new_line + "\n"; 63 | } 64 | 65 | if let Some(matches) = reference_def.captures(line) { 66 | let new_line = format!("[{footnote}{prefix}--{id}]: {link}", 67 | footnote = matches.name("footnote").unwrap_or(""), 68 | prefix = prefix, 69 | id = matches.name("id").expect("no id in ref def"), 70 | link = matches.name("link").expect("no ink in ref def") 71 | ); 72 | return initial + &new_line + "\n"; 73 | } 74 | 75 | initial + line + "\n" 76 | }); 77 | 78 | Ok(output) 79 | } 80 | 81 | #[test] 82 | fn reference_renamer() { 83 | assert_eq!( 84 | adjust_reference_name( 85 | "Lorem ipsum [dolor sit][amet], [consectetur adipisicing][elit]. Odio provident repellendus temporibus possimus magnam odit [neque obcaecati][illo], ab tenetur deserunt quae quia? Asperiores a hic, maiores quaerat, autem ea!", 86 | "PREFIX" 87 | ).unwrap(), 88 | "Lorem ipsum [dolor sit][PREFIX--amet], [consectetur adipisicing][PREFIX--elit]. Odio provident repellendus temporibus possimus magnam odit [neque obcaecati][PREFIX--illo], ab tenetur deserunt quae quia? Asperiores a hic, maiores quaerat, autem ea!\n" 89 | 90 | ); 91 | } 92 | -------------------------------------------------------------------------------- /src/helpers/convert_checkmarks.rs: -------------------------------------------------------------------------------- 1 | use regex::Regex; 2 | 3 | pub fn convert_checkmarks(input: &str) -> String { 4 | let checks = Regex::new("[\u{2713}\u{2714}]").unwrap(); 5 | // rely on pandoc's raw latex support 6 | checks.replace_all(input, "\\checkmark") 7 | } 8 | 9 | #[test] 10 | fn checkmark_conversion() { 11 | assert_eq!(convert_checkmarks("checks: ✓ ✔"), "checks: \\checkmark \\checkmark"); 12 | } 13 | -------------------------------------------------------------------------------- /src/helpers/file.rs: -------------------------------------------------------------------------------- 1 | use std::io::prelude::*; 2 | use std::error::Error; 3 | use std::path::Path; 4 | use std::fs::File; 5 | 6 | pub fn get_file_content<P: AsRef<Path>>(path: P) -> Result<String, Box<Error>> { 7 | let mut file = try!(File::open(path)); 8 | let mut buffer = String::new(); 9 | try!(file.read_to_string(&mut buffer)); 10 | Ok(buffer) 11 | } 12 | 13 | pub fn write_string_to_file(input: &str, name: &str) -> Result<(), Box<Error>> { 14 | let mut file = try!(File::create(&Path::new(name))); 15 | 16 | try!(file.write_all(input.as_bytes())); 17 | 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /src/helpers/line_breaks.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | pub fn break_long_line(line: &str, max_len: usize, sep: &str) -> Result<String, Box<Error>> { 4 | let sep_length = sep.chars().count() as usize; 5 | let mut output = String::with_capacity(line.len()); 6 | 7 | // First time: `max_len`, after that `max_len - sep_length` 8 | let mut line_end = max_len; 9 | 10 | for (index, ch) in line.chars().enumerate() { 11 | if index >= (line_end - 1) { 12 | line_end += max_len - sep_length - 1; 13 | output.push_str("\n"); 14 | output.push_str(sep); 15 | } 16 | output.push(ch); 17 | } 18 | 19 | Ok(output) 20 | } 21 | 22 | #[test] 23 | fn break_long_lines() { 24 | let long_line = "markdown+grid_tables+pipe_tables+raw_html+implicit_figures+footnotes+intraword_underscores+auto_identifiers-inline_code_attributesmarkdown+grid_tables+pipe_tables+raw_html+implicit_figures+footnotes+intraword_underscores+auto_identifiers-inline_code_attributes"; 25 | 26 | let correct_split = "markdown+grid_tables+pipe_tables+raw_html+implicit_figures+footnotes+intraword_ 27 | ↳ underscores+auto_identifiers-inline_code_attributesmarkdown+grid_tables+pipe_ 28 | ↳ tables+raw_html+implicit_figures+footnotes+intraword_underscores+auto_identif 29 | ↳ iers-inline_code_attributes"; 30 | 31 | let max_len = 80; 32 | 33 | let broken = break_long_line(long_line, max_len, "↳ ").unwrap(); 34 | 35 | assert_eq!(broken, correct_split); 36 | assert!(broken.lines().all(|x| x.chars().count() <= max_len)); 37 | assert_eq!(broken.lines().count(), 4); 38 | } 39 | -------------------------------------------------------------------------------- /src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | //! Various Helper Functions 2 | 3 | pub mod adjust_header_level; 4 | pub mod adjust_reference_names; 5 | pub mod convert_checkmarks; 6 | pub mod file; 7 | pub mod line_breaks; 8 | pub mod normalize; 9 | pub mod normalize_code_blocks; 10 | pub mod remove_emojis; 11 | pub mod remove_file_title; 12 | pub mod shell_pipe; 13 | -------------------------------------------------------------------------------- /src/helpers/normalize.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use regex::Regex; 3 | 4 | use helpers::normalize_code_blocks::*; 5 | 6 | fn normalize_links(input: &str) -> Result<String, Box<Error>> { 7 | let mut output = input.replace(r"../std", r"http://doc.rust-lang.org/std") 8 | .replace(r"../reference", 9 | r"http://doc.rust-lang.org/reference") 10 | .replace(r"../rustc", r"http://doc.rust-lang.org/rustc") 11 | .replace(r"../syntax", r"http://doc.rust-lang.org/syntax") 12 | .replace(r"../book", r"http://doc.rust-lang.org/book") 13 | .replace(r"../adv-book", r"http://doc.rust-lang.org/adv-book") 14 | .replace(r"../core", r"http://doc.rust-lang.org/core"); 15 | 16 | let cross_section_link = Regex::new(r"]\((?P<file>[\w-_]+)\.html\)").unwrap(); 17 | output = cross_section_link.replace_all(&output, r"](#sec--$file)"); 18 | 19 | let cross_section_ref = Regex::new(r"(?m)^\[(?P<id>.+)\]:\s(?P<file>[^:^/]+)\.html$").unwrap(); 20 | output = cross_section_ref.replace_all(&output, r"[$id]: #sec--$file"); 21 | 22 | let cross_subsection_link = Regex::new(r"]\((?P<file>[\w-_]+)\.html#(?P<subsection>[\w-_]+)\)") 23 | .unwrap(); 24 | output = cross_subsection_link.replace_all(&output, r"](#$subsection)"); 25 | 26 | let cross_subsection_ref = 27 | Regex::new(r"(?m)^\[(?P<id>.+)\]:\s(?P<file>[^:^/]+)\.html#(?P<subsection>[\w-_]+)$") 28 | .unwrap(); 29 | output = cross_subsection_ref.replace_all(&output, r"[$id]: #$subsection"); 30 | 31 | Ok(output) 32 | } 33 | 34 | fn normalize_math(input: &str) -> Result<String, Box<Error>> { 35 | let superscript = Regex::new(r"(\d+)<sup>(\d+)</sup>").unwrap(); 36 | Ok(superscript.replace_all(&input, r"$1^$2^")) 37 | } 38 | 39 | 40 | pub fn normalize(input: &str) -> Result<String, Box<Error>> { 41 | let mut output; 42 | 43 | output = try!(break_code_blocks(&input, 87, "↳ ")); 44 | output = try!(normalize_code_start(&output)); 45 | output = try!(normalize_links(&output)); 46 | output = try!(normalize_math(&output)); 47 | 48 | Ok(output) 49 | } 50 | -------------------------------------------------------------------------------- /src/helpers/normalize_code_blocks.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use regex::Regex; 3 | 4 | use helpers::line_breaks; 5 | 6 | const CODE_BLOCK_TOGGLE: &'static str = "```"; 7 | 8 | pub fn break_code_blocks(input: &str, max_len: usize, sep: &str) -> Result<String, Box<Error>> { 9 | let mut in_code_block = false; 10 | 11 | let output = input.lines() 12 | .fold(String::new(), |initial, line| { 13 | match (in_code_block, line.starts_with(CODE_BLOCK_TOGGLE)) { 14 | (true, false) => { 15 | let lines = line_breaks::break_long_line(line, max_len, sep).unwrap(); 16 | return initial + &lines + "\n"; 17 | } 18 | (true, true ) => { in_code_block = false; } 19 | (false, true ) => { in_code_block = true; } 20 | (false, false) => {} 21 | }; 22 | initial + line + "\n" 23 | }); 24 | 25 | Ok(output) 26 | } 27 | 28 | 29 | pub fn normalize_code_start(input: &str) -> Result<String, Box<Error>> { 30 | let rust_code_block_start = Regex::new(r"^```(.*)rust(.*)").unwrap(); 31 | let hidden_code = Regex::new(r"^(#\s.*|#$)").unwrap(); 32 | 33 | let mut in_code_block = false; 34 | 35 | let output = input.lines() 36 | .fold(String::new(), |initial, line| { 37 | if in_code_block && hidden_code.is_match(line) { 38 | initial 39 | } else if rust_code_block_start.is_match(line) { 40 | in_code_block = true; 41 | initial + "```rust\n" 42 | } else if line.starts_with(CODE_BLOCK_TOGGLE) { 43 | in_code_block = false; 44 | initial + line + "\n" 45 | } else { 46 | initial + line + "\n" 47 | } 48 | }); 49 | 50 | Ok(output) 51 | } 52 | 53 | #[test] 54 | fn code_block_breaking() { 55 | let long_code_block = "If we truly want a reference, we need the other option: ensure that our reference goes out of scope before we try to do the mutation. That looks like this: 56 | 57 | ```text 58 | Whew! The Rust compiler gives quite detailed errors at times, and this is one of those times. As the error explains, while we made our binding mutable, we still cannot call `push`. This is because we already have a reference to an element of the vector, `y`. Mutating something while another reference exists is dangerous, because we may invalidate the reference. In this speciffic case, when we create the vector, we may have only allocated space for three elements. Adding a fourth would mean allocating a new chunk of memory for all thosee elements, copying the old values over, and updating the internal pointer to that memory. That all works just fine. 59 | ``` 60 | 61 | We created an inner scope with an additional set of curly braces. `y` will go out of scope before we call `push()`, and so we’re all good."; 62 | 63 | let code_block_broken_down = "If we truly want a reference, we need the other option: ensure that our reference goes out of scope before we try to do the mutation. That looks like this: 64 | 65 | ```text 66 | Whew! The Rust compiler gives quite detailed errors at times, and this is one o 67 | ↳ f those times. As the error explains, while we made our binding mutable, we s 68 | ↳ till cannot call `push`. This is because we already have a reference to an el 69 | ↳ ement of the vector, `y`. Mutating something while another reference exists i 70 | ↳ s dangerous, because we may invalidate the reference. In this speciffic case, 71 | ↳ when we create the vector, we may have only allocated space for three elemen 72 | ↳ ts. Adding a fourth would mean allocating a new chunk of memory for all those 73 | ↳ e elements, copying the old values over, and updating the internal pointer to 74 | ↳ that memory. That all works just fine. 75 | ``` 76 | 77 | We created an inner scope with an additional set of curly braces. `y` will go out of scope before we call `push()`, and so we’re all good. 78 | "; 79 | 80 | let max_len = 80; 81 | 82 | let broken = break_code_blocks(long_code_block, max_len, "↳ ").unwrap(); 83 | 84 | assert_eq!(broken, code_block_broken_down); 85 | } 86 | 87 | #[test] 88 | fn code_block_starts() { 89 | let code_blocks = "Code: 90 | 91 | ```sh 92 | $ lol 93 | ``` 94 | 95 | ```{rust,ignore} 96 | let x = true; 97 | ``` 98 | 99 | ``` rust,no_extras 100 | let x = true; 101 | ``` 102 | 103 | ```rust 104 | # use magic::from_the_future::*; 105 | # 106 | # #[inline] 107 | # fn extension(file_name: &str) -> Option<&str> { 108 | # find(file_name, '.').map(|i| &file_name[i+1..]) 109 | # } 110 | let x = true; 111 | ``` 112 | "; 113 | 114 | let code_blocks_clean = "Code: 115 | 116 | ```sh 117 | $ lol 118 | ``` 119 | 120 | ```rust 121 | let x = true; 122 | ``` 123 | 124 | ```rust 125 | let x = true; 126 | ``` 127 | 128 | ```rust 129 | let x = true; 130 | ``` 131 | "; 132 | 133 | let cleaned = normalize_code_start(code_blocks).unwrap(); 134 | 135 | assert_eq!(cleaned, code_blocks_clean); 136 | } 137 | -------------------------------------------------------------------------------- /src/helpers/remove_emojis.rs: -------------------------------------------------------------------------------- 1 | use regex::Regex; 2 | 3 | pub fn remove_emojis(input: &str) -> String { 4 | // cf. http://stackoverflow.com/a/29115826/1254484 5 | let emojis = Regex::new("[\u{203c}\u{2049}\u{20e3}\u{2122}\u{2139}\u{2194}-\u{2199}\u{21a9}-\u{21aa}\u{231a}-\u{231b}\u{23e9}-\u{23ec}\u{23f0}\u{23f3}\u{24c2}\u{25aa}-\u{25ab}\u{25b6}\u{25c0}\u{25fb}-\u{25fe}\u{2600}-\u{2601}\u{260e}\u{2611}\u{2614}-\u{2615}\u{261d}\u{263a}\u{2648}-\u{2653}\u{2660}\u{2663}\u{2665}-\u{2666}\u{2668}\u{267b}\u{267f}\u{2693}\u{26a0}-\u{26a1}\u{26aa}-\u{26ab}\u{26bd}-\u{26be}\u{26c4}-\u{26c5}\u{26ce}\u{26d4}\u{26ea}\u{26f2}-\u{26f3}\u{26f5}\u{26fa}\u{26fd}\u{2702}\u{2705}\u{2708}-\u{270c}\u{270f}\u{2712}\u{2714}\u{2716}\u{2728}\u{2733}-\u{2734}\u{2744}\u{2747}\u{274c}\u{274e}\u{2753}-\u{2755}\u{2757}\u{2764}\u{2795}-\u{2797}\u{27a1}\u{27b0}\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}-\u{2b1c}\u{2b50}\u{2b55}\u{3030}\u{303d}\u{3297}\u{3299}\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}-\u{1f17f}\u{1f18e}\u{1f191}-\u{1f19a}\u{1f1e7}-\u{1f1ec}\u{1f1ee}-\u{1f1f0}\u{1f1f3}\u{1f1f5}\u{1f1f7}-\u{1f1fa}\u{1f201}-\u{1f202}\u{1f21a}\u{1f22f}\u{1f232}-\u{1f23a}\u{1f250}-\u{1f251}\u{1f300}-\u{1f320}\u{1f330}-\u{1f335}\u{1f337}-\u{1f37c}\u{1f380}-\u{1f393}\u{1f3a0}-\u{1f3c4}\u{1f3c6}-\u{1f3ca}\u{1f3e0}-\u{1f3f0}\u{1f400}-\u{1f43e}\u{1f440}\u{1f442}-\u{1f4f7}\u{1f4f9}-\u{1f4fc}\u{1f500}-\u{1f507}\u{1f509}-\u{1f53d}\u{1f550}-\u{1f567}\u{1f5fb}-\u{1f640}\u{1f645}-\u{1f64f}\u{1f680}-\u{1f68a}]").unwrap(); 6 | 7 | emojis.replace_all(input, "") 8 | } 9 | 10 | #[test] 11 | fn emoji_removal() { 12 | assert_eq!(remove_emojis("emojis? 😅"), "emojis? "); 13 | } 14 | -------------------------------------------------------------------------------- /src/helpers/remove_file_title.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use regex::Regex; 3 | 4 | pub fn remove_file_title(input: &str) -> Result<String, Box<Error>> { 5 | Ok(Regex::new(r"^%\s(.+)\n").unwrap().replace(input, "")) 6 | } 7 | -------------------------------------------------------------------------------- /src/helpers/shell_pipe.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::fmt; 3 | 4 | use std::io::prelude::*; 5 | use std::process::{self, Command, Stdio}; 6 | 7 | #[derive(Debug, Hash, PartialEq, Eq)] 8 | enum CommandError { 9 | StdIn, 10 | StdOut, 11 | } 12 | 13 | impl fmt::Display for CommandError { 14 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 15 | match *self { 16 | CommandError::StdIn => write!(f, "Error getting stdin"), 17 | CommandError::StdOut => write!(f, "Error getting stdout"), 18 | } 19 | } 20 | } 21 | 22 | impl Error for CommandError { 23 | fn description(&self) -> &str { 24 | match *self { 25 | CommandError::StdIn => "Error getting stdin", 26 | CommandError::StdOut => "Error getting stdout", 27 | } 28 | } 29 | } 30 | 31 | pub fn run(command: &str, args: &str, input: &str) -> Result<String, Box<Error>> { 32 | let args: Vec<&str> = if args.is_empty() { 33 | vec![] 34 | } else { 35 | // Command arguments are space separated but may contain sub strings in quotation marks 36 | let mut in_substr = false; 37 | args.split(|c: char| { 38 | if c == '\'' { in_substr = !in_substr; } 39 | !in_substr && (c == ' ') 40 | }).collect() 41 | }; 42 | 43 | let process = try!( 44 | Command::new(command) 45 | .args(&args) 46 | .stdin(Stdio::piped()) 47 | .stdout(Stdio::piped()) 48 | .spawn() 49 | ); 50 | 51 | { 52 | let mut stdin: process::ChildStdin = try!(process.stdin.ok_or(CommandError::StdIn)); 53 | try!(stdin.write_all(input.as_bytes())); 54 | } 55 | 56 | let mut output = String::new(); 57 | 58 | let mut stdout: process::ChildStdout = try!(process.stdout.ok_or(CommandError::StdOut)); 59 | try!(stdout.read_to_string(&mut output)); 60 | 61 | Ok(output) 62 | } 63 | 64 | #[test] 65 | fn dry_run() { 66 | let output = run("cat", "", "lol").unwrap(); 67 | 68 | assert_eq!(output, "lol"); 69 | } 70 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | //! Compile EBooks for 'The Rust Programming Language' 2 | //! 3 | //! ['The Rust Programming Language'][trpl] is originally published as Markdown 4 | //! and rendered by _rustbook_. This set of scripts does some transformations 5 | //! and uses _Pandoc_ to render it as HTML, EPUB and PDF (usign LaTeX). 6 | //! 7 | //! [trpl]: http://doc.rust-lang.org/book/ 8 | 9 | #![cfg_attr(feature = "dev", feature(plugin))] 10 | #![cfg_attr(feature = "dev", plugin(clippy))] 11 | 12 | extern crate regex; 13 | extern crate docopt; 14 | extern crate rustc_serialize; 15 | 16 | use std::path::Path; 17 | use docopt::Docopt; 18 | 19 | pub mod helpers; 20 | pub mod convert_book; 21 | 22 | static USAGE: &'static str = r#" 23 | Compile Rustbook to EBook formats. 24 | 25 | Usage: 26 | compile-trpl [--prefix=<prefix>] [--source=<directory>] [--meta=<meta_file>] 27 | 28 | Options: 29 | --prefix=<prefix> Prefix/short name of your book, e.g. "trpl" or "nomicon". 30 | --source=<directory> Directory containing the git book files, especially SUMMARY.md and README.md. 31 | --meta=<meta_file> Meta data of your book, needs to contain `date: {release_date}`. 32 | "#; 33 | 34 | #[derive(Debug, RustcDecodable)] 35 | struct Args { 36 | flag_prefix: Option<String>, 37 | flag_source: Option<String>, 38 | flag_meta: Option<String>, 39 | } 40 | 41 | fn main() { 42 | let args: Args = Docopt::new(USAGE) 43 | .and_then(|d| d.decode()) 44 | .unwrap_or_else(|e| e.exit()); 45 | 46 | let prefix = args.flag_prefix.unwrap_or("trpl".to_owned()); 47 | let source = args.flag_source.unwrap_or("trpl".to_owned()); 48 | let meta = args.flag_meta.unwrap_or("trpl_meta.yml".to_owned()); 49 | 50 | convert_book::render_book(&prefix, &Path::new(&source), &meta).unwrap(); 51 | 52 | let index = convert_book::index::render_index("dist/").unwrap(); 53 | helpers::file::write_string_to_file(&index, "dist/index.html").unwrap(); 54 | println!("[✓] {}", "Index"); 55 | } 56 | -------------------------------------------------------------------------------- /trpl/README.md: -------------------------------------------------------------------------------- 1 | % The Rust Programming Language 2 | 3 | Welcome! This book will teach you about the [Rust Programming Language][rust]. 4 | Rust is a systems programming language focused on three goals: safety, speed, 5 | and concurrency. It maintains these goals without having a garbage collector, 6 | making it a useful language for a number of use cases other languages aren’t 7 | good at: embedding in other languages, programs with specific space and time 8 | requirements, and writing low-level code, like device drivers and operating 9 | systems. It improves on current languages targeting this space by having a 10 | number of compile-time safety checks that produce no runtime overhead, while 11 | eliminating all data races. Rust also aims to achieve ‘zero-cost abstractions’ 12 | even though some of these abstractions feel like those of a high-level language. 13 | Even then, Rust still allows precise control like a low-level language would. 14 | 15 | [rust]: https://www.rust-lang.org 16 | 17 | “The Rust Programming Language” is split into chapters. This introduction 18 | is the first. After this: 19 | 20 | * [Getting started][gs] - Set up your computer for Rust development. 21 | * [Tutorial: Guessing Game][gg] - Learn some Rust with a small project. 22 | * [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks. 23 | * [Effective Rust][er] - Higher-level concepts for writing excellent Rust code. 24 | * [Nightly Rust][nr] - Cutting-edge features that aren’t in stable builds yet. 25 | * [Glossary][gl] - A reference of terms used in the book. 26 | * [Bibliography][bi] - Background on Rust's influences, papers about Rust. 27 | 28 | [gs]: getting-started.html 29 | [gg]: guessing-game.html 30 | [er]: effective-rust.html 31 | [ss]: syntax-and-semantics.html 32 | [nr]: nightly-rust.html 33 | [gl]: glossary.html 34 | [bi]: bibliography.html 35 | 36 | ### Contributing 37 | 38 | The source files from which this book is generated can be found on 39 | [GitHub][book]. 40 | 41 | [book]: https://github.com/rust-lang/rust/tree/master/src/doc/book 42 | -------------------------------------------------------------------------------- /trpl/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Getting Started](getting-started.md) 4 | * [Tutorial: Guessing Game](guessing-game.md) 5 | * [Syntax and Semantics](syntax-and-semantics.md) 6 | * [Variable Bindings](variable-bindings.md) 7 | * [Functions](functions.md) 8 | * [Primitive Types](primitive-types.md) 9 | * [Comments](comments.md) 10 | * [if](if.md) 11 | * [Loops](loops.md) 12 | * [Vectors](vectors.md) 13 | * [Ownership](ownership.md) 14 | * [References and Borrowing](references-and-borrowing.md) 15 | * [Lifetimes](lifetimes.md) 16 | * [Mutability](mutability.md) 17 | * [Structs](structs.md) 18 | * [Enums](enums.md) 19 | * [Match](match.md) 20 | * [Patterns](patterns.md) 21 | * [Method Syntax](method-syntax.md) 22 | * [Strings](strings.md) 23 | * [Generics](generics.md) 24 | * [Traits](traits.md) 25 | * [Drop](drop.md) 26 | * [if let](if-let.md) 27 | * [Trait Objects](trait-objects.md) 28 | * [Closures](closures.md) 29 | * [Universal Function Call Syntax](ufcs.md) 30 | * [Crates and Modules](crates-and-modules.md) 31 | * [`const` and `static`](const-and-static.md) 32 | * [Attributes](attributes.md) 33 | * [`type` aliases](type-aliases.md) 34 | * [Casting between types](casting-between-types.md) 35 | * [Associated Types](associated-types.md) 36 | * [Unsized Types](unsized-types.md) 37 | * [Operators and Overloading](operators-and-overloading.md) 38 | * [Deref coercions](deref-coercions.md) 39 | * [Macros](macros.md) 40 | * [Raw Pointers](raw-pointers.md) 41 | * [`unsafe`](unsafe.md) 42 | * [Effective Rust](effective-rust.md) 43 | * [The Stack and the Heap](the-stack-and-the-heap.md) 44 | * [Testing](testing.md) 45 | * [Conditional Compilation](conditional-compilation.md) 46 | * [Documentation](documentation.md) 47 | * [Iterators](iterators.md) 48 | * [Concurrency](concurrency.md) 49 | * [Error Handling](error-handling.md) 50 | * [Choosing your Guarantees](choosing-your-guarantees.md) 51 | * [FFI](ffi.md) 52 | * [Borrow and AsRef](borrow-and-asref.md) 53 | * [Release Channels](release-channels.md) 54 | * [Using Rust without the standard library](using-rust-without-the-standard-library.md) 55 | * [Nightly Rust](nightly-rust.md) 56 | * [Compiler Plugins](compiler-plugins.md) 57 | * [Inline Assembly](inline-assembly.md) 58 | * [No stdlib](no-stdlib.md) 59 | * [Intrinsics](intrinsics.md) 60 | * [Lang items](lang-items.md) 61 | * [Advanced linking](advanced-linking.md) 62 | * [Benchmark Tests](benchmark-tests.md) 63 | * [Box Syntax and Patterns](box-syntax-and-patterns.md) 64 | * [Slice Patterns](slice-patterns.md) 65 | * [Associated Constants](associated-constants.md) 66 | * [Custom Allocators](custom-allocators.md) 67 | * [Glossary](glossary.md) 68 | * [Syntax Index](syntax-index.md) 69 | * [Bibliography](bibliography.md) 70 | -------------------------------------------------------------------------------- /trpl/associated-constants.md: -------------------------------------------------------------------------------- 1 | % Associated Constants 2 | 3 | With the `associated_consts` feature, you can define constants like this: 4 | 5 | ```rust 6 | #![feature(associated_consts)] 7 | 8 | trait Foo { 9 | const ID: i32; 10 | } 11 | 12 | impl Foo for i32 { 13 | const ID: i32 = 1; 14 | } 15 | 16 | fn main() { 17 | assert_eq!(1, i32::ID); 18 | } 19 | ``` 20 | 21 | Any implementor of `Foo` will have to define `ID`. Without the definition: 22 | 23 | ```rust,ignore 24 | #![feature(associated_consts)] 25 | 26 | trait Foo { 27 | const ID: i32; 28 | } 29 | 30 | impl Foo for i32 { 31 | } 32 | ``` 33 | 34 | gives 35 | 36 | ```text 37 | error: not all trait items implemented, missing: `ID` [E0046] 38 | impl Foo for i32 { 39 | } 40 | ``` 41 | 42 | A default value can be implemented as well: 43 | 44 | ```rust 45 | #![feature(associated_consts)] 46 | 47 | trait Foo { 48 | const ID: i32 = 1; 49 | } 50 | 51 | impl Foo for i32 { 52 | } 53 | 54 | impl Foo for i64 { 55 | const ID: i32 = 5; 56 | } 57 | 58 | fn main() { 59 | assert_eq!(1, i32::ID); 60 | assert_eq!(5, i64::ID); 61 | } 62 | ``` 63 | 64 | As you can see, when implementing `Foo`, you can leave it unimplemented, as 65 | with `i32`. It will then use the default value. But, as in `i64`, we can also 66 | add our own definition. 67 | 68 | Associated constants don’t have to be associated with a trait. An `impl` block 69 | for a `struct` or an `enum` works fine too: 70 | 71 | ```rust 72 | #![feature(associated_consts)] 73 | 74 | struct Foo; 75 | 76 | impl Foo { 77 | const FOO: u32 = 3; 78 | } 79 | ``` 80 | -------------------------------------------------------------------------------- /trpl/attributes.md: -------------------------------------------------------------------------------- 1 | % Attributes 2 | 3 | Declarations can be annotated with ‘attributes’ in Rust. They look like this: 4 | 5 | ```rust 6 | #[test] 7 | # fn foo() {} 8 | ``` 9 | 10 | or like this: 11 | 12 | ```rust 13 | # mod foo { 14 | #![test] 15 | # } 16 | ``` 17 | 18 | The difference between the two is the `!`, which changes what the attribute 19 | applies to: 20 | 21 | ```rust,ignore 22 | #[foo] 23 | struct Foo; 24 | 25 | mod bar { 26 | #![bar] 27 | } 28 | ``` 29 | 30 | The `#[foo]` attribute applies to the next item, which is the `struct` 31 | declaration. The `#![bar]` attribute applies to the item enclosing it, which is 32 | the `mod` declaration. Otherwise, they’re the same. Both change the meaning of 33 | the item they’re attached to somehow. 34 | 35 | For example, consider a function like this: 36 | 37 | ```rust 38 | #[test] 39 | fn check() { 40 | assert_eq!(2, 1 + 1); 41 | } 42 | ``` 43 | 44 | It is marked with `#[test]`. This means it’s special: when you run 45 | [tests][tests], this function will execute. When you compile as usual, it won’t 46 | even be included. This function is now a test function. 47 | 48 | [tests]: testing.html 49 | 50 | Attributes may also have additional data: 51 | 52 | ```rust 53 | #[inline(always)] 54 | fn super_fast_fn() { 55 | # } 56 | ``` 57 | 58 | Or even keys and values: 59 | 60 | ```rust 61 | #[cfg(target_os = "macos")] 62 | mod macos_only { 63 | # } 64 | ``` 65 | 66 | Rust attributes are used for a number of different things. There is a full list 67 | of attributes [in the reference][reference]. Currently, you are not allowed to 68 | create your own attributes, the Rust compiler defines them. 69 | 70 | [reference]: ../reference.html#attributes 71 | -------------------------------------------------------------------------------- /trpl/borrow-and-asref.md: -------------------------------------------------------------------------------- 1 | % Borrow and AsRef 2 | 3 | The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but 4 | different. Here’s a quick refresher on what these two traits mean. 5 | 6 | [borrow]: ../std/borrow/trait.Borrow.html 7 | [asref]: ../std/convert/trait.AsRef.html 8 | 9 | # Borrow 10 | 11 | The `Borrow` trait is used when you’re writing a datastructure, and you want to 12 | use either an owned or borrowed type as synonymous for some purpose. 13 | 14 | For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`: 15 | 16 | ```rust,ignore 17 | fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> 18 | where K: Borrow<Q>, 19 | Q: Hash + Eq 20 | ``` 21 | 22 | [hashmap]: ../std/collections/struct.HashMap.html 23 | [get]: ../std/collections/struct.HashMap.html#method.get 24 | 25 | This signature is pretty complicated. The `K` parameter is what we’re interested 26 | in here. It refers to a parameter of the `HashMap` itself: 27 | 28 | ```rust,ignore 29 | struct HashMap<K, V, S = RandomState> { 30 | ``` 31 | 32 | The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at 33 | the signature of `get()` again, we can use `get()` when the key implements 34 | `Borrow<Q>`. That way, we can make a `HashMap` which uses `String` keys, 35 | but use `&str`s when we’re searching: 36 | 37 | ```rust 38 | use std::collections::HashMap; 39 | 40 | let mut map = HashMap::new(); 41 | map.insert("Foo".to_string(), 42); 42 | 43 | assert_eq!(map.get("Foo"), Some(&42)); 44 | ``` 45 | 46 | This is because the standard library has `impl Borrow<str> for String`. 47 | 48 | For most types, when you want to take an owned or borrowed type, a `&T` is 49 | enough. But one area where `Borrow` is effective is when there’s more than one 50 | kind of borrowed value. This is especially true of references and slices: you 51 | can have both an `&T` or a `&mut T`. If we wanted to accept both of these types, 52 | `Borrow` is up for it: 53 | 54 | ```rust 55 | use std::borrow::Borrow; 56 | use std::fmt::Display; 57 | 58 | fn foo<T: Borrow<i32> + Display>(a: T) { 59 | println!("a is borrowed: {}", a); 60 | } 61 | 62 | let mut i = 5; 63 | 64 | foo(&i); 65 | foo(&mut i); 66 | ``` 67 | 68 | This will print out `a is borrowed: 5` twice. 69 | 70 | # AsRef 71 | 72 | The `AsRef` trait is a conversion trait. It’s used for converting some value to 73 | a reference in generic code. Like this: 74 | 75 | ```rust 76 | let s = "Hello".to_string(); 77 | 78 | fn foo<T: AsRef<str>>(s: T) { 79 | let slice = s.as_ref(); 80 | } 81 | ``` 82 | 83 | # Which should I use? 84 | 85 | We can see how they’re kind of the same: they both deal with owned and borrowed 86 | versions of some type. However, they’re a bit different. 87 | 88 | Choose `Borrow` when you want to abstract over different kinds of borrowing, or 89 | when you’re building a datastructure that treats owned and borrowed values in 90 | equivalent ways, such as hashing and comparison. 91 | 92 | Choose `AsRef` when you want to convert something to a reference directly, and 93 | you’re writing generic code. 94 | -------------------------------------------------------------------------------- /trpl/box-syntax-and-patterns.md: -------------------------------------------------------------------------------- 1 | % Box Syntax and Patterns 2 | 3 | Currently the only stable way to create a `Box` is via the `Box::new` method. 4 | Also it is not possible in stable Rust to destructure a `Box` in a match 5 | pattern. The unstable `box` keyword can be used to both create and destructure 6 | a `Box`. An example usage would be: 7 | 8 | ```rust 9 | #![feature(box_syntax, box_patterns)] 10 | 11 | fn main() { 12 | let b = Some(box 5); 13 | match b { 14 | Some(box n) if n < 0 => { 15 | println!("Box contains negative number {}", n); 16 | }, 17 | Some(box n) if n >= 0 => { 18 | println!("Box contains non-negative number {}", n); 19 | }, 20 | None => { 21 | println!("No box"); 22 | }, 23 | _ => unreachable!() 24 | } 25 | } 26 | ``` 27 | 28 | Note that these features are currently hidden behind the `box_syntax` (box 29 | creation) and `box_patterns` (destructuring and pattern matching) gates 30 | because the syntax may still change in the future. 31 | 32 | # Returning Pointers 33 | 34 | In many languages with pointers, you'd return a pointer from a function 35 | so as to avoid copying a large data structure. For example: 36 | 37 | ```rust 38 | struct BigStruct { 39 | one: i32, 40 | two: i32, 41 | // etc 42 | one_hundred: i32, 43 | } 44 | 45 | fn foo(x: Box<BigStruct>) -> Box<BigStruct> { 46 | Box::new(*x) 47 | } 48 | 49 | fn main() { 50 | let x = Box::new(BigStruct { 51 | one: 1, 52 | two: 2, 53 | one_hundred: 100, 54 | }); 55 | 56 | let y = foo(x); 57 | } 58 | ``` 59 | 60 | The idea is that by passing around a box, you're only copying a pointer, rather 61 | than the hundred `i32`s that make up the `BigStruct`. 62 | 63 | This is an antipattern in Rust. Instead, write this: 64 | 65 | ```rust 66 | #![feature(box_syntax)] 67 | 68 | struct BigStruct { 69 | one: i32, 70 | two: i32, 71 | // etc 72 | one_hundred: i32, 73 | } 74 | 75 | fn foo(x: Box<BigStruct>) -> BigStruct { 76 | *x 77 | } 78 | 79 | fn main() { 80 | let x = Box::new(BigStruct { 81 | one: 1, 82 | two: 2, 83 | one_hundred: 100, 84 | }); 85 | 86 | let y: Box<BigStruct> = box foo(x); 87 | } 88 | ``` 89 | 90 | This gives you flexibility without sacrificing performance. 91 | 92 | You may think that this gives us terrible performance: return a value and then 93 | immediately box it up ?! Isn't this pattern the worst of both worlds? Rust is 94 | smarter than that. There is no copy in this code. `main` allocates enough room 95 | for the `box`, passes a pointer to that memory into `foo` as `x`, and then 96 | `foo` writes the value straight into the `Box<T>`. 97 | 98 | This is important enough that it bears repeating: pointers are not for 99 | optimizing returning values from your code. Allow the caller to choose how they 100 | want to use your output. 101 | -------------------------------------------------------------------------------- /trpl/comments.md: -------------------------------------------------------------------------------- 1 | % Comments 2 | 3 | Now that we have some functions, it’s a good idea to learn about comments. 4 | Comments are notes that you leave to other programmers to help explain things 5 | about your code. The compiler mostly ignores them. 6 | 7 | Rust has two kinds of comments that you should care about: *line comments* 8 | and *doc comments*. 9 | 10 | ```rust 11 | // Line comments are anything after ‘//’ and extend to the end of the line. 12 | 13 | let x = 5; // this is also a line comment. 14 | 15 | // If you have a long explanation for something, you can put line comments next 16 | // to each other. Put a space between the // and your comment so that it’s 17 | // more readable. 18 | ``` 19 | 20 | The other kind of comment is a doc comment. Doc comments use `///` instead of 21 | `//`, and support Markdown notation inside: 22 | 23 | ```rust 24 | /// Adds one to the number given. 25 | /// 26 | /// # Examples 27 | /// 28 | /// ``` 29 | /// let five = 5; 30 | /// 31 | /// assert_eq!(6, add_one(5)); 32 | /// # fn add_one(x: i32) -> i32 { 33 | /// # x + 1 34 | /// # } 35 | /// ``` 36 | fn add_one(x: i32) -> i32 { 37 | x + 1 38 | } 39 | ``` 40 | 41 | There is another style of doc comment, `//!`, to comment containing items (e.g. 42 | crates, modules or functions), instead of the items following it. Commonly used 43 | inside crates root (lib.rs) or modules root (mod.rs): 44 | 45 | ``` 46 | //! # The Rust Standard Library 47 | //! 48 | //! The Rust Standard Library provides the essential runtime 49 | //! functionality for building portable Rust software. 50 | ``` 51 | 52 | When writing doc comments, providing some examples of usage is very, very 53 | helpful. You’ll notice we’ve used a new macro here: `assert_eq!`. This compares 54 | two values, and `panic!`s if they’re not equal to each other. It’s very helpful 55 | in documentation. There’s another macro, `assert!`, which `panic!`s if the 56 | value passed to it is `false`. 57 | 58 | You can use the [`rustdoc`](documentation.html) tool to generate HTML documentation 59 | from these doc comments, and also to run the code examples as tests! 60 | -------------------------------------------------------------------------------- /trpl/conditional-compilation.md: -------------------------------------------------------------------------------- 1 | % Conditional Compilation 2 | 3 | Rust has a special attribute, `#[cfg]`, which allows you to compile code 4 | based on a flag passed to the compiler. It has two forms: 5 | 6 | ```rust 7 | #[cfg(foo)] 8 | # fn foo() {} 9 | 10 | #[cfg(bar = "baz")] 11 | # fn bar() {} 12 | ``` 13 | 14 | They also have some helpers: 15 | 16 | ```rust 17 | #[cfg(any(unix, windows))] 18 | # fn foo() {} 19 | 20 | #[cfg(all(unix, target_pointer_width = "32"))] 21 | # fn bar() {} 22 | 23 | #[cfg(not(foo))] 24 | # fn not_foo() {} 25 | ``` 26 | 27 | These can nest arbitrarily: 28 | 29 | ```rust 30 | #[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))] 31 | # fn foo() {} 32 | ``` 33 | 34 | As for how to enable or disable these switches, if you’re using Cargo, 35 | they get set in the [`[features]` section][features] of your `Cargo.toml`: 36 | 37 | [features]: http://doc.crates.io/manifest.html#the-features-section 38 | 39 | ```toml 40 | [features] 41 | # no features by default 42 | default = [] 43 | 44 | # Add feature "foo" here, then you can use it. 45 | # Our "foo" feature depends on nothing else. 46 | foo = [] 47 | ``` 48 | 49 | When you do this, Cargo passes along a flag to `rustc`: 50 | 51 | ```text 52 | --cfg feature="${feature_name}" 53 | ``` 54 | 55 | The sum of these `cfg` flags will determine which ones get activated, and 56 | therefore, which code gets compiled. Let’s take this code: 57 | 58 | ```rust 59 | #[cfg(feature = "foo")] 60 | mod foo { 61 | } 62 | ``` 63 | 64 | If we compile it with `cargo build --features "foo"`, it will send the `--cfg 65 | feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it. 66 | If we compile it with a regular `cargo build`, no extra flags get passed on, 67 | and so, no `foo` module will exist. 68 | 69 | # cfg_attr 70 | 71 | You can also set another attribute based on a `cfg` variable with `cfg_attr`: 72 | 73 | ```rust 74 | #[cfg_attr(a, b)] 75 | # fn foo() {} 76 | ``` 77 | 78 | Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise. 79 | 80 | # cfg! 81 | 82 | The `cfg!` [syntax extension][compilerplugins] lets you use these kinds of flags 83 | elsewhere in your code, too: 84 | 85 | ```rust 86 | if cfg!(target_os = "macos") || cfg!(target_os = "ios") { 87 | println!("Think Different!"); 88 | } 89 | ``` 90 | 91 | [compilerplugins]: compiler-plugins.html 92 | 93 | These will be replaced by a `true` or `false` at compile-time, depending on the 94 | configuration settings. 95 | -------------------------------------------------------------------------------- /trpl/const-and-static.md: -------------------------------------------------------------------------------- 1 | % `const` and `static` 2 | 3 | Rust has a way of defining constants with the `const` keyword: 4 | 5 | ```rust 6 | const N: i32 = 5; 7 | ``` 8 | 9 | Unlike [`let`][let] bindings, you must annotate the type of a `const`. 10 | 11 | [let]: variable-bindings.html 12 | 13 | Constants live for the entire lifetime of a program. More specifically, 14 | constants in Rust have no fixed address in memory. This is because they’re 15 | effectively inlined to each place that they’re used. References to the same 16 | constant are not necessarily guaranteed to refer to the same memory address for 17 | this reason. 18 | 19 | # `static` 20 | 21 | Rust provides a ‘global variable’ sort of facility in static items. They’re 22 | similar to constants, but static items aren’t inlined upon use. This means that 23 | there is only one instance for each value, and it’s at a fixed location in 24 | memory. 25 | 26 | Here’s an example: 27 | 28 | ```rust 29 | static N: i32 = 5; 30 | ``` 31 | 32 | Unlike [`let`][let] bindings, you must annotate the type of a `static`. 33 | 34 | Statics live for the entire lifetime of a program, and therefore any 35 | reference stored in a constant has a [`'static` lifetime][lifetimes]: 36 | 37 | ```rust 38 | static NAME: &'static str = "Steve"; 39 | ``` 40 | 41 | [lifetimes]: lifetimes.html 42 | 43 | ## Mutability 44 | 45 | You can introduce mutability with the `mut` keyword: 46 | 47 | ```rust 48 | static mut N: i32 = 5; 49 | ``` 50 | 51 | Because this is mutable, one thread could be updating `N` while another is 52 | reading it, causing memory unsafety. As such both accessing and mutating a 53 | `static mut` is [`unsafe`][unsafe], and so must be done in an `unsafe` block: 54 | 55 | ```rust 56 | # static mut N: i32 = 5; 57 | 58 | unsafe { 59 | N += 1; 60 | 61 | println!("N: {}", N); 62 | } 63 | ``` 64 | 65 | [unsafe]: unsafe.html 66 | 67 | Furthermore, any type stored in a `static` must be `Sync`, and must not have 68 | a [`Drop`][drop] implementation. 69 | 70 | [drop]: drop.html 71 | 72 | # Initializing 73 | 74 | Both `const` and `static` have requirements for giving them a value. They must 75 | be given a value that’s a constant expression. In other words, you cannot use 76 | the result of a function call or anything similarly complex or at runtime. 77 | 78 | # Which construct should I use? 79 | 80 | Almost always, if you can choose between the two, choose `const`. It’s pretty 81 | rare that you actually want a memory location associated with your constant, 82 | and using a `const` allows for optimizations like constant propagation not only 83 | in your crate but downstream crates. 84 | -------------------------------------------------------------------------------- /trpl/deref-coercions.md: -------------------------------------------------------------------------------- 1 | % `Deref` coercions 2 | 3 | The standard library provides a special trait, [`Deref`][deref]. It’s normally 4 | used to overload `*`, the dereference operator: 5 | 6 | ```rust 7 | use std::ops::Deref; 8 | 9 | struct DerefExample<T> { 10 | value: T, 11 | } 12 | 13 | impl<T> Deref for DerefExample<T> { 14 | type Target = T; 15 | 16 | fn deref(&self) -> &T { 17 | &self.value 18 | } 19 | } 20 | 21 | fn main() { 22 | let x = DerefExample { value: 'a' }; 23 | assert_eq!('a', *x); 24 | } 25 | ``` 26 | 27 | [deref]: ../std/ops/trait.Deref.html 28 | 29 | This is useful for writing custom pointer types. However, there’s a language 30 | feature related to `Deref`: ‘deref coercions’. Here’s the rule: If you have a 31 | type `U`, and it implements `Deref<Target=T>`, values of `&U` will 32 | automatically coerce to a `&T`. Here’s an example: 33 | 34 | ```rust 35 | fn foo(s: &str) { 36 | // borrow a string for a second 37 | } 38 | 39 | // String implements Deref<Target=str> 40 | let owned = "Hello".to_string(); 41 | 42 | // therefore, this works: 43 | foo(&owned); 44 | ``` 45 | 46 | Using an ampersand in front of a value takes a reference to it. So `owned` is a 47 | `String`, `&owned` is an `&String`, and since `impl Deref<Target=str> for 48 | String`, `&String` will deref to `&str`, which `foo()` takes. 49 | 50 | That’s it. This rule is one of the only places in which Rust does an automatic 51 | conversion for you, but it adds a lot of flexibility. For example, the `Rc<T>` 52 | type implements `Deref<Target=T>`, so this works: 53 | 54 | ```rust 55 | use std::rc::Rc; 56 | 57 | fn foo(s: &str) { 58 | // borrow a string for a second 59 | } 60 | 61 | // String implements Deref<Target=str> 62 | let owned = "Hello".to_string(); 63 | let counted = Rc::new(owned); 64 | 65 | // therefore, this works: 66 | foo(&counted); 67 | ``` 68 | 69 | All we’ve done is wrap our `String` in an `Rc<T>`. But we can now pass the 70 | `Rc<String>` around anywhere we’d have a `String`. The signature of `foo` 71 | didn’t change, but works just as well with either type. This example has two 72 | conversions: `Rc<String>` to `String` and then `String` to `&str`. Rust will do 73 | this as many times as possible until the types match. 74 | 75 | Another very common implementation provided by the standard library is: 76 | 77 | ```rust 78 | fn foo(s: &[i32]) { 79 | // borrow a slice for a second 80 | } 81 | 82 | // Vec<T> implements Deref<Target=[T]> 83 | let owned = vec![1, 2, 3]; 84 | 85 | foo(&owned); 86 | ``` 87 | 88 | Vectors can `Deref` to a slice. 89 | 90 | ## Deref and method calls 91 | 92 | `Deref` will also kick in when calling a method. Consider the following 93 | example. 94 | 95 | ```rust 96 | struct Foo; 97 | 98 | impl Foo { 99 | fn foo(&self) { println!("Foo"); } 100 | } 101 | 102 | let f = &&Foo; 103 | 104 | f.foo(); 105 | ``` 106 | 107 | Even though `f` is a `&&Foo` and `foo` takes `&self`, this works. That’s 108 | because these things are the same: 109 | 110 | ```rust,ignore 111 | f.foo(); 112 | (&f).foo(); 113 | (&&f).foo(); 114 | (&&&&&&&&f).foo(); 115 | ``` 116 | 117 | A value of type `&&&&&&&&&&&&&&&&Foo` can still have methods defined on `Foo` 118 | called, because the compiler will insert as many * operations as necessary to 119 | get it right. And since it’s inserting `*`s, that uses `Deref`. 120 | -------------------------------------------------------------------------------- /trpl/drop.md: -------------------------------------------------------------------------------- 1 | % Drop 2 | 3 | Now that we’ve discussed traits, let’s talk about a particular trait provided 4 | by the Rust standard library, [`Drop`][drop]. The `Drop` trait provides a way 5 | to run some code when a value goes out of scope. For example: 6 | 7 | [drop]: ../std/ops/trait.Drop.html 8 | 9 | ```rust 10 | struct HasDrop; 11 | 12 | impl Drop for HasDrop { 13 | fn drop(&mut self) { 14 | println!("Dropping!"); 15 | } 16 | } 17 | 18 | fn main() { 19 | let x = HasDrop; 20 | 21 | // do stuff 22 | 23 | } // x goes out of scope here 24 | ``` 25 | 26 | When `x` goes out of scope at the end of `main()`, the code for `Drop` will 27 | run. `Drop` has one method, which is also called `drop()`. It takes a mutable 28 | reference to `self`. 29 | 30 | That’s it! The mechanics of `Drop` are very simple, but there are some 31 | subtleties. For example, values are dropped in the opposite order they are 32 | declared. Here’s another example: 33 | 34 | ```rust 35 | struct Firework { 36 | strength: i32, 37 | } 38 | 39 | impl Drop for Firework { 40 | fn drop(&mut self) { 41 | println!("BOOM times {}!!!", self.strength); 42 | } 43 | } 44 | 45 | fn main() { 46 | let firecracker = Firework { strength: 1 }; 47 | let tnt = Firework { strength: 100 }; 48 | } 49 | ``` 50 | 51 | This will output: 52 | 53 | ```text 54 | BOOM times 100!!! 55 | BOOM times 1!!! 56 | ``` 57 | 58 | The `tnt` goes off before the `firecracker` does, because it was declared 59 | afterwards. Last in, first out. 60 | 61 | So what is `Drop` good for? Generally, `Drop` is used to clean up any resources 62 | associated with a `struct`. For example, the [`Arc<T>` type][arc] is a 63 | reference-counted type. When `Drop` is called, it will decrement the reference 64 | count, and if the total number of references is zero, will clean up the 65 | underlying value. 66 | 67 | [arc]: ../std/sync/struct.Arc.html 68 | -------------------------------------------------------------------------------- /trpl/effective-rust.md: -------------------------------------------------------------------------------- 1 | % Effective Rust 2 | 3 | So you’ve learned how to write some Rust code. But there’s a difference between 4 | writing *any* Rust code and writing *good* Rust code. 5 | 6 | This chapter consists of relatively independent tutorials which show you how to 7 | take your Rust to the next level. Common patterns and standard library features 8 | will be introduced. Read these sections in any order of your choosing. 9 | -------------------------------------------------------------------------------- /trpl/enums.md: -------------------------------------------------------------------------------- 1 | % Enums 2 | 3 | An `enum` in Rust is a type that represents data that is one of 4 | several possible variants. Each variant in the `enum` can optionally 5 | have data associated with it: 6 | 7 | ```rust 8 | enum Message { 9 | Quit, 10 | ChangeColor(i32, i32, i32), 11 | Move { x: i32, y: i32 }, 12 | Write(String), 13 | } 14 | ``` 15 | 16 | The syntax for defining variants resembles the syntaxes used to define structs: 17 | you can have variants with no data (like unit-like structs), variants with named 18 | data, and variants with unnamed data (like tuple structs). Unlike 19 | separate struct definitions, however, an `enum` is a single type. A 20 | value of the enum can match any of the variants. For this reason, an 21 | enum is sometimes called a ‘sum type’: the set of possible values of the 22 | enum is the sum of the sets of possible values for each variant. 23 | 24 | We use the `::` syntax to use the name of each variant: they’re scoped by the name 25 | of the `enum` itself. This allows both of these to work: 26 | 27 | ```rust 28 | # enum Message { 29 | # Move { x: i32, y: i32 }, 30 | # } 31 | let x: Message = Message::Move { x: 3, y: 4 }; 32 | 33 | enum BoardGameTurn { 34 | Move { squares: i32 }, 35 | Pass, 36 | } 37 | 38 | let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 }; 39 | ``` 40 | 41 | Both variants are named `Move`, but since they’re scoped to the name of 42 | the enum, they can both be used without conflict. 43 | 44 | A value of an `enum` type contains information about which variant it is, 45 | in addition to any data associated with that variant. This is sometimes 46 | referred to as a ‘tagged union’, since the data includes a ‘tag’ 47 | indicating what type it is. The compiler uses this information to 48 | enforce that you’re accessing the data in the enum safely. For instance, 49 | you can’t simply try to destructure a value as if it were one of the 50 | possible variants: 51 | 52 | ```rust,ignore 53 | fn process_color_change(msg: Message) { 54 | let Message::ChangeColor(r, g, b) = msg; // compile-time error 55 | } 56 | ``` 57 | 58 | Not supporting these operations may seem rather limiting, but it’s a limitation 59 | which we can overcome. There are two ways: by implementing equality ourselves, 60 | or by pattern matching variants with [`match`][match] expressions, which you’ll 61 | learn in the next section. We don’t know enough about Rust to implement 62 | equality yet, but we’ll find out in the [`traits`][traits] section. 63 | 64 | [match]: match.html 65 | [traits]: traits.html 66 | 67 | # Constructors as functions 68 | 69 | An `enum` constructor can also be used like a function. For example: 70 | 71 | ```rust 72 | # enum Message { 73 | # Write(String), 74 | # } 75 | let m = Message::Write("Hello, world".to_string()); 76 | ``` 77 | 78 | is the same as 79 | 80 | ```rust 81 | # enum Message { 82 | # Write(String), 83 | # } 84 | fn foo(x: String) -> Message { 85 | Message::Write(x) 86 | } 87 | 88 | let x = foo("Hello, world".to_string()); 89 | ``` 90 | 91 | This is not immediately useful to us, but when we get to 92 | [`closures`][closures], we’ll talk about passing functions as arguments to 93 | other functions. For example, with [`iterators`][iterators], we can do this 94 | to convert a vector of `String`s into a vector of `Message::Write`s: 95 | 96 | ```rust 97 | # enum Message { 98 | # Write(String), 99 | # } 100 | 101 | let v = vec!["Hello".to_string(), "World".to_string()]; 102 | 103 | let v1: Vec<Message> = v.into_iter().map(Message::Write).collect(); 104 | ``` 105 | 106 | [closures]: closures.html 107 | [iterators]: iterators.html 108 | -------------------------------------------------------------------------------- /trpl/generics.md: -------------------------------------------------------------------------------- 1 | % Generics 2 | 3 | Sometimes, when writing a function or data type, we may want it to work for 4 | multiple types of arguments. In Rust, we can do this with generics. 5 | Generics are called ‘parametric polymorphism’ in type theory, 6 | which means that they are types or functions that have multiple forms (‘poly’ 7 | is multiple, ‘morph’ is form) over a given parameter (‘parametric’). 8 | 9 | Anyway, enough type theory, let’s check out some generic code. Rust’s 10 | standard library provides a type, `Option<T>`, that’s generic: 11 | 12 | ```rust 13 | enum Option<T> { 14 | Some(T), 15 | None, 16 | } 17 | ``` 18 | 19 | The `<T>` part, which you’ve seen a few times before, indicates that this is 20 | a generic data type. Inside the declaration of our `enum`, wherever we see a `T`, 21 | we substitute that type for the same type used in the generic. Here’s an 22 | example of using `Option<T>`, with some extra type annotations: 23 | 24 | ```rust 25 | let x: Option<i32> = Some(5); 26 | ``` 27 | 28 | In the type declaration, we say `Option<i32>`. Note how similar this looks to 29 | `Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On 30 | the right-hand side of the binding, we make a `Some(T)`, where `T` is `5`. 31 | Since that’s an `i32`, the two sides match, and Rust is happy. If they didn’t 32 | match, we’d get an error: 33 | 34 | ```rust,ignore 35 | let x: Option<f64> = Some(5); 36 | // error: mismatched types: expected `core::option::Option<f64>`, 37 | // found `core::option::Option<_>` (expected f64 but found integral variable) 38 | ``` 39 | 40 | That doesn’t mean we can’t make `Option<T>`s that hold an `f64`! They have 41 | to match up: 42 | 43 | ```rust 44 | let x: Option<i32> = Some(5); 45 | let y: Option<f64> = Some(5.0f64); 46 | ``` 47 | 48 | This is just fine. One definition, multiple uses. 49 | 50 | Generics don’t have to only be generic over one type. Consider another type from Rust’s standard library that’s similar, `Result<T, E>`: 51 | 52 | ```rust 53 | enum Result<T, E> { 54 | Ok(T), 55 | Err(E), 56 | } 57 | ``` 58 | 59 | This type is generic over _two_ types: `T` and `E`. By the way, the capital letters 60 | can be any letter you’d like. We could define `Result<T, E>` as: 61 | 62 | ```rust 63 | enum Result<A, Z> { 64 | Ok(A), 65 | Err(Z), 66 | } 67 | ``` 68 | 69 | if we wanted to. Convention says that the first generic parameter should be 70 | `T`, for ‘type’, and that we use `E` for ‘error’. Rust doesn’t care, however. 71 | 72 | The `Result<T, E>` type is intended to be used to return the result of a 73 | computation, and to have the ability to return an error if it didn’t work out. 74 | 75 | ## Generic functions 76 | 77 | We can write functions that take generic types with a similar syntax: 78 | 79 | ```rust 80 | fn takes_anything<T>(x: T) { 81 | // do something with x 82 | } 83 | ``` 84 | 85 | The syntax has two parts: the `<T>` says “this function is generic over one 86 | type, `T`”, and the `x: T` says “x has the type `T`.” 87 | 88 | Multiple arguments can have the same generic type: 89 | 90 | ```rust 91 | fn takes_two_of_the_same_things<T>(x: T, y: T) { 92 | // ... 93 | } 94 | ``` 95 | 96 | We could write a version that takes multiple types: 97 | 98 | ```rust 99 | fn takes_two_things<T, U>(x: T, y: U) { 100 | // ... 101 | } 102 | ``` 103 | 104 | ## Generic structs 105 | 106 | You can store a generic type in a `struct` as well: 107 | 108 | ```rust 109 | struct Point<T> { 110 | x: T, 111 | y: T, 112 | } 113 | 114 | let int_origin = Point { x: 0, y: 0 }; 115 | let float_origin = Point { x: 0.0, y: 0.0 }; 116 | ``` 117 | 118 | Similar to functions, the `<T>` is where we declare the generic parameters, 119 | and we then use `x: T` in the type declaration, too. 120 | 121 | When you want to add an implementation for the generic `struct`, you 122 | declare the type parameter after the `impl`: 123 | 124 | ```rust 125 | # struct Point<T> { 126 | # x: T, 127 | # y: T, 128 | # } 129 | # 130 | impl<T> Point<T> { 131 | fn swap(&mut self) { 132 | std::mem::swap(&mut self.x, &mut self.y); 133 | } 134 | } 135 | ``` 136 | 137 | So far you’ve seen generics that take absolutely any type. These are useful in 138 | many cases: you’ve already seen `Option<T>`, and later you’ll meet universal 139 | container types like [`Vec<T>`][Vec]. On the other hand, often you want to 140 | trade that flexibility for increased expressive power. Read about [trait 141 | bounds][traits] to see why and how. 142 | 143 | [traits]: traits.html 144 | [Vec]: ../std/vec/struct.Vec.html 145 | -------------------------------------------------------------------------------- /trpl/glossary.md: -------------------------------------------------------------------------------- 1 | % Glossary 2 | 3 | Not every Rustacean has a background in systems programming, nor in computer 4 | science, so we've added explanations of terms that might be unfamiliar. 5 | 6 | ### Abstract Syntax Tree 7 | 8 | When a compiler is compiling your program, it does a number of different things. 9 | One of the things that it does is turn the text of your program into an 10 | ‘abstract syntax tree’, or ‘AST’. This tree is a representation of the structure 11 | of your program. For example, `2 + 3` can be turned into a tree: 12 | 13 | ```text 14 | + 15 | / \ 16 | 2 3 17 | ``` 18 | 19 | And `2 + (3 * 4)` would look like this: 20 | 21 | ```text 22 | + 23 | / \ 24 | 2 * 25 | / \ 26 | 3 4 27 | ``` 28 | 29 | ### Arity 30 | 31 | Arity refers to the number of arguments a function or operation takes. 32 | 33 | ```rust 34 | let x = (2, 3); 35 | let y = (4, 6); 36 | let z = (8, 2, 6); 37 | ``` 38 | 39 | In the example above `x` and `y` have arity 2. `z` has arity 3. 40 | 41 | ### Bounds 42 | 43 | Bounds are constraints on a type or [trait][traits]. For example, if a bound 44 | is placed on the argument a function takes, types passed to that function 45 | must abide by that constraint. 46 | 47 | [traits]: traits.html 48 | 49 | ### Combinators 50 | 51 | Combinators are higher-order functions that apply only functions and 52 | earlier defined combinators to provide a result from its arguments. 53 | They can be used to manage control flow in a modular fashion. 54 | 55 | ### DST (Dynamically Sized Type) 56 | 57 | A type without a statically known size or alignment. ([more info][link]) 58 | 59 | [link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-dsts 60 | 61 | ### Expression 62 | 63 | In computer programming, an expression is a combination of values, constants, 64 | variables, operators and functions that evaluate to a single value. For example, 65 | `2 + (3 * 4)` is an expression that returns the value 14. It is worth noting 66 | that expressions can have side-effects. For example, a function included in an 67 | expression might perform actions other than simply returning a value. 68 | 69 | ### Expression-Oriented Language 70 | 71 | In early programming languages, [expressions][expression] and 72 | [statements][statement] were two separate syntactic categories: expressions had 73 | a value and statements did things. However, later languages blurred this 74 | distinction, allowing expressions to do things and statements to have a value. 75 | In an expression-oriented language, (nearly) every statement is an expression 76 | and therefore returns a value. Consequently, these expression statements can 77 | themselves form part of larger expressions. 78 | 79 | [expression]: glossary.html#expression 80 | [statement]: glossary.html#statement 81 | 82 | ### Statement 83 | 84 | In computer programming, a statement is the smallest standalone element of a 85 | programming language that commands a computer to perform an action. 86 | -------------------------------------------------------------------------------- /trpl/if-let.md: -------------------------------------------------------------------------------- 1 | % if let 2 | 3 | `if let` allows you to combine `if` and `let` together to reduce the overhead 4 | of certain kinds of pattern matches. 5 | 6 | For example, let’s say we have some sort of `Option<T>`. We want to call a function 7 | on it if it’s `Some<T>`, but do nothing if it’s `None`. That looks like this: 8 | 9 | ```rust 10 | # let option = Some(5); 11 | # fn foo(x: i32) { } 12 | match option { 13 | Some(x) => { foo(x) }, 14 | None => {}, 15 | } 16 | ``` 17 | 18 | We don’t have to use `match` here, for example, we could use `if`: 19 | 20 | ```rust 21 | # let option = Some(5); 22 | # fn foo(x: i32) { } 23 | if option.is_some() { 24 | let x = option.unwrap(); 25 | foo(x); 26 | } 27 | ``` 28 | 29 | Neither of these options is particularly appealing. We can use `if let` to 30 | do the same thing in a nicer way: 31 | 32 | ```rust 33 | # let option = Some(5); 34 | # fn foo(x: i32) { } 35 | if let Some(x) = option { 36 | foo(x); 37 | } 38 | ``` 39 | 40 | If a [pattern][patterns] matches successfully, it binds any appropriate parts of 41 | the value to the identifiers in the pattern, then evaluates the expression. If 42 | the pattern doesn’t match, nothing happens. 43 | 44 | If you want to do something else when the pattern does not match, you can 45 | use `else`: 46 | 47 | ```rust 48 | # let option = Some(5); 49 | # fn foo(x: i32) { } 50 | # fn bar() { } 51 | if let Some(x) = option { 52 | foo(x); 53 | } else { 54 | bar(); 55 | } 56 | ``` 57 | 58 | ## `while let` 59 | 60 | In a similar fashion, `while let` can be used when you want to conditionally 61 | loop as long as a value matches a certain pattern. It turns code like this: 62 | 63 | ```rust 64 | let mut v = vec![1, 3, 5, 7, 11]; 65 | loop { 66 | match v.pop() { 67 | Some(x) => println!("{}", x), 68 | None => break, 69 | } 70 | } 71 | ``` 72 | 73 | Into code like this: 74 | 75 | ```rust 76 | let mut v = vec![1, 3, 5, 7, 11]; 77 | while let Some(x) = v.pop() { 78 | println!("{}", x); 79 | } 80 | ``` 81 | 82 | [patterns]: patterns.html 83 | -------------------------------------------------------------------------------- /trpl/if.md: -------------------------------------------------------------------------------- 1 | % if 2 | 3 | Rust’s take on `if` is not particularly complex, but it’s much more like the 4 | `if` you’ll find in a dynamically typed language than in a more traditional 5 | systems language. So let’s talk about it, to make sure you grasp the nuances. 6 | 7 | `if` is a specific form of a more general concept, the ‘branch’, whose name comes 8 | from a branch in a tree: a decision point, where depending on a choice, 9 | multiple paths can be taken. 10 | 11 | In the case of `if`, there is one choice that leads down two paths: 12 | 13 | ```rust 14 | let x = 5; 15 | 16 | if x == 5 { 17 | println!("x is five!"); 18 | } 19 | ``` 20 | 21 | If we changed the value of `x` to something else, this line would not print. 22 | More specifically, if the expression after the `if` evaluates to `true`, then 23 | the block is executed. If it’s `false`, then it is not. 24 | 25 | If you want something to happen in the `false` case, use an `else`: 26 | 27 | ```rust 28 | let x = 5; 29 | 30 | if x == 5 { 31 | println!("x is five!"); 32 | } else { 33 | println!("x is not five :("); 34 | } 35 | ``` 36 | 37 | If there is more than one case, use an `else if`: 38 | 39 | ```rust 40 | let x = 5; 41 | 42 | if x == 5 { 43 | println!("x is five!"); 44 | } else if x == 6 { 45 | println!("x is six!"); 46 | } else { 47 | println!("x is not five or six :("); 48 | } 49 | ``` 50 | 51 | This is all pretty standard. However, you can also do this: 52 | 53 | ```rust 54 | let x = 5; 55 | 56 | let y = if x == 5 { 57 | 10 58 | } else { 59 | 15 60 | }; // y: i32 61 | ``` 62 | 63 | Which we can (and probably should) write like this: 64 | 65 | ```rust 66 | let x = 5; 67 | 68 | let y = if x == 5 { 10 } else { 15 }; // y: i32 69 | ``` 70 | 71 | This works because `if` is an expression. The value of the expression is the 72 | value of the last expression in whichever branch was chosen. An `if` without an 73 | `else` always results in `()` as the value. 74 | -------------------------------------------------------------------------------- /trpl/intrinsics.md: -------------------------------------------------------------------------------- 1 | % Intrinsics 2 | 3 | > **Note**: intrinsics will forever have an unstable interface, it is 4 | > recommended to use the stable interfaces of libcore rather than intrinsics 5 | > directly. 6 | 7 | These are imported as if they were FFI functions, with the special 8 | `rust-intrinsic` ABI. For example, if one was in a freestanding 9 | context, but wished to be able to `transmute` between types, and 10 | perform efficient pointer arithmetic, one would import those functions 11 | via a declaration like 12 | 13 | ```rust 14 | #![feature(intrinsics)] 15 | # fn main() {} 16 | 17 | extern "rust-intrinsic" { 18 | fn transmute<T, U>(x: T) -> U; 19 | 20 | fn offset<T>(dst: *const T, offset: isize) -> *const T; 21 | } 22 | ``` 23 | 24 | As with any other FFI functions, these are always `unsafe` to call. 25 | 26 | -------------------------------------------------------------------------------- /trpl/lang-items.md: -------------------------------------------------------------------------------- 1 | % Lang items 2 | 3 | > **Note**: lang items are often provided by crates in the Rust distribution, 4 | > and lang items themselves have an unstable interface. It is recommended to use 5 | > officially distributed crates instead of defining your own lang items. 6 | 7 | The `rustc` compiler has certain pluggable operations, that is, 8 | functionality that isn't hard-coded into the language, but is 9 | implemented in libraries, with a special marker to tell the compiler 10 | it exists. The marker is the attribute `#[lang = "..."]` and there are 11 | various different values of `...`, i.e. various different 'lang 12 | items'. 13 | 14 | For example, `Box` pointers require two lang items, one for allocation 15 | and one for deallocation. A freestanding program that uses the `Box` 16 | sugar for dynamic allocations via `malloc` and `free`: 17 | 18 | ```rust,ignore 19 | #![feature(lang_items, box_syntax, start, libc)] 20 | #![no_std] 21 | 22 | extern crate libc; 23 | 24 | extern { 25 | fn abort() -> !; 26 | } 27 | 28 | #[lang = "owned_box"] 29 | pub struct Box<T>(*mut T); 30 | 31 | #[lang = "exchange_malloc"] 32 | unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { 33 | let p = libc::malloc(size as libc::size_t) as *mut u8; 34 | 35 | // malloc failed 36 | if p as usize == 0 { 37 | abort(); 38 | } 39 | 40 | p 41 | } 42 | 43 | #[lang = "exchange_free"] 44 | unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) { 45 | libc::free(ptr as *mut libc::c_void) 46 | } 47 | 48 | #[lang = "box_free"] 49 | unsafe fn box_free<T>(ptr: *mut T) { 50 | deallocate(ptr as *mut u8, ::core::mem::size_of::<T>(), ::core::mem::align_of::<T>()); 51 | } 52 | 53 | #[start] 54 | fn main(argc: isize, argv: *const *const u8) -> isize { 55 | let x = box 1; 56 | 57 | 0 58 | } 59 | 60 | #[lang = "eh_personality"] extern fn eh_personality() {} 61 | #[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } 62 | # #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} 63 | # #[no_mangle] pub extern fn rust_eh_register_frames () {} 64 | # #[no_mangle] pub extern fn rust_eh_unregister_frames () {} 65 | ``` 66 | 67 | Note the use of `abort`: the `exchange_malloc` lang item is assumed to 68 | return a valid pointer, and so needs to do the check internally. 69 | 70 | Other features provided by lang items include: 71 | 72 | - overloadable operators via traits: the traits corresponding to the 73 | `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all 74 | marked with lang items; those specific four are `eq`, `ord`, 75 | `deref`, and `add` respectively. 76 | - stack unwinding and general failure; the `eh_personality`, `fail` 77 | and `fail_bounds_checks` lang items. 78 | - the traits in `std::marker` used to indicate types of 79 | various kinds; lang items `send`, `sync` and `copy`. 80 | - the marker types and variance indicators found in 81 | `std::marker`; lang items `covariant_type`, 82 | `contravariant_lifetime`, etc. 83 | 84 | Lang items are loaded lazily by the compiler; e.g. if one never uses 85 | `Box` then there is no need to define functions for `exchange_malloc` 86 | and `exchange_free`. `rustc` will emit an error when an item is needed 87 | but not found in the current crate or any that it depends on. 88 | -------------------------------------------------------------------------------- /trpl/match.md: -------------------------------------------------------------------------------- 1 | % Match 2 | 3 | Often, a simple [`if`][if]/`else` isn’t enough, because you have more than two 4 | possible options. Also, conditions can get quite complex. Rust 5 | has a keyword, `match`, that allows you to replace complicated `if`/`else` 6 | groupings with something more powerful. Check it out: 7 | 8 | ```rust 9 | let x = 5; 10 | 11 | match x { 12 | 1 => println!("one"), 13 | 2 => println!("two"), 14 | 3 => println!("three"), 15 | 4 => println!("four"), 16 | 5 => println!("five"), 17 | _ => println!("something else"), 18 | } 19 | ``` 20 | 21 | [if]: if.html 22 | 23 | `match` takes an expression and then branches based on its value. Each ‘arm’ of 24 | the branch is of the form `val => expression`. When the value matches, that arm’s 25 | expression will be evaluated. It’s called `match` because of the term ‘pattern 26 | matching’, which `match` is an implementation of. There’s a [separate section on 27 | patterns][patterns] that covers all the patterns that are possible here. 28 | 29 | [patterns]: patterns.html 30 | 31 | One of the many advantages of `match` is it enforces ‘exhaustiveness checking’. 32 | For example if we remove the last arm with the underscore `_`, the compiler will 33 | give us an error: 34 | 35 | ```text 36 | error: non-exhaustive patterns: `_` not covered 37 | ``` 38 | 39 | Rust is telling us that we forgot some value. The compiler infers from `x` that it 40 | can have any 32bit integer value; for example -2,147,483,648 to 2,147,483,647. The `_` acts 41 | as a 'catch-all', and will catch all possible values that *aren't* specified in 42 | an arm of `match`. As you can see in the previous example, we provide `match` 43 | arms for integers 1-5, if `x` is 6 or any other value, then it is caught by `_`. 44 | 45 | `match` is also an expression, which means we can use it on the right-hand 46 | side of a `let` binding or directly where an expression is used: 47 | 48 | ```rust 49 | let x = 5; 50 | 51 | let number = match x { 52 | 1 => "one", 53 | 2 => "two", 54 | 3 => "three", 55 | 4 => "four", 56 | 5 => "five", 57 | _ => "something else", 58 | }; 59 | ``` 60 | 61 | Sometimes it’s a nice way of converting something from one type to another; in 62 | this example the integers are converted to `String`. 63 | 64 | # Matching on enums 65 | 66 | Another important use of the `match` keyword is to process the possible 67 | variants of an enum: 68 | 69 | ```rust 70 | enum Message { 71 | Quit, 72 | ChangeColor(i32, i32, i32), 73 | Move { x: i32, y: i32 }, 74 | Write(String), 75 | } 76 | 77 | fn quit() { /* ... */ } 78 | fn change_color(r: i32, g: i32, b: i32) { /* ... */ } 79 | fn move_cursor(x: i32, y: i32) { /* ... */ } 80 | 81 | fn process_message(msg: Message) { 82 | match msg { 83 | Message::Quit => quit(), 84 | Message::ChangeColor(r, g, b) => change_color(r, g, b), 85 | Message::Move { x: x, y: y } => move_cursor(x, y), 86 | Message::Write(s) => println!("{}", s), 87 | }; 88 | } 89 | ``` 90 | 91 | Again, the Rust compiler checks exhaustiveness, so it demands that you 92 | have a match arm for every variant of the enum. If you leave one off, it 93 | will give you a compile-time error unless you use `_` or provide all possible 94 | arms. 95 | 96 | Unlike the previous uses of `match`, you can’t use the normal `if` 97 | statement to do this. You can use the [`if let`][if-let] statement, 98 | which can be seen as an abbreviated form of `match`. 99 | 100 | [if-let]: if-let.html 101 | -------------------------------------------------------------------------------- /trpl/nightly-rust.md: -------------------------------------------------------------------------------- 1 | % Nightly Rust 2 | 3 | Rust provides three distribution channels for Rust: nightly, beta, and stable. 4 | Unstable features are only available on nightly Rust. For more details on this 5 | process, see ‘[Stability as a deliverable][stability]’. 6 | 7 | [stability]: http://blog.rust-lang.org/2014/10/30/Stability.html 8 | 9 | To install nightly Rust, you can use `rustup.sh`: 10 | 11 | ```bash 12 | $ curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly 13 | ``` 14 | 15 | If you're concerned about the [potential insecurity][insecurity] of using `curl 16 | | sh`, please keep reading and see our disclaimer below. And feel free to 17 | use a two-step version of the installation and examine our installation script: 18 | 19 | ```bash 20 | $ curl -f -L https://static.rust-lang.org/rustup.sh -O 21 | $ sh rustup.sh --channel=nightly 22 | ``` 23 | 24 | [insecurity]: http://curlpipesh.tumblr.com 25 | 26 | If you're on Windows, please download either the [32-bit installer][win32] or 27 | the [64-bit installer][win64] and run it. 28 | 29 | [win32]: https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.msi 30 | [win64]: https://static.rust-lang.org/dist/rust-nightly-x86_64-pc-windows-gnu.msi 31 | 32 | ## Uninstalling 33 | 34 | If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay. 35 | Not every programming language is great for everyone. Just run the uninstall 36 | script: 37 | 38 | ```bash 39 | $ sudo /usr/local/lib/rustlib/uninstall.sh 40 | ``` 41 | 42 | If you used the Windows installer, re-run the `.msi` and it will give you 43 | an uninstall option. 44 | 45 | Some people, and somewhat rightfully so, get very upset when we tell you to 46 | `curl | sh`. Basically, when you do this, you are trusting that the good 47 | people who maintain Rust aren't going to hack your computer and do bad things. 48 | That's a good instinct! If you're one of those people, please check out the 49 | documentation on [building Rust from Source][from-source], or [the official 50 | binary downloads][install-page]. 51 | 52 | [from-source]: https://github.com/rust-lang/rust#building-from-source 53 | [install-page]: https://www.rust-lang.org/install.html 54 | 55 | Oh, we should also mention the officially supported platforms: 56 | 57 | * Windows (7, 8, Server 2008 R2) 58 | * Linux (2.6.18 or later, various distributions), x86 and x86-64 59 | * OSX 10.7 (Lion) or greater, x86 and x86-64 60 | 61 | We extensively test Rust on these platforms, and a few others, too, like 62 | Android. But these are the ones most likely to work, as they have the most 63 | testing. 64 | 65 | Finally, a comment about Windows. Rust considers Windows to be a first-class 66 | platform upon release, but if we're honest, the Windows experience isn't as 67 | integrated as the Linux/OS X experience is. We're working on it! If anything 68 | does not work, it is a bug. Please let us know if that happens. Each and every 69 | commit is tested against Windows like any other platform. 70 | 71 | If you've got Rust installed, you can open up a shell, and type this: 72 | 73 | ```bash 74 | $ rustc --version 75 | ``` 76 | 77 | You should see the version number, commit hash, commit date and build date: 78 | 79 | ```bash 80 | rustc 1.0.0-nightly (f11f3e7ba 2015-01-04) (built 2015-01-06) 81 | ``` 82 | 83 | If you did, Rust has been installed successfully! Congrats! 84 | 85 | This installer also installs a copy of the documentation locally, so you can 86 | read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. 87 | On Windows, it's in a `share/doc` directory, inside wherever you installed Rust 88 | to. 89 | 90 | If not, there are a number of places where you can get help. The easiest is 91 | [the #rust IRC channel on irc.mozilla.org][irc], which you can access through 92 | [Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans 93 | (a silly nickname we call ourselves), and we can help you out. Other great 94 | resources include [the user’s forum][users], and [Stack Overflow][stackoverflow]. 95 | 96 | [irc]: irc://irc.mozilla.org/#rust 97 | [mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust 98 | [users]: https://users.rust-lang.org/ 99 | [stackoverflow]: http://stackoverflow.com/questions/tagged/rust 100 | -------------------------------------------------------------------------------- /trpl/no-stdlib.md: -------------------------------------------------------------------------------- 1 | % No stdlib 2 | 3 | Rust’s standard library provides a lot of useful functionality, but assumes 4 | support for various features of its host system: threads, networking, heap 5 | allocation, and others. There are systems that do not have these features, 6 | however, and Rust can work with those too! To do so, we tell Rust that we 7 | don’t want to use the standard library via an attribute: `#![no_std]`. 8 | 9 | > Note: This feature is technically stable, but there are some caveats. For 10 | > one, you can build a `#![no_std]` _library_ on stable, but not a _binary_. 11 | > For details on libraries without the standard library, see [the chapter on 12 | > `#![no_std]`](using-rust-without-the-standard-library.html) 13 | 14 | Obviously there's more to life than just libraries: one can use 15 | `#[no_std]` with an executable. 16 | 17 | ### Using libc 18 | 19 | In order to build a `#[no_std]` executable we will need libc as a dependency. We can specify 20 | this using our `Cargo.toml` file: 21 | 22 | ```toml 23 | [dependencies] 24 | libc = { version = "0.2.14", default-features = false } 25 | ``` 26 | 27 | Note that the default features have been disabled. This is a critical step - 28 | **the default features of libc include the standard library and so must be 29 | disabled.** 30 | 31 | ### Writing an executable without stdlib 32 | 33 | Controlling the entry point is possible in two ways: the `#[start]` attribute, 34 | or overriding the default shim for the C `main` function with your own. 35 | 36 | The function marked `#[start]` is passed the command line parameters 37 | in the same format as C: 38 | 39 | ```rust,ignore 40 | #![feature(lang_items)] 41 | #![feature(start)] 42 | #![no_std] 43 | 44 | // Pull in the system libc library for what crt0.o likely requires 45 | extern crate libc; 46 | 47 | // Entry point for this program 48 | #[start] 49 | fn start(_argc: isize, _argv: *const *const u8) -> isize { 50 | 0 51 | } 52 | 53 | // These functions are used by the compiler, but not 54 | // for a bare-bones hello world. These are normally 55 | // provided by libstd. 56 | #[lang = "eh_personality"] 57 | #[no_mangle] 58 | pub extern fn eh_personality() { 59 | } 60 | 61 | #[lang = "panic_fmt"] 62 | #[no_mangle] 63 | pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, 64 | _file: &'static str, 65 | _line: u32) -> ! { 66 | loop {} 67 | } 68 | ``` 69 | 70 | To override the compiler-inserted `main` shim, one has to disable it 71 | with `#![no_main]` and then create the appropriate symbol with the 72 | correct ABI and the correct name, which requires overriding the 73 | compiler's name mangling too: 74 | 75 | ```rust,ignore 76 | #![feature(lang_items)] 77 | #![feature(start)] 78 | #![no_std] 79 | #![no_main] 80 | 81 | // Pull in the system libc library for what crt0.o likely requires 82 | extern crate libc; 83 | 84 | // Entry point for this program 85 | #[no_mangle] // ensure that this symbol is called `main` in the output 86 | pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { 87 | 0 88 | } 89 | 90 | // These functions and traits are used by the compiler, but not 91 | // for a bare-bones hello world. These are normally 92 | // provided by libstd. 93 | #[lang = "eh_personality"] 94 | #[no_mangle] 95 | pub extern fn eh_personality() { 96 | } 97 | 98 | #[lang = "panic_fmt"] 99 | #[no_mangle] 100 | pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, 101 | _file: &'static str, 102 | _line: u32) -> ! { 103 | loop {} 104 | } 105 | ``` 106 | 107 | ## More about the langauge items 108 | 109 | The compiler currently makes a few assumptions about symbols which are 110 | available in the executable to call. Normally these functions are provided by 111 | the standard library, but without it you must define your own. These symbols 112 | are called "language items", and they each have an internal name, and then a 113 | signature that an implementation must conform to. 114 | 115 | The first of these two functions, `eh_personality`, is used by the failure 116 | mechanisms of the compiler. This is often mapped to GCC's personality function 117 | (see the [libstd implementation][unwind] for more information), but crates 118 | which do not trigger a panic can be assured that this function is never 119 | called. Both the language item and the symbol name are `eh_personality`. 120 | 121 | [unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs 122 | 123 | The second function, `panic_fmt`, is also used by the failure mechanisms of the 124 | compiler. When a panic happens, this controls the message that's displayed on 125 | the screen. While the language item's name is `panic_fmt`, the symbol name is 126 | `rust_begin_panic`. 127 | -------------------------------------------------------------------------------- /trpl/operators-and-overloading.md: -------------------------------------------------------------------------------- 1 | % Operators and Overloading 2 | 3 | Rust allows for a limited form of operator overloading. There are certain 4 | operators that are able to be overloaded. To support a particular operator 5 | between types, there’s a specific trait that you can implement, which then 6 | overloads the operator. 7 | 8 | For example, the `+` operator can be overloaded with the `Add` trait: 9 | 10 | ```rust 11 | use std::ops::Add; 12 | 13 | #[derive(Debug)] 14 | struct Point { 15 | x: i32, 16 | y: i32, 17 | } 18 | 19 | impl Add for Point { 20 | type Output = Point; 21 | 22 | fn add(self, other: Point) -> Point { 23 | Point { x: self.x + other.x, y: self.y + other.y } 24 | } 25 | } 26 | 27 | fn main() { 28 | let p1 = Point { x: 1, y: 0 }; 29 | let p2 = Point { x: 2, y: 3 }; 30 | 31 | let p3 = p1 + p2; 32 | 33 | println!("{:?}", p3); 34 | } 35 | ``` 36 | 37 | In `main`, we can use `+` on our two `Point`s, since we’ve implemented 38 | `Add<Output=Point>` for `Point`. 39 | 40 | There are a number of operators that can be overloaded this way, and all of 41 | their associated traits live in the [`std::ops`][stdops] module. Check out its 42 | documentation for the full list. 43 | 44 | [stdops]: ../std/ops/index.html 45 | 46 | Implementing these traits follows a pattern. Let’s look at [`Add`][add] in more 47 | detail: 48 | 49 | ```rust 50 | # mod foo { 51 | pub trait Add<RHS = Self> { 52 | type Output; 53 | 54 | fn add(self, rhs: RHS) -> Self::Output; 55 | } 56 | # } 57 | ``` 58 | 59 | [add]: ../std/ops/trait.Add.html 60 | 61 | There’s three types in total involved here: the type you `impl Add` for, `RHS`, 62 | which defaults to `Self`, and `Output`. For an expression `let z = x + y`, `x` 63 | is the `Self` type, `y` is the RHS, and `z` is the `Self::Output` type. 64 | 65 | ```rust 66 | # struct Point; 67 | # use std::ops::Add; 68 | impl Add<i32> for Point { 69 | type Output = f64; 70 | 71 | fn add(self, rhs: i32) -> f64 { 72 | // add an i32 to a Point and get an f64 73 | # 1.0 74 | } 75 | } 76 | ``` 77 | 78 | will let you do this: 79 | 80 | ```rust,ignore 81 | let p: Point = // ... 82 | let x: f64 = p + 2i32; 83 | ``` 84 | 85 | # Using operator traits in generic structs 86 | 87 | Now that we know how operator traits are defined, we can define our `HasArea` 88 | trait and `Square` struct from the [traits chapter][traits] more generically: 89 | 90 | [traits]: traits.html 91 | 92 | ```rust 93 | use std::ops::Mul; 94 | 95 | trait HasArea<T> { 96 | fn area(&self) -> T; 97 | } 98 | 99 | struct Square<T> { 100 | x: T, 101 | y: T, 102 | side: T, 103 | } 104 | 105 | impl<T> HasArea<T> for Square<T> 106 | where T: Mul<Output=T> + Copy { 107 | fn area(&self) -> T { 108 | self.side * self.side 109 | } 110 | } 111 | 112 | fn main() { 113 | let s = Square { 114 | x: 0.0f64, 115 | y: 0.0f64, 116 | side: 12.0f64, 117 | }; 118 | 119 | println!("Area of s: {}", s.area()); 120 | } 121 | ``` 122 | 123 | For `HasArea` and `Square`, we declare a type parameter `T` and replace 124 | `f64` with it. The `impl` needs more involved modifications: 125 | 126 | ```rust,ignore 127 | impl<T> HasArea<T> for Square<T> 128 | where T: Mul<Output=T> + Copy { ... } 129 | ``` 130 | 131 | The `area` method requires that we can multiply the sides, so we declare that 132 | type `T` must implement `std::ops::Mul`. Like `Add`, mentioned above, `Mul` 133 | itself takes an `Output` parameter: since we know that numbers don't change 134 | type when multiplied, we also set it to `T`. `T` must also support copying, so 135 | Rust doesn't try to move `self.side` into the return value. 136 | -------------------------------------------------------------------------------- /trpl/raw-pointers.md: -------------------------------------------------------------------------------- 1 | % Raw Pointers 2 | 3 | Rust has a number of different smart pointer types in its standard library, but 4 | there are two types that are extra-special. Much of Rust’s safety comes from 5 | compile-time checks, but raw pointers don’t have such guarantees, and are 6 | [unsafe][unsafe] to use. 7 | 8 | `*const T` and `*mut T` are called ‘raw pointers’ in Rust. Sometimes, when 9 | writing certain kinds of libraries, you’ll need to get around Rust’s safety 10 | guarantees for some reason. In this case, you can use raw pointers to implement 11 | your library, while exposing a safe interface for your users. For example, `*` 12 | pointers are allowed to alias, allowing them to be used to write 13 | shared-ownership types, and even thread-safe shared memory types (the `Rc<T>` 14 | and `Arc<T>` types are both implemented entirely in Rust). 15 | 16 | Here are some things to remember about raw pointers that are different than 17 | other pointer types. They: 18 | 19 | - are not guaranteed to point to valid memory and are not even 20 | guaranteed to be non-NULL (unlike both `Box` and `&`); 21 | - do not have any automatic clean-up, unlike `Box`, and so require 22 | manual resource management; 23 | - are plain-old-data, that is, they don't move ownership, again unlike 24 | `Box`, hence the Rust compiler cannot protect against bugs like 25 | use-after-free; 26 | - lack any form of lifetimes, unlike `&`, and so the compiler cannot 27 | reason about dangling pointers; and 28 | - have no guarantees about aliasing or mutability other than mutation 29 | not being allowed directly through a `*const T`. 30 | 31 | # Basics 32 | 33 | Creating a raw pointer is perfectly safe: 34 | 35 | ```rust 36 | let x = 5; 37 | let raw = &x as *const i32; 38 | 39 | let mut y = 10; 40 | let raw_mut = &mut y as *mut i32; 41 | ``` 42 | 43 | However, dereferencing one is not. This won’t work: 44 | 45 | ```rust,ignore 46 | let x = 5; 47 | let raw = &x as *const i32; 48 | 49 | println!("raw points at {}", *raw); 50 | ``` 51 | 52 | It gives this error: 53 | 54 | ```text 55 | error: dereference of raw pointer requires unsafe function or block [E0133] 56 | println!("raw points at {}", *raw); 57 | ^~~~ 58 | ``` 59 | 60 | When you dereference a raw pointer, you’re taking responsibility that it’s not 61 | pointing somewhere that would be incorrect. As such, you need `unsafe`: 62 | 63 | ```rust 64 | let x = 5; 65 | let raw = &x as *const i32; 66 | 67 | let points_at = unsafe { *raw }; 68 | 69 | println!("raw points at {}", points_at); 70 | ``` 71 | 72 | For more operations on raw pointers, see [their API documentation][rawapi]. 73 | 74 | [unsafe]: unsafe.html 75 | [rawapi]: ../std/primitive.pointer.html 76 | 77 | # FFI 78 | 79 | Raw pointers are useful for FFI: Rust’s `*const T` and `*mut T` are similar to 80 | C’s `const T*` and `T*`, respectively. For more about this use, consult the 81 | [FFI chapter][ffi]. 82 | 83 | [ffi]: ffi.html 84 | 85 | # References and raw pointers 86 | 87 | At runtime, a raw pointer `*` and a reference pointing to the same piece of 88 | data have an identical representation. In fact, an `&T` reference will 89 | implicitly coerce to an `*const T` raw pointer in safe code and similarly for 90 | the `mut` variants (both coercions can be performed explicitly with, 91 | respectively, `value as *const T` and `value as *mut T`). 92 | 93 | Going the opposite direction, from `*const` to a reference `&`, is not safe. A 94 | `&T` is always valid, and so, at a minimum, the raw pointer `*const T` has to 95 | point to a valid instance of type `T`. Furthermore, the resulting pointer must 96 | satisfy the aliasing and mutability laws of references. The compiler assumes 97 | these properties are true for any references, no matter how they are created, 98 | and so any conversion from raw pointers is asserting that they hold. The 99 | programmer *must* guarantee this. 100 | 101 | The recommended method for the conversion is: 102 | 103 | ```rust 104 | // explicit cast 105 | let i: u32 = 1; 106 | let p_imm: *const u32 = &i as *const u32; 107 | 108 | // implicit coercion 109 | let mut m: u32 = 2; 110 | let p_mut: *mut u32 = &mut m; 111 | 112 | unsafe { 113 | let ref_imm: &u32 = &*p_imm; 114 | let ref_mut: &mut u32 = &mut *p_mut; 115 | } 116 | ``` 117 | 118 | The `&*x` dereferencing style is preferred to using a `transmute`. The latter 119 | is far more powerful than necessary, and the more restricted operation is 120 | harder to use incorrectly; for example, it requires that `x` is a pointer 121 | (unlike `transmute`). 122 | -------------------------------------------------------------------------------- /trpl/release-channels.md: -------------------------------------------------------------------------------- 1 | % Release Channels 2 | 3 | The Rust project uses a concept called ‘release channels’ to manage releases. 4 | It’s important to understand this process to choose which version of Rust 5 | your project should use. 6 | 7 | # Overview 8 | 9 | There are three channels for Rust releases: 10 | 11 | * Nightly 12 | * Beta 13 | * Stable 14 | 15 | New nightly releases are created once a day. Every six weeks, the latest 16 | nightly release is promoted to ‘Beta’. At that point, it will only receive 17 | patches to fix serious errors. Six weeks later, the beta is promoted to 18 | ‘Stable’, and becomes the next release of `1.x`. 19 | 20 | This process happens in parallel. So every six weeks, on the same day, 21 | nightly goes to beta, beta goes to stable. When `1.x` is released, at 22 | the same time, `1.(x + 1)-beta` is released, and the nightly becomes the 23 | first version of `1.(x + 2)-nightly`. 24 | 25 | # Choosing a version 26 | 27 | Generally speaking, unless you have a specific reason, you should be using the 28 | stable release channel. These releases are intended for a general audience. 29 | 30 | However, depending on your interest in Rust, you may choose to use nightly 31 | instead. The basic tradeoff is this: in the nightly channel, you can use 32 | unstable, new Rust features. However, unstable features are subject to change, 33 | and so any new nightly release may break your code. If you use the stable 34 | release, you cannot use experimental features, but the next release of Rust 35 | will not cause significant issues through breaking changes. 36 | 37 | # Helping the ecosystem through CI 38 | 39 | What about beta? We encourage all Rust users who use the stable release channel 40 | to also test against the beta channel in their continuous integration systems. 41 | This will help alert the team in case there’s an accidental regression. 42 | 43 | Additionally, testing against nightly can catch regressions even sooner, and so 44 | if you don’t mind a third build, we’d appreciate testing against all channels. 45 | 46 | As an example, many Rust programmers use [Travis](https://travis-ci.org/) to 47 | test their crates, which is free for open source projects. Travis [supports 48 | Rust directly][travis], and you can use a `.travis.yml` file like this to 49 | test on all channels: 50 | 51 | ```yaml 52 | language: rust 53 | rust: 54 | - nightly 55 | - beta 56 | - stable 57 | 58 | matrix: 59 | allow_failures: 60 | - rust: nightly 61 | ``` 62 | 63 | [travis]: http://docs.travis-ci.com/user/languages/rust/ 64 | 65 | With this configuration, Travis will test all three channels, but if something 66 | breaks on nightly, it won’t fail your build. A similar configuration is 67 | recommended for any CI system, check the documentation of the one you’re 68 | using for more details. 69 | -------------------------------------------------------------------------------- /trpl/slice-patterns.md: -------------------------------------------------------------------------------- 1 | % Slice patterns 2 | 3 | If you want to match against a slice or array, you can use `&` with the 4 | `slice_patterns` feature: 5 | 6 | ```rust 7 | #![feature(slice_patterns)] 8 | 9 | fn main() { 10 | let v = vec!["match_this", "1"]; 11 | 12 | match &v[..] { 13 | &["match_this", second] => println!("The second element is {}", second), 14 | _ => {}, 15 | } 16 | } 17 | ``` 18 | 19 | The `advanced_slice_patterns` gate lets you use `..` to indicate any number of 20 | elements inside a pattern matching a slice. This wildcard can only be used once 21 | for a given array. If there's an identifier before the `..`, the result of the 22 | slice will be bound to that name. For example: 23 | 24 | ```rust 25 | #![feature(advanced_slice_patterns, slice_patterns)] 26 | 27 | fn is_symmetric(list: &[u32]) -> bool { 28 | match list { 29 | &[] | &[_] => true, 30 | &[x, ref inside.., y] if x == y => is_symmetric(inside), 31 | _ => false 32 | } 33 | } 34 | 35 | fn main() { 36 | let sym = &[0, 1, 4, 2, 4, 1, 0]; 37 | assert!(is_symmetric(sym)); 38 | 39 | let not_sym = &[0, 1, 7, 2, 4, 1, 0]; 40 | assert!(!is_symmetric(not_sym)); 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /trpl/syntax-and-semantics.md: -------------------------------------------------------------------------------- 1 | % Syntax and Semantics 2 | 3 | This chapter breaks Rust down into small chunks, one for each concept. 4 | 5 | If you’d like to learn Rust from the bottom up, reading this in order is a 6 | great way to do that. 7 | 8 | These sections also form a reference for each concept, so if you’re reading 9 | another tutorial and find something confusing, you can find it explained 10 | somewhere in here. 11 | -------------------------------------------------------------------------------- /trpl/type-aliases.md: -------------------------------------------------------------------------------- 1 | % `type` Aliases 2 | 3 | The `type` keyword lets you declare an alias of another type: 4 | 5 | ```rust 6 | type Name = String; 7 | ``` 8 | 9 | You can then use this type as if it were a real type: 10 | 11 | ```rust 12 | type Name = String; 13 | 14 | let x: Name = "Hello".to_string(); 15 | ``` 16 | 17 | Note, however, that this is an _alias_, not a new type entirely. In other 18 | words, because Rust is strongly typed, you’d expect a comparison between two 19 | different types to fail: 20 | 21 | ```rust,ignore 22 | let x: i32 = 5; 23 | let y: i64 = 5; 24 | 25 | if x == y { 26 | // ... 27 | } 28 | ``` 29 | 30 | this gives 31 | 32 | ```text 33 | error: mismatched types: 34 | expected `i32`, 35 | found `i64` 36 | (expected i32, 37 | found i64) [E0308] 38 | if x == y { 39 | ^ 40 | ``` 41 | 42 | But, if we had an alias: 43 | 44 | ```rust 45 | type Num = i32; 46 | 47 | let x: i32 = 5; 48 | let y: Num = 5; 49 | 50 | if x == y { 51 | // ... 52 | } 53 | ``` 54 | 55 | This compiles without error. Values of a `Num` type are the same as a value of 56 | type `i32`, in every way. You can use [tuple struct] to really get a new type. 57 | 58 | [tuple struct]: structs.html#tuple-structs 59 | 60 | You can also use type aliases with generics: 61 | 62 | ```rust 63 | use std::result; 64 | 65 | enum ConcreteError { 66 | Foo, 67 | Bar, 68 | } 69 | 70 | type Result<T> = result::Result<T, ConcreteError>; 71 | ``` 72 | 73 | This creates a specialized version of the `Result` type, which always has a 74 | `ConcreteError` for the `E` part of `Result<T, E>`. This is commonly used 75 | in the standard library to create custom errors for each subsection. For 76 | example, [io::Result][ioresult]. 77 | 78 | [ioresult]: ../std/io/type.Result.html 79 | -------------------------------------------------------------------------------- /trpl/ufcs.md: -------------------------------------------------------------------------------- 1 | % Universal Function Call Syntax 2 | 3 | Sometimes, functions can have the same names. Consider this code: 4 | 5 | ```rust 6 | trait Foo { 7 | fn f(&self); 8 | } 9 | 10 | trait Bar { 11 | fn f(&self); 12 | } 13 | 14 | struct Baz; 15 | 16 | impl Foo for Baz { 17 | fn f(&self) { println!("Baz’s impl of Foo"); } 18 | } 19 | 20 | impl Bar for Baz { 21 | fn f(&self) { println!("Baz’s impl of Bar"); } 22 | } 23 | 24 | let b = Baz; 25 | ``` 26 | 27 | If we were to try to call `b.f()`, we’d get an error: 28 | 29 | ```text 30 | error: multiple applicable methods in scope [E0034] 31 | b.f(); 32 | ^~~ 33 | note: candidate #1 is defined in an impl of the trait `main::Foo` for the type 34 | `main::Baz` 35 | fn f(&self) { println!("Baz’s impl of Foo"); } 36 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 37 | note: candidate #2 is defined in an impl of the trait `main::Bar` for the type 38 | `main::Baz` 39 | fn f(&self) { println!("Baz’s impl of Bar"); } 40 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 | 42 | ``` 43 | 44 | We need a way to disambiguate which method we need. This feature is called 45 | ‘universal function call syntax’, and it looks like this: 46 | 47 | ```rust 48 | # trait Foo { 49 | # fn f(&self); 50 | # } 51 | # trait Bar { 52 | # fn f(&self); 53 | # } 54 | # struct Baz; 55 | # impl Foo for Baz { 56 | # fn f(&self) { println!("Baz’s impl of Foo"); } 57 | # } 58 | # impl Bar for Baz { 59 | # fn f(&self) { println!("Baz’s impl of Bar"); } 60 | # } 61 | # let b = Baz; 62 | Foo::f(&b); 63 | Bar::f(&b); 64 | ``` 65 | 66 | Let’s break it down. 67 | 68 | ```rust,ignore 69 | Foo:: 70 | Bar:: 71 | ``` 72 | 73 | These halves of the invocation are the types of the two traits: `Foo` and 74 | `Bar`. This is what ends up actually doing the disambiguation between the two: 75 | Rust calls the one from the trait name you use. 76 | 77 | ```rust,ignore 78 | f(&b) 79 | ``` 80 | 81 | When we call a method like `b.f()` using [method syntax][methodsyntax], Rust 82 | will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will 83 | not, and so we need to pass an explicit `&b`. 84 | 85 | [methodsyntax]: method-syntax.html 86 | 87 | # Angle-bracket Form 88 | 89 | The form of UFCS we just talked about: 90 | 91 | ```rust,ignore 92 | Trait::method(args); 93 | ``` 94 | 95 | Is a short-hand. There’s an expanded form of this that’s needed in some 96 | situations: 97 | 98 | ```rust,ignore 99 | <Type as Trait>::method(args); 100 | ``` 101 | 102 | The `<>::` syntax is a means of providing a type hint. The type goes inside 103 | the `<>`s. In this case, the type is `Type as Trait`, indicating that we want 104 | `Trait`’s version of `method` to be called here. The `as Trait` part is 105 | optional if it’s not ambiguous. Same with the angle brackets, hence the 106 | shorter form. 107 | 108 | Here’s an example of using the longer form. 109 | 110 | ```rust 111 | trait Foo { 112 | fn foo() -> i32; 113 | } 114 | 115 | struct Bar; 116 | 117 | impl Bar { 118 | fn foo() -> i32 { 119 | 20 120 | } 121 | } 122 | 123 | impl Foo for Bar { 124 | fn foo() -> i32 { 125 | 10 126 | } 127 | } 128 | 129 | fn main() { 130 | assert_eq!(10, <Bar as Foo>::foo()); 131 | assert_eq!(20, Bar::foo()); 132 | } 133 | ``` 134 | 135 | Using the angle bracket syntax lets you call the trait method instead of the 136 | inherent one. 137 | -------------------------------------------------------------------------------- /trpl/unsized-types.md: -------------------------------------------------------------------------------- 1 | % Unsized Types 2 | 3 | Most types have a particular size, in bytes, that is knowable at compile time. 4 | For example, an `i32` is thirty-two bits big, or four bytes. However, there are 5 | some types which are useful to express, but do not have a defined size. These are 6 | called ‘unsized’ or ‘dynamically sized’ types. One example is `[T]`. This type 7 | represents a certain number of `T` in sequence. But we don’t know how many 8 | there are, so the size is not known. 9 | 10 | Rust understands a few of these types, but they have some restrictions. There 11 | are three: 12 | 13 | 1. We can only manipulate an instance of an unsized type via a pointer. An 14 | `&[T]` works fine, but a `[T]` does not. 15 | 2. Variables and arguments cannot have dynamically sized types. 16 | 3. Only the last field in a `struct` may have a dynamically sized type; the 17 | other fields must not. Enum variants must not have dynamically sized types as 18 | data. 19 | 20 | So why bother? Well, because `[T]` can only be used behind a pointer, if we 21 | didn’t have language support for unsized types, it would be impossible to write 22 | this: 23 | 24 | ```rust,ignore 25 | impl Foo for str { 26 | ``` 27 | 28 | or 29 | 30 | ```rust,ignore 31 | impl<T> Foo for [T] { 32 | ``` 33 | 34 | Instead, you would have to write: 35 | 36 | ```rust,ignore 37 | impl Foo for &str { 38 | ``` 39 | 40 | Meaning, this implementation would only work for [references][ref], and not 41 | other types of pointers. With the `impl for str`, all pointers, including (at 42 | some point, there are some bugs to fix first) user-defined custom smart 43 | pointers, can use this `impl`. 44 | 45 | [ref]: references-and-borrowing.html 46 | 47 | # ?Sized 48 | 49 | If you want to write a function that accepts a dynamically sized type, you 50 | can use the special bound syntax, `?Sized`: 51 | 52 | ```rust 53 | struct Foo<T: ?Sized> { 54 | f: T, 55 | } 56 | ``` 57 | 58 | This `?Sized`, read as “T may or may not be `Sized`”, which allows us to match 59 | both sized and unsized types. All generic type parameters implicitly 60 | have the `Sized` bound, so the `?Sized` can be used to opt-out of the implicit 61 | bound. 62 | -------------------------------------------------------------------------------- /trpl/using-rust-without-the-standard-library.md: -------------------------------------------------------------------------------- 1 | % Using Rust Without the Standard Library 2 | 3 | Rust’s standard library provides a lot of useful functionality, but assumes 4 | support for various features of its host system: threads, networking, heap 5 | allocation, and others. There are systems that do not have these features, 6 | however, and Rust can work with those too! To do so, we tell Rust that we 7 | don’t want to use the standard library via an attribute: `#![no_std]`. 8 | 9 | > Note: This feature is technically stable, but there are some caveats. For 10 | > one, you can build a `#![no_std]` _library_ on stable, but not a _binary_. 11 | > For details on binaries without the standard library, see [the nightly 12 | > chapter on `#![no_std]`](no-stdlib.html) 13 | 14 | To use `#![no_std]`, add it to your crate root: 15 | 16 | ```rust 17 | #![no_std] 18 | 19 | fn plus_one(x: i32) -> i32 { 20 | x + 1 21 | } 22 | ``` 23 | 24 | Much of the functionality that’s exposed in the standard library is also 25 | available via the [`core` crate](../core/index.html). When we’re using the 26 | standard library, Rust automatically brings `std` into scope, allowing you to 27 | use its features without an explicit import. By the same token, when using 28 | `#![no_std]`, Rust will bring `core` into scope for you, as well as [its 29 | prelude](../core/prelude/v1/index.html). This means that a lot of code will Just 30 | Work: 31 | 32 | ```rust 33 | #![no_std] 34 | 35 | fn may_fail(failure: bool) -> Result<(), &'static str> { 36 | if failure { 37 | Err("this didn’t work!") 38 | } else { 39 | Ok(()) 40 | } 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /trpl/vectors.md: -------------------------------------------------------------------------------- 1 | % Vectors 2 | 3 | A ‘vector’ is a dynamic or ‘growable’ array, implemented as the standard 4 | library type [`Vec<T>`][vec]. The `T` means that we can have vectors 5 | of any type (see the chapter on [generics][generic] for more). 6 | Vectors always allocate their data on the heap. 7 | You can create them with the `vec!` macro: 8 | 9 | ```rust 10 | let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32> 11 | ``` 12 | 13 | (Notice that unlike the `println!` macro we’ve used in the past, we use square 14 | brackets `[]` with `vec!` macro. Rust allows you to use either in either 15 | situation, this is just convention.) 16 | 17 | There’s an alternate form of `vec!` for repeating an initial value: 18 | 19 | ```rust 20 | let v = vec![0; 10]; // ten zeroes 21 | ``` 22 | 23 | Vectors store their contents as contiguous arrays of `T` on the heap. This means 24 | that they must be able to know the size of `T` at compile time (that is, how 25 | many bytes are needed to store a `T`?). The size of some things can't be known 26 | at compile time. For these you'll have to store a pointer to that thing: 27 | thankfully, the [`Box`][box] type works perfectly for this. 28 | 29 | ## Accessing elements 30 | 31 | To get the value at a particular index in the vector, we use `[]`s: 32 | 33 | ```rust 34 | let v = vec![1, 2, 3, 4, 5]; 35 | 36 | println!("The third element of v is {}", v[2]); 37 | ``` 38 | 39 | The indices count from `0`, so the third element is `v[2]`. 40 | 41 | It’s also important to note that you must index with the `usize` type: 42 | 43 | ```rust,ignore 44 | let v = vec![1, 2, 3, 4, 5]; 45 | 46 | let i: usize = 0; 47 | let j: i32 = 0; 48 | 49 | // works 50 | v[i]; 51 | 52 | // doesn’t 53 | v[j]; 54 | ``` 55 | 56 | Indexing with a non-`usize` type gives an error that looks like this: 57 | 58 | ```text 59 | error: the trait bound `collections::vec::Vec<_> : core::ops::Index<i32>` 60 | is not satisfied [E0277] 61 | v[j]; 62 | ^~~~ 63 | note: the type `collections::vec::Vec<_>` cannot be indexed by `i32` 64 | error: aborting due to previous error 65 | ``` 66 | 67 | There’s a lot of punctuation in that message, but the core of it makes sense: 68 | you cannot index with an `i32`. 69 | 70 | ## Out-of-bounds Access 71 | 72 | If you try to access an index that doesn’t exist: 73 | 74 | ```rust,ignore 75 | let v = vec![1, 2, 3]; 76 | println!("Item 7 is {}", v[7]); 77 | ``` 78 | 79 | then the current thread will [panic] with a message like this: 80 | 81 | ```text 82 | thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 7' 83 | ``` 84 | 85 | If you want to handle out-of-bounds errors without panicking, you can use 86 | methods like [`get`][get] or [`get_mut`][get_mut] that return `None` when 87 | given an invalid index: 88 | 89 | ```rust 90 | let v = vec![1, 2, 3]; 91 | match v.get(7) { 92 | Some(x) => println!("Item 7 is {}", x), 93 | None => println!("Sorry, this vector is too short.") 94 | } 95 | ``` 96 | 97 | ## Iterating 98 | 99 | Once you have a vector, you can iterate through its elements with `for`. There 100 | are three versions: 101 | 102 | ```rust 103 | let mut v = vec![1, 2, 3, 4, 5]; 104 | 105 | for i in &v { 106 | println!("A reference to {}", i); 107 | } 108 | 109 | for i in &mut v { 110 | println!("A mutable reference to {}", i); 111 | } 112 | 113 | for i in v { 114 | println!("Take ownership of the vector and its element {}", i); 115 | } 116 | ``` 117 | 118 | Note: You cannot use the vector again once you have iterated by taking ownership of the vector. 119 | You can iterate the vector multiple times by taking a reference to the vector whilst iterating. 120 | For example, the following code does not compile. 121 | 122 | ```rust,ignore 123 | let v = vec![1, 2, 3, 4, 5]; 124 | 125 | for i in v { 126 | println!("Take ownership of the vector and its element {}", i); 127 | } 128 | 129 | for i in v { 130 | println!("Take ownership of the vector and its element {}", i); 131 | } 132 | ``` 133 | 134 | Whereas the following works perfectly, 135 | 136 | ```rust 137 | let v = vec![1, 2, 3, 4, 5]; 138 | 139 | for i in &v { 140 | println!("This is a reference to {}", i); 141 | } 142 | 143 | for i in &v { 144 | println!("This is a reference to {}", i); 145 | } 146 | ``` 147 | 148 | Vectors have many more useful methods, which you can read about in [their 149 | API documentation][vec]. 150 | 151 | [vec]: ../std/vec/index.html 152 | [box]: ../std/boxed/index.html 153 | [generic]: generics.html 154 | [panic]: concurrency.html#panics 155 | [get]: ../std/vec/struct.Vec.html#method.get 156 | [get_mut]: ../std/vec/struct.Vec.html#method.get_mut 157 | -------------------------------------------------------------------------------- /trpl_meta.yml: -------------------------------------------------------------------------------- 1 | --- 2 | title: "The Rust Programming Language" 3 | author: "The Rust Team" 4 | date: {release_date} 5 | description: "This book will teach you about the Rust Programming Language. Rust is a modern systems programming language focusing on safety and speed. It accomplishes these goals by being memory safe without using garbage collection." 6 | language: en 7 | documentclass: book 8 | links-as-notes: true 9 | verbatim-in-note: true 10 | toc-depth: 2 11 | monofont: "DejaVu Sans Mono" 12 | ... 13 | --------------------------------------------------------------------------------